← 返回部落格

用 Unity MCP 將 AI Studio 匯出的 HUD 綁到血量事件

AI Studio 匯出 Unity HUD 預製體後,用 Cursor + Unity MCP 掛上血量事件、更新血條與傷害數字,並提供可在 Play 模式驗收的步驟與常見斷點排查。

發布於
  • Unity MCP
  • AI Studio
  • HUD
  • Unity
  • Cursor
  • AI game development
  • tutorial

HUD 進了 Unity 卻「看起來有血條、打怪不掉血」——多數時候不是預製體壞了,而是介面層和玩法層沒有共用同一套血量事件。設計側已經在 VberAI Studio 裡把主 HUD 匯出成 Canvas / Prefab;玩法側要用 Unity MCP 在已開啟的專案裡把 PlayerHealth 的變化接到 Slider / Image.fillAmount,並用 Play 模式驗收。

本文只做這一段接線,不重複「怎麼從 Figma 匯出」或「怎麼裝 MCP」。

步驟工具產出
HUD 結構進引擎AI Studio帶穩定命名的 HUD Prefab
掛腳本、綁引用、改場景Cursor(或 Claude Code)+ Unity MCPPlayerHealth ↔ HudHealthView
驗收Unity Play受傷 / 回血時條長變化

相關閱讀:

先約定:命名比「好看」更重要

AI Studio 匯出後,程式要能用路徑或序列化引用找到血條。匯出前(或進專案後立刻)保證這些名字穩定:

GameObject / 元件用途建議命名說明
HUD 根HUD_Root場景裡唯一
血條填充HUD_HealthFillImage(Filled)或掛在 Slider.fillRect 上
可選:數值文字HUD_HealthTextTextMeshProUGUI,如 80/100
可選:受傷閃紅HUD_DamageFlash全螢幕或邊框 Image,預設透明

避免把血條叫 Rectangle 42、組 3 這類設計稿預設名——MCP 和手寫腳本都會跟著一起倒霉。

步驟 1:確認 HUD 已在場景裡

  1. 開啟含玩家的場景(例如 Game)
  2. Hierarchy 中應有 HUD_Root(或你的等價名),其下能看到血條 Image / Slider
  3. Canvas 的 Render Mode 與相機關係正確(Screen Space - Overlay 最簡單)

對 MCP 做唯讀冒煙測試(不要改場景):

列出目前作用中場景裡名稱包含 HUD 的 GameObject,以及它們掛的 UI 元件類型。不要修改任何內容。

若列表為空:先回到 AI Studio 匯出/同步,或檢查 Prefab 是否拖進了錯誤場景。

步驟 2:玩法側只暴露「血量變化」,不直接 Find UI

把血量放在玩家上,用 C# event(或 UnityEvent)廣播。HUD 只訂閱,不反向 Find("Player") 改邏輯。

在 Cursor 裡讓 Unity MCP 建立腳本(路徑可按專案調整):

在 Assets/Scripts/Combat/PlayerHealth.cs 建立元件:
- maxHealth、currentHealth(float)
- 事件 Action<float,float> OnHealthChanged(current, max)
- 方法 TakeDamage(float)、Heal(float);數值夾在 0~max
- 受傷後若 current<=0,再發一次 OnHealthChanged,並可選 OnDied
- 把腳本掛到場景裡的 Player 上;Start 時廣播一次目前血量
不要修改任何 HUD 節點。

參考實作(可讓模型產生後你再審一遍):

using System;
using UnityEngine;

public class PlayerHealth : MonoBehaviour
{
    [SerializeField] float maxHealth = 100f;
    float currentHealth;

    public event Action<float, float> OnHealthChanged;
    public event Action OnDied;

    void Awake() => currentHealth = maxHealth;

    void Start() => OnHealthChanged?.Invoke(currentHealth, maxHealth);

    public void TakeDamage(float amount)
    {
        if (amount <= 0f || currentHealth <= 0f) return;
        currentHealth = Mathf.Max(0f, currentHealth - amount);
        OnHealthChanged?.Invoke(currentHealth, maxHealth);
        if (currentHealth <= 0f) OnDied?.Invoke();
    }

    public void Heal(float amount)
    {
        if (amount <= 0f || currentHealth <= 0f) return;
        currentHealth = Mathf.Min(maxHealth, currentHealth + amount);
        OnHealthChanged?.Invoke(currentHealth, maxHealth);
    }
}

臨時驗收傷害可以先掛一個除錯鍵(正式專案再刪):

給 Player 加臨時 DebugDealDamage.cs:按 H 鍵對同物體上的 PlayerHealth 造成 10 點傷害。僅用於接線驗收。

步驟 3:HUD 視圖只負責「聽事件 → 改條」

再建視圖腳本,序列化引用血條,不要在 Update 裡每幀 GameObject.Find。

