增加怪物功能,调整灵灯参数

This commit is contained in:
2026-07-03 16:06:18 +08:00
parent e75868832f
commit 6e414a3022
46 changed files with 5907 additions and 300 deletions
+268
View File
@@ -0,0 +1,268 @@
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;
}
}