更新game HUD 界面
This commit is contained in:
@@ -132,6 +132,13 @@ public static class UIBuilder
|
||||
[MenuItem("Tools/搭建 HUD Canvas")]
|
||||
public static void BuildHUD()
|
||||
{
|
||||
// 加载 HUD 美术资源(可选,没有则用占位)
|
||||
var soulIconSprite = AssetDatabase.LoadAssetAtPath<Sprite>("Assets/UI/Art/HUD/soul_icon.png");
|
||||
var lifeIconSprite = AssetDatabase.LoadAssetAtPath<Sprite>("Assets/UI/Art/HUD/life_icon.png");
|
||||
var sprintIconSprite = AssetDatabase.LoadAssetAtPath<Sprite>("Assets/UI/Art/HUD/skill_sprint.png");
|
||||
var bellIconSprite = AssetDatabase.LoadAssetAtPath<Sprite>("Assets/UI/Art/HUD/skill_bell.png");
|
||||
var lanternIconSprite = AssetDatabase.LoadAssetAtPath<Sprite>("Assets/UI/Art/HUD/skill_lantern.png");
|
||||
|
||||
// 创建 HUD Canvas
|
||||
var hudCanvasObj = new GameObject("HUD_Canvas");
|
||||
var canvas = hudCanvasObj.AddComponent<Canvas>();
|
||||
@@ -143,104 +150,89 @@ public static class UIBuilder
|
||||
|
||||
// 添加 GameHUD 脚本
|
||||
var hud = hudCanvasObj.AddComponent<GameHUD>();
|
||||
var so = new SerializedObject(hud);
|
||||
|
||||
// ===== 左上角:血量区域 =====
|
||||
var healthArea = CreateChild(hudCanvasObj, "HealthArea", new Vector2(20, -20));
|
||||
var healthLayout = healthArea.AddComponent<VerticalLayoutGroup>();
|
||||
healthLayout.spacing = 5;
|
||||
healthLayout.childForceExpandWidth = false;
|
||||
healthLayout.childForceExpandHeight = false;
|
||||
healthArea.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
// ===== 左上角:魂灵计数 =====
|
||||
var soulArea = CreateChild(hudCanvasObj, "SoulArea", new Vector2(20, -20));
|
||||
var soulLayout = soulArea.AddComponent<HorizontalLayoutGroup>();
|
||||
soulLayout.spacing = 8;
|
||||
soulLayout.childForceExpandWidth = false;
|
||||
soulLayout.childForceExpandHeight = true;
|
||||
soulLayout.childAlignment = TextAnchor.MiddleLeft;
|
||||
soulArea.AddComponent<ContentSizeFitter>().horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
|
||||
// 血量 Slider
|
||||
var sliderObj = new GameObject("HealthSlider");
|
||||
sliderObj.transform.SetParent(healthArea.transform, false);
|
||||
var slider = sliderObj.AddComponent<Slider>();
|
||||
slider.minValue = 0;
|
||||
slider.maxValue = 1;
|
||||
slider.value = 1;
|
||||
slider.interactable = false;
|
||||
var sliderRect = sliderObj.GetComponent<RectTransform>();
|
||||
sliderRect.sizeDelta = new Vector2(200, 20);
|
||||
// 魂灵 Icon
|
||||
var soulIconObj = CreateIcon(soulArea.transform, "SoulIcon", soulIconSprite, new Vector2(40, 40), Color.cyan);
|
||||
so.FindProperty("soulIcon").objectReferenceValue = soulIconObj.GetComponent<Image>();
|
||||
|
||||
// Slider 背景
|
||||
var sliderBg = new GameObject("Background");
|
||||
sliderBg.transform.SetParent(sliderObj.transform, false);
|
||||
var bgImage = sliderBg.AddComponent<Image>();
|
||||
bgImage.color = new Color(0.2f, 0.2f, 0.2f, 0.8f);
|
||||
var bgRect = sliderBg.GetComponent<RectTransform>();
|
||||
bgRect.anchorMin = Vector2.zero;
|
||||
bgRect.anchorMax = Vector2.one;
|
||||
bgRect.sizeDelta = Vector2.zero;
|
||||
// 魂灵数字
|
||||
var soulCountObj = CreateText(soulArea.transform, "SoulCount", "0", 28, TextAnchor.MiddleLeft);
|
||||
soulCountObj.GetComponent<Text>().fontStyle = FontStyle.Bold;
|
||||
soulCountObj.GetComponent<RectTransform>().sizeDelta = new Vector2(60, 40);
|
||||
so.FindProperty("soulCountText").objectReferenceValue = soulCountObj.GetComponent<Text>();
|
||||
|
||||
// Slider 填充区域
|
||||
var fillArea = new GameObject("Fill Area");
|
||||
fillArea.transform.SetParent(sliderObj.transform, false);
|
||||
var fillAreaRect = fillArea.AddComponent<RectTransform>();
|
||||
fillAreaRect.anchorMin = new Vector2(0, 0);
|
||||
fillAreaRect.anchorMax = new Vector2(1, 1);
|
||||
fillAreaRect.sizeDelta = Vector2.zero;
|
||||
// ===== 左下角:生命图标(5个) =====
|
||||
var lifeArea = CreateChild(hudCanvasObj, "LifeArea", new Vector2(20, -20));
|
||||
var lifeAreaRect = lifeArea.GetComponent<RectTransform>();
|
||||
lifeAreaRect.anchorMin = new Vector2(0, 0);
|
||||
lifeAreaRect.anchorMax = new Vector2(0, 0);
|
||||
lifeAreaRect.pivot = new Vector2(0, 0);
|
||||
lifeAreaRect.anchoredPosition = new Vector2(20, 20);
|
||||
|
||||
var fill = new GameObject("Fill");
|
||||
fill.transform.SetParent(fillArea.transform, false);
|
||||
var fillImage = fill.AddComponent<Image>();
|
||||
fillImage.color = new Color(0.8f, 0.1f, 0.1f, 0.9f);
|
||||
var fillRect = fill.GetComponent<RectTransform>();
|
||||
fillRect.anchorMin = Vector2.zero;
|
||||
fillRect.anchorMax = Vector2.one;
|
||||
fillRect.sizeDelta = Vector2.zero;
|
||||
var lifeLayout = lifeArea.AddComponent<HorizontalLayoutGroup>();
|
||||
lifeLayout.spacing = 5;
|
||||
lifeLayout.childForceExpandWidth = false;
|
||||
lifeLayout.childForceExpandHeight = true;
|
||||
lifeLayout.childAlignment = TextAnchor.LowerLeft;
|
||||
|
||||
slider.fillRect = fillRect;
|
||||
var lifeIconsProp = so.FindProperty("lifeIcons");
|
||||
lifeIconsProp.arraySize = 5;
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
var lifeIconObj = CreateIcon(lifeArea.transform, $"LifeIcon_{i}", lifeIconSprite, new Vector2(36, 36), Color.red);
|
||||
lifeIconsProp.GetArrayElementAtIndex(i).objectReferenceValue = lifeIconObj.GetComponent<Image>();
|
||||
}
|
||||
|
||||
// 血量文字
|
||||
var healthTextObj = CreateText(healthArea.transform, "HealthText", "100/100", 14, TextAnchor.MiddleLeft);
|
||||
healthTextObj.GetComponent<RectTransform>().sizeDelta = new Vector2(200, 20);
|
||||
// ===== 右下角:技能图标(冲刺/摇铃/灵灯) =====
|
||||
var skillArea = CreateChild(hudCanvasObj, "SkillArea", new Vector2(-20, -20));
|
||||
var skillAreaRect = skillArea.GetComponent<RectTransform>();
|
||||
skillAreaRect.anchorMin = new Vector2(1, 0);
|
||||
skillAreaRect.anchorMax = new Vector2(1, 0);
|
||||
skillAreaRect.pivot = new Vector2(1, 0);
|
||||
skillAreaRect.anchoredPosition = new Vector2(-20, 20);
|
||||
|
||||
// ===== 左上角下方:灵灯区域 =====
|
||||
var lanternArea = CreateChild(hudCanvasObj, "LanternArea", new Vector2(20, -80));
|
||||
var lanternLayout = lanternArea.AddComponent<VerticalLayoutGroup>();
|
||||
lanternLayout.spacing = 3;
|
||||
lanternLayout.childForceExpandWidth = false;
|
||||
lanternLayout.childForceExpandHeight = false;
|
||||
lanternArea.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
var skillLayout = skillArea.AddComponent<HorizontalLayoutGroup>();
|
||||
skillLayout.spacing = 12;
|
||||
skillLayout.childForceExpandWidth = false;
|
||||
skillLayout.childForceExpandHeight = true;
|
||||
skillLayout.childAlignment = TextAnchor.LowerRight;
|
||||
|
||||
var lanternCountObj = CreateText(lanternArea.transform, "LanternCount", "灵灯: 5", 16, TextAnchor.MiddleLeft);
|
||||
lanternCountObj.GetComponent<RectTransform>().sizeDelta = new Vector2(200, 24);
|
||||
// 冲刺技能
|
||||
var sprintObj = CreateSkillIcon(skillArea.transform, "SkillSprint", sprintIconSprite, new Color(0.3f, 0.8f, 1f));
|
||||
so.FindProperty("skillSprintIcon").objectReferenceValue = sprintObj.transform.Find("Icon").GetComponent<Image>();
|
||||
so.FindProperty("skillSprintCD").objectReferenceValue = sprintObj.transform.Find("CDOverlay").GetComponent<Image>();
|
||||
|
||||
var lanternCDObj = CreateText(lanternArea.transform, "LanternCD", "就绪", 14, TextAnchor.MiddleLeft);
|
||||
lanternCDObj.GetComponent<RectTransform>().sizeDelta = new Vector2(200, 20);
|
||||
// 摇铃技能
|
||||
var bellObj = CreateSkillIcon(skillArea.transform, "SkillBell", bellIconSprite, new Color(1f, 0.85f, 0.2f));
|
||||
so.FindProperty("skillBellIcon").objectReferenceValue = bellObj.transform.Find("Icon").GetComponent<Image>();
|
||||
so.FindProperty("skillBellCD").objectReferenceValue = bellObj.transform.Find("CDOverlay").GetComponent<Image>();
|
||||
|
||||
// ===== 右上角:分数 + 暂停 =====
|
||||
// 灵灯技能
|
||||
var lanternObj = CreateSkillIcon(skillArea.transform, "SkillLantern", lanternIconSprite, new Color(1f, 0.6f, 0.2f));
|
||||
so.FindProperty("skillLanternIcon").objectReferenceValue = lanternObj.transform.Find("Icon").GetComponent<Image>();
|
||||
so.FindProperty("skillLanternCD").objectReferenceValue = lanternObj.transform.Find("CDOverlay").GetComponent<Image>();
|
||||
|
||||
// ===== 右上角:暂停按钮 =====
|
||||
var topRight = CreateChild(hudCanvasObj, "TopRight", new Vector2(-20, -20));
|
||||
var topRightRect = topRight.GetComponent<RectTransform>();
|
||||
topRightRect.anchorMin = new Vector2(1, 1);
|
||||
topRightRect.anchorMax = new Vector2(1, 1);
|
||||
topRightRect.pivot = new Vector2(1, 1);
|
||||
|
||||
var topRightLayout = topRight.AddComponent<VerticalLayoutGroup>();
|
||||
topRightLayout.spacing = 8;
|
||||
topRightLayout.childForceExpandWidth = false;
|
||||
topRightLayout.childForceExpandHeight = false;
|
||||
topRightLayout.childAlignment = TextAnchor.UpperRight;
|
||||
topRight.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
|
||||
var scoreObj = CreateText(topRight.transform, "ScoreText", "分数: 0", 20, TextAnchor.MiddleRight);
|
||||
scoreObj.GetComponent<RectTransform>().sizeDelta = new Vector2(200, 30);
|
||||
|
||||
// 暂停按钮
|
||||
var pauseObj = CreateButton(topRight.transform, "PauseButton", "暂停", new Vector2(100, 35));
|
||||
|
||||
// ===== 连接 GameHUD 引用 =====
|
||||
var so = new SerializedObject(hud);
|
||||
so.FindProperty("healthSlider").objectReferenceValue = slider;
|
||||
so.FindProperty("healthText").objectReferenceValue = healthTextObj.GetComponent<Text>();
|
||||
so.FindProperty("lanternCountText").objectReferenceValue = lanternCountObj.GetComponent<Text>();
|
||||
so.FindProperty("lanternCDText").objectReferenceValue = lanternCDObj.GetComponent<Text>();
|
||||
so.FindProperty("scoreText").objectReferenceValue = scoreObj.GetComponent<Text>();
|
||||
var pauseObj = CreateButton(topRight.transform, "PauseButton", "||", new Vector2(50, 50));
|
||||
so.FindProperty("pauseButton").objectReferenceValue = pauseObj.GetComponent<Button>();
|
||||
so.ApplyModifiedProperties();
|
||||
|
||||
Debug.Log("[UIBuilder] HUD Canvas 搭建完成");
|
||||
so.ApplyModifiedProperties();
|
||||
Debug.Log("[UIBuilder] HUD Canvas 搭建完成(魂灵+生命+技能CD)");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -361,6 +353,76 @@ public static class UIBuilder
|
||||
return btnObj;
|
||||
}
|
||||
|
||||
private static GameObject CreateIcon(Transform parent, string name, Sprite sprite, Vector2 size, Color placeholderColor)
|
||||
{
|
||||
var obj = new GameObject(name);
|
||||
obj.transform.SetParent(parent, false);
|
||||
obj.AddComponent<RectTransform>().sizeDelta = size;
|
||||
var img = obj.AddComponent<Image>();
|
||||
if (sprite != null)
|
||||
{
|
||||
img.sprite = sprite;
|
||||
img.preserveAspect = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
img.color = placeholderColor; // 占位色
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
private static GameObject CreateSkillIcon(Transform parent, string name, Sprite sprite, Color cdColor)
|
||||
{
|
||||
var container = new GameObject(name);
|
||||
container.transform.SetParent(parent, false);
|
||||
container.AddComponent<RectTransform>().sizeDelta = new Vector2(56, 56);
|
||||
|
||||
// 背景
|
||||
var bgObj = new GameObject("BG");
|
||||
bgObj.transform.SetParent(container.transform, false);
|
||||
var bgRect = bgObj.AddComponent<RectTransform>();
|
||||
bgRect.anchorMin = Vector2.zero;
|
||||
bgRect.anchorMax = Vector2.one;
|
||||
bgRect.sizeDelta = Vector2.zero;
|
||||
var bgImg = bgObj.AddComponent<Image>();
|
||||
bgImg.color = new Color(0.1f, 0.1f, 0.1f, 0.7f);
|
||||
|
||||
// 技能图标
|
||||
var iconObj = new GameObject("Icon");
|
||||
iconObj.transform.SetParent(container.transform, false);
|
||||
var iconRect = iconObj.AddComponent<RectTransform>();
|
||||
iconRect.anchorMin = new Vector2(0.1f, 0.1f);
|
||||
iconRect.anchorMax = new Vector2(0.9f, 0.9f);
|
||||
iconRect.sizeDelta = Vector2.zero;
|
||||
var iconImg = iconObj.AddComponent<Image>();
|
||||
if (sprite != null)
|
||||
{
|
||||
iconImg.sprite = sprite;
|
||||
iconImg.preserveAspect = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
iconImg.color = cdColor; // 占位色
|
||||
}
|
||||
|
||||
// CD 遮罩(覆盖在图标上方)
|
||||
var cdObj = new GameObject("CDOverlay");
|
||||
cdObj.transform.SetParent(container.transform, false);
|
||||
var cdRect = cdObj.AddComponent<RectTransform>();
|
||||
cdRect.anchorMin = Vector2.zero;
|
||||
cdRect.anchorMax = Vector2.one;
|
||||
cdRect.sizeDelta = Vector2.zero;
|
||||
var cdImg = cdObj.AddComponent<Image>();
|
||||
cdImg.color = new Color(0, 0, 0, 0.6f);
|
||||
cdImg.type = Image.Type.Filled;
|
||||
cdImg.fillMethod = Image.FillMethod.Radial360;
|
||||
cdImg.fillOrigin = 2; // Top
|
||||
cdImg.fillAmount = 0f;
|
||||
cdObj.SetActive(false); // 初始无 CD
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
private static GameObject CreateImageButton(Transform parent, string name, Sprite sprite)
|
||||
{
|
||||
var btnObj = new GameObject(name);
|
||||
|
||||
Reference in New Issue
Block a user