建立 Assets/Scripts/UI/HudHealthView.cs:
- 序列化 Image healthFill(Filled,Horizontal)
- 可選 TMP_Text healthText
- 序列化 PlayerHealth playerHealth(或執行時在 Awake 訂閱場景中的唯一 PlayerHealth)
- OnEnable 訂閱 OnHealthChanged;OnDisable 取消訂閱
- 回呼裡:healthFill.fillAmount = current/max;文字寫成 $"{current:0}/{max:0}"
- 把腳本掛到 HUD_Root;把 HUD_HealthFill 的 Image 拖到 healthFill 欄位
- 把場景 Player 上的 PlayerHealth 拖到 playerHealth 欄位

參考實作:

using TMPro;
using UnityEngine;
using UnityEngine.UI;

public class HudHealthView : MonoBehaviour
{
    [SerializeField] PlayerHealth playerHealth;
    [SerializeField] Image healthFill;
    [SerializeField] TMP_Text healthText;

    void OnEnable()
    {
        if (playerHealth == null) return;
        playerHealth.OnHealthChanged += HandleHealthChanged;
        // 若訂閱晚於 Start,可再主動拉一次;此處依賴 PlayerHealth.Start 已廣播
    }

    void OnDisable()
    {
        if (playerHealth == null) return;
        playerHealth.OnHealthChanged -= HandleHealthChanged;
    }

    void HandleHealthChanged(float current, float max)
    {
        float t = max > 0f ? current / max : 0f;
        if (healthFill != null) healthFill.fillAmount = t;
        if (healthText != null) healthText.text = $"{Mathf.CeilToInt(current)}/{Mathf.CeilToInt(max)}";
    }
}

若 Image 不是 Filled:讓 MCP 改 Image Type = Filled、Fill Method = Horizontal,再綁 fillAmount。若你用的是 Slider,把視圖改成寫 slider.value = t(minValue=0,maxValue=1)即可,原則相同。

步驟 4:用 Unity MCP 完成序列化引用(別手點漏欄位)

腳本編譯通過後,在 Cursor 下明確寫入意圖:

在目前場景:
1. 確認 Player 上有 PlayerHealth;HUD_Root 上有 HudHealthView
2. 將 HudHealthView.healthFill 指到名為 HUD_HealthFill 的 Image
3. 將 HudHealthView.playerHealth 指到 Player 上的 PlayerHealth
4. 若存在 HUD_HealthText,指到對應 TMP_Text
5. 儲存場景
完成後列出這兩個元件的序列化欄位是否還有 None。

再做一次唯讀核對:

檢查 HudHealthView 與 PlayerHealth 的引用:有沒有 missing script 或 None 欄位?不要改場景,只報告。

步驟 5:Play 驗收清單

進入 Play,按下面勾選(全部通過才算接線完成):

  1. 進場景瞬間:血條為滿(或等於 current/max),不是空條或髒資料
  2. 按 H(或打到玩家):fillAmount 下降;若有文字,數字同步變
  3. 連續受傷到 0:條空;若實作了死亡邏輯,角色進入死亡態且 HUD 不再亂跳
  4. Heal:條回升(可臨時加按鍵或道具)
  5. 退出 Play 再進:引用仍在,不出現 Missing Script

驗收提示範例:

我正在 Play 模式接線驗收。根據 Console:若有 NullReferenceException,定位是 PlayerHealth 還是 HudHealthView,並說明是哪個序列化欄位為 None。先診斷,提出最小修復,等我確認後再改。

常見斷點(按出現頻率)

現象優先查
Play 後條不動OnHealthChanged 未訂閱;或受傷沒走到 TakeDamage
一進 Play 就 NREhealthFill / playerHealth 仍是 None
條反向或跳變Image 不是 Filled;或用了錯誤的 Rect(邊框當填充)
文字不更新綁錯 TMP;或字型資源缺失導致元件本身報錯
AI 改壞了別的物件提示裡寫「只改 HUD_Root / Player,禁止動關卡幾何」

原則:玩法改血量,UI 只聽事件。不要在 PlayerCombat 裡直接 Find("HUD_HealthFill")——下次 AI Studio 重匯改名,戰鬥腳本會一起斷。

和「重匯 HUD」怎麼和平共處

設計在 AI Studio 改了一版 HUD 再匯出時:

  1. 盡量保留 HUD_HealthFill / HUD_Root 等約定名
  2. 重匯後只重跑步驟 4 的引用檢查;不要讓 MCP 重寫 PlayerHealth
  3. 視圖腳本留在專案裡,Prefab 變體上的序列化引用丟了就再綁一次

邊界清單可以記成一句提示詞:

這次只處理 UI Prefab 引用遺失:不要改動 Assets/Scripts/Combat 下任何玩法腳本。

小結

  1. AI Studio 負責把 HUD 結構送進 Unity
  2. PlayerHealth 廣播 (current, max)
  3. HudHealthView 訂閱並改 fillAmount / 文字
  4. Unity MCP 負責掛元件、填序列化引用、按 Console 做最小修復
  5. 用按鍵傷害 + Play 清單驗收,而不是「腳本產生成功」就算完

做完這一段,你就有一條可重複的「介面進引擎 → 事件接線 → Play 驗收」閉環;後面背包、藍條、Boss 條都可以複製同一模式。

你可能還會喜歡這些文章