Files
gold_dolphin/unity/Assets/Editor/UIBuilder.cs
T

269 lines
13 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using UnityEngine;
using UnityEditor;
using UnityEngine.UI;
using GameFramework;
/// <summary>
/// 一键搭建游戏 UIHUD Canvas + 游戏结果 Canvas + 主菜单标题。
/// 菜单路径:Tools > 搭建游戏UI
/// </summary>
public static class UIBuilder
{
[MenuItem("Tools/搭建游戏UI (HUD + ResultScreen + MainMenu标题)")]
public static void BuildAll()
{
BuildHUD();
BuildResultScreen();
Debug.Log("[UIBuilder] 全部 UI 搭建完成!请在 Inspector 中检查引用是否正确。");
}
/// <summary>
/// 在 Gameplay 场景中搭建 HUD Canvas。
/// </summary>
[MenuItem("Tools/搭建 HUD Canvas")]
public static void BuildHUD()
{
// 创建 HUD Canvas
var hudCanvasObj = new GameObject("HUD_Canvas");
var canvas = hudCanvasObj.AddComponent<Canvas>();
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
canvas.sortingOrder = 10001;
hudCanvasObj.AddComponent<CanvasScaler>().uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
hudCanvasObj.GetComponent<CanvasScaler>().referenceResolution = new Vector2(1920, 1080);
hudCanvasObj.AddComponent<GraphicRaycaster>();
// 添加 GameHUD 脚本
var hud = hudCanvasObj.AddComponent<GameHUD>();
// ===== 左上角:血量区域 =====
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;
// 血量 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);
// 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;
// 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;
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;
slider.fillRect = fillRect;
// 血量文字
var healthTextObj = CreateText(healthArea.transform, "HealthText", "100/100", 14, TextAnchor.MiddleLeft);
healthTextObj.GetComponent<RectTransform>().sizeDelta = new Vector2(200, 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 lanternCountObj = CreateText(lanternArea.transform, "LanternCount", "灵灯: 5", 16, TextAnchor.MiddleLeft);
lanternCountObj.GetComponent<RectTransform>().sizeDelta = new Vector2(200, 24);
var lanternCDObj = CreateText(lanternArea.transform, "LanternCD", "就绪", 14, TextAnchor.MiddleLeft);
lanternCDObj.GetComponent<RectTransform>().sizeDelta = new Vector2(200, 20);
// ===== 右上角:分数 + 暂停 =====
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>();
so.FindProperty("pauseButton").objectReferenceValue = pauseObj.GetComponent<Button>();
so.ApplyModifiedProperties();
Debug.Log("[UIBuilder] HUD Canvas 搭建完成");
}
/// <summary>
/// 在 Gameplay 场景中搭建游戏结果 Canvas。
/// </summary>
[MenuItem("Tools/搭建 ResultScreen Canvas")]
public static void BuildResultScreen()
{
// 创建 Result Canvas
var resultCanvasObj = new GameObject("ResultScreen_Canvas");
var canvas = resultCanvasObj.AddComponent<Canvas>();
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
canvas.sortingOrder = 10002;
resultCanvasObj.AddComponent<CanvasScaler>().uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
resultCanvasObj.GetComponent<CanvasScaler>().referenceResolution = new Vector2(1920, 1080);
resultCanvasObj.AddComponent<GraphicRaycaster>();
// 添加 GameResultScreen 脚本
var resultScreen = resultCanvasObj.AddComponent<GameResultScreen>();
// 半透明黑色背景
var bgObj = new GameObject("Overlay");
bgObj.transform.SetParent(resultCanvasObj.transform, false);
var bgImage = bgObj.AddComponent<Image>();
bgImage.color = new Color(0, 0, 0, 0.7f);
var bgRect = bgObj.GetComponent<RectTransform>();
bgRect.anchorMin = Vector2.zero;
bgRect.anchorMax = Vector2.one;
bgRect.sizeDelta = Vector2.zero;
// ===== 胜利面板 =====
var winPanel = CreateCenterPanel(resultCanvasObj, "WinPanel", new Color(0.1f, 0.3f, 0.1f, 0.9f));
var winTitle = CreateText(winPanel.transform, "WinTitle", "胜利!", 40, TextAnchor.MiddleCenter);
winTitle.GetComponent<Text>().color = new Color(1f, 0.85f, 0.2f);
winTitle.GetComponent<RectTransform>().anchoredPosition = new Vector2(0, 60);
var winScore = CreateText(winPanel.transform, "WinScore", "分数: 0", 24, TextAnchor.MiddleCenter);
winScore.GetComponent<RectTransform>().anchoredPosition = new Vector2(0, 0);
var winBtn = CreateButton(winPanel.transform, "WinConfirmBtn", "确认", new Vector2(160, 50));
winBtn.GetComponent<RectTransform>().anchoredPosition = new Vector2(0, -60);
// ===== 失败面板 =====
var losePanel = CreateCenterPanel(resultCanvasObj, "LosePanel", new Color(0.3f, 0.1f, 0.1f, 0.9f));
var loseTitle = CreateText(losePanel.transform, "LoseTitle", "游戏结束", 40, TextAnchor.MiddleCenter);
loseTitle.GetComponent<Text>().color = new Color(1f, 0.3f, 0.3f);
loseTitle.GetComponent<RectTransform>().anchoredPosition = new Vector2(0, 60);
var loseScore = CreateText(losePanel.transform, "LoseScore", "分数: 0", 24, TextAnchor.MiddleCenter);
loseScore.GetComponent<RectTransform>().anchoredPosition = new Vector2(0, 0);
var loseBtn = CreateButton(losePanel.transform, "LoseConfirmBtn", "确认", new Vector2(160, 50));
loseBtn.GetComponent<RectTransform>().anchoredPosition = new Vector2(0, -60);
// 初始隐藏两个面板
winPanel.SetActive(false);
losePanel.SetActive(false);
// ===== 连接 GameResultScreen 引用 =====
var so = new SerializedObject(resultScreen);
so.FindProperty("resultCanvas").objectReferenceValue = canvas;
so.FindProperty("winPanel").objectReferenceValue = winPanel;
so.FindProperty("winConfirmButton").objectReferenceValue = winBtn.GetComponent<Button>();
so.FindProperty("winTitleText").objectReferenceValue = winTitle.GetComponent<Text>();
so.FindProperty("winScoreText").objectReferenceValue = winScore.GetComponent<Text>();
so.FindProperty("losePanel").objectReferenceValue = losePanel;
so.FindProperty("loseConfirmButton").objectReferenceValue = loseBtn.GetComponent<Button>();
so.FindProperty("loseTitleText").objectReferenceValue = loseTitle.GetComponent<Text>();
so.FindProperty("loseScoreText").objectReferenceValue = loseScore.GetComponent<Text>();
so.ApplyModifiedProperties();
Debug.Log("[UIBuilder] ResultScreen Canvas 搭建完成");
}
// ===== 辅助方法 =====
private static GameObject CreateChild(GameObject parent, string name, Vector2 pos)
{
var obj = new GameObject(name);
obj.transform.SetParent(parent.transform, false);
var rect = obj.AddComponent<RectTransform>();
rect.anchorMin = new Vector2(0, 1);
rect.anchorMax = new Vector2(0, 1);
rect.pivot = new Vector2(0, 1);
rect.anchoredPosition = pos;
return obj;
}
private static GameObject CreateText(Transform parent, string name, string content, int fontSize, TextAnchor alignment)
{
var obj = new GameObject(name);
obj.transform.SetParent(parent, false);
obj.AddComponent<RectTransform>();
var text = obj.AddComponent<Text>();
text.text = content;
text.fontSize = fontSize;
text.alignment = alignment;
text.color = Color.white;
text.font = Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf");
if (text.font == null) text.font = Font.CreateDynamicFontFromOSFont("Arial", fontSize);
text.horizontalOverflow = HorizontalWrapMode.Overflow;
text.verticalOverflow = VerticalWrapMode.Overflow;
return obj;
}
private static GameObject CreateButton(Transform parent, string name, string label, Vector2 size)
{
var btnObj = new GameObject(name);
btnObj.transform.SetParent(parent, false);
var rect = btnObj.AddComponent<RectTransform>();
rect.sizeDelta = size;
var img = btnObj.AddComponent<Image>();
img.color = new Color(0.3f, 0.3f, 0.3f, 0.9f);
var btn = btnObj.AddComponent<Button>();
var textObj = CreateText(btnObj.transform, "Text", label, 18, TextAnchor.MiddleCenter);
var textRect = textObj.GetComponent<RectTransform>();
textRect.anchorMin = Vector2.zero;
textRect.anchorMax = Vector2.one;
textRect.sizeDelta = Vector2.zero;
return btnObj;
}
private static GameObject CreateCenterPanel(GameObject parent, string name, Color bgColor)
{
var panel = new GameObject(name);
panel.transform.SetParent(parent.transform, false);
var rect = panel.AddComponent<RectTransform>();
rect.anchorMin = new Vector2(0.5f, 0.5f);
rect.anchorMax = new Vector2(0.5f, 0.5f);
rect.pivot = new Vector2(0.5f, 0.5f);
rect.sizeDelta = new Vector2(400, 250);
var img = panel.AddComponent<Image>();
img.color = bgColor;
return panel;
}
}