Editor 能跑、构建挂了:用 Unity MCP 根据 Console 定位引用问题
针对 Unity「编辑器正常、真机/Player 构建失败或进场景 NRE」:按 A/B/C 分层,用 Cursor + Unity MCP 读 Console、核对 Build Settings 与序列化引用;含堆栈样例、人手检查项与最小修复。
- Unity MCP
- Unity
- Console
- build
- Android
- Cursor
- troubleshooting
- AI game development
「Unity works in editor, fails on device / build」类帖子里,症状高度重复:本地 Play 正常,一打 Player / 真机包 就构建红字、闪退、黑屏,或进场景立刻 NullReferenceException。多数不是引擎坏了,而是编辑器路径掩盖了引用与平台差异——场景未进包、序列化字段在磁盘上是 None、路径大小写、把 UnityEditor API 写进运行时程序集,到打包或真机才爆。
本文主轴只有三条(与标题一致):
- Console / 堆栈 → 定位脚本与场景对象
- 核对 Build Settings、Missing Script、序列化引用
- 用 Unity MCP 在 Cursor 里只读诊断 → 确认后最小修复
不重复插件安装,不写完整上架流水线;IL2CPP 剥离、原生插件等放文末扩展。
相关阅读:
- Unity MCP 安装
- 用 Claude Code 与 Cursor 操作 Unity MCP
- 把 AI Studio 导出的 HUD 绑到血量事件(正确接线;本文侧重「断了怎么查」)
先分清:挂在哪一层
A. 构建窗口红字(编译 / 打包阶段失败)
↓
B. 包能打出,真机一开就闪退 / 黑屏
↓
C. 能进游戏,进某场景或点某功能才炸(运行时)
| 你看到的 | 层 | 本文优先查 |
|---|---|---|
Build 失败,error CS… / 找不到类型 | A | 运行时程序集误引用 UnityEditor、条件编译、asmdef |
| 进启动场景立刻 NRE / MissingReference | B/C | 场景是否进包、Missing Script、Inspector 里 None |
某 Resources.Load / 加性场景才挂 | C | 路径大小写、资源是否在包内、场景是否加载 |
Unity MCP 强项在已打开的编辑器:读 Console、扫 Hierarchy、看组件字段。真机 logcat / Xcode 需你把堆栈贴进 Cursor;或先打 Development Build,尽量在 Editor 用同一启动场景复现。
排障环(人手检查 + MCP)
每次失败按顺序做,不要跳过「人手」直接让 AI 重写 Player。
步骤 0:人手固定现场(2 分钟)
在 Cursor 开口前,自己先完成:
- 记下 Unity 版本、目标平台(如 Android / IL2CPP)
- Window → General → Console 清空,再 Build 或 Development Build 一次
- 复制第一条相关 Error(含堆栈),不要只丢 Warning 墙
- 打开 File → Build Settings:嫌疑场景是否勾选;列表第 0 项是否为启动场景
- 若改过 Prefab:实例上是否 Apply(未 Apply 的覆盖不会进别人的包,也常进不了你以为的磁盘资源)
步骤 1:MCP 只读分类 Console
汇总当前 Console 里与本次构建/上次 Play 相关的 Error(忽略 Info)。
按「编译错误 / Missing Script / NullReference / 资源加载」分类。
列出每条错误中的脚本路径、行号、GameObject 名(若日志有)。
不要修改任何资源。
步骤 2:人手 + MCP 核对「引用三件套」
对运行时 NRE(B/C),在编辑器里点开堆栈里的对象,并让 MCP 交叉验证:
| 人手 | MCP 提示 |
|---|---|
| Build Settings 场景列表截图或口述 | 「列出 Build Settings 中的场景路径与是否启用;指出启动场景。」 |
| 选中嫌疑对象,看 Inspector 是否 Missing Script / 引用 None | 「在场景 <Name> 列出 Missing Script;检查 <Object> 上 <Component> 各序列化字段是否为 None。表格输出。不要改。」 |
| Prefab 模式 vs 场景实例是否一致 | 「说明 <X> 是 Prefab 资源还是场景实例;实例上有无未 Apply 覆盖(若可见)。只报告。」 |
原则: 打包用的是磁盘上的场景/Prefab。Editor 里靠 OnValidate 临时赋值、「看起来有引用」,以 MCP/Inspector 读到的序列化结果为准。
步骤 3:先诊断模板,确认后再改
【约束】
- 先诊断与最小方案,等我确认后再改
- 禁止用大面积 GameObject.Find 冒充修复
- 只动与本条 Error 直接相关的脚本/Prefab/场景
【现场】
- Editor Play:正常 / 异常(如实填)
- 平台与构建:…
- Build Settings 启动场景:…
- Console / 设备堆栈(原文):
<粘贴>
【请回答】
1. 属于 A / B / C 哪一层
2. 最可能的 1~2 个根因(未进包 / None 引用 / Missing Script / 大小写 / Editor API…)
3. 要我核对的对象与字段名
4. 最小修复步骤(仍先不执行)
步骤 4:确认后最小写入 + 复查
按确认方案执行最小修复:仅修 <对象.字段> 或 <脚本路径> 中与本 Error 相关的几行。
保存场景/Prefab。
然后只读复查:相关字段是否仍为 None;Console 是否还有同类 Error。
完整样例:从一条 NRE 堆栈到字段
下面是一段仿真实设备/Player 日志(结构常见;路径按你工程替换)。
日志
NullReferenceException: Object reference not set to an instance of an object
at HudHealthView.HandleHealthChanged (System.Single current, System.Single max) [0x00000] in Assets/Scripts/UI/HudHealthView.cs:42
at PlayerHealth.TakeDamage (System.Single amount) [0x00000] in Assets/Scripts/Combat/PlayerHealth.cs:28
at DebugDealDamage.Update () [0x00000] in Assets/Scripts/Debug/DebugDealDamage.cs:15
判层
- 能进 Play/包并执行到
Update→ 不是 A(编译已过) - 一受伤就炸 → C(运行时),嫌疑是 UI 引用,不是「重写战斗」
人手
- Build Settings 是否包含该 HUD 所在场景
- 打开场景,选中挂
HudHealthView的对象,看healthFill/playerHealth是否为 None - 若在 Prefab 上改过:是否 Apply
给 MCP
只读:打开含 HUD 的场景。
1. 找到挂有 HudHealthView 的对象
2. 报告 healthFill、playerHealth(及同类)字段是否为 None / Missing
3. 不要修改
根据结果:若为 None,最小方案应是重新指定引用并保存,而不是改 TakeDamage 逻辑。
最小修复(确认后)
- 把
HUD_HealthFill的 Image 拖回healthFill,Player 上的PlayerHealth拖回playerHealth - 保存场景;Development Build 再走一次受伤
错误「修复」(不要做)
// 反例:用 Find 掩盖 None —— 真机改名或加性加载后仍会挂
healthFill = GameObject.Find("HUD_HealthFill").GetComponent<Image>();
正确方向与接线步骤见 HUD 绑血量事件;本文只要求:先用堆栈钉住字段,再绑回去。
症状对照(主轴)
症状 1:构建红字,找不到类型 / UnityEditor
| 可能根因 | 人手 | 给 MCP |
|---|---|---|
| 运行时脚本引用了 Editor API | 看报错文件是否在非 Editor/ 目录 | 「搜索非 Editor 文件夹中的 UnityEditor.;只列路径。」 |
#if 写反,Player 缺类型 | 核对 UNITY_EDITOR 包裹 | 「说明该文件在 Editor 与 Player 下哪些类型可见。」 |
| asmdef 未引用 | 打开报错程序集的 .asmdef | 「列出该 asmdef 引用,说明缺哪一个。」 |
反例(运行时程序集里误用 Editor API,Player 构建必挂):
using UnityEngine;
using UnityEditor; // 若文件不在 Editor 程序集,构建失败
public class BadBake : MonoBehaviour
{
[MenuItem("Tools/Bad")] // 进一步依赖 UnityEditor
static void Run() { }
}
正解 A:整文件放进 Editor 文件夹
Assets/Scripts/Editor/BakeTools.cs ← 仅编辑器编译
正解 B:同一文件内隔离(仅当必须同文件时)
using UnityEngine;
public class RuntimeSafe : MonoBehaviour
{
public void DoGameplay() { /* Player 可见 */ }
#if UNITY_EDITOR
[ContextMenu("Debug/Fill Refs")]
void EditorOnlyFill()
{
// 仅编辑器;不要在 Awake 里依赖这里的结果当打包数据
}
#endif
}
更干净的做法是 Editor 专用脚本 + asmdef,避免运行时程序集被 Editor 引用拖死。
症状 2:真机进场景 NRE,Editor Play「好像正常」
按顺序查,不要并联大改:
- 场景未进 Build Settings 或启动场景不是你以为的那一个
- Missing Script / 序列化 None(含 Prefab 未 Apply)
- 加性场景未加载 就 Find / 访问对象
Resources.Load路径大小写(macOS Editor 常不敏感,Android 敏感)
1. 报告 Build Settings 场景列表与启用状态、启动场景索引
2. 在场景 <X> 列出全部 Missing Script
3. 检查启动路径上 GameManager / Player / HUD 的公开引用是否为 None
只报告,不修改。
| 编辑器里 | 包里 | 常见原因 |
|---|---|---|
| 引用看着有 | 运行 None | 实例覆盖未 Apply;改错场景文件 |
Find 得到 | 真机 null | 对象在未加载场景;名称不一致 |
Resources.Load 成功 | 真机 null | 路径大小写;资源不在 Resources/ |
// 磁盘:Assets/Resources/UI/HealthBar.png
// Android 上常失败(大小写不一致):
Resources.Load<Sprite>("ui/healthbar");
// 应与 Resources 下相对路径一致,例如:
Resources.Load<Sprite>("UI/HealthBar");
搜索工程中 Resources.Load / Addressables.LoadAssetAsync 的路径字符串,
与实际文件相对路径做大小写对照表。不要改代码。
症状 3:Console 刷 Missing Script
扫描场景 <X> 与 Prefab <path>:
列出 Missing Script 的对象路径。
对每个给出「重挂原脚本」或「删除空组件」建议(根据残留脚本名/GUID 若可见)。
先不要批量自动删除。
人手:在 Project 窗口确认脚本文件还在、没有改程序集定义导致 GUID 断裂;一条条确认再删空组件。
验收清单
- 同类 Error 从 Console 消失
- Editor Play 走同一条会炸操作(进关、受伤、开界面等)
- 打一次 Development Build 到目标平台(或本地 Player)
- MCP 只读复查 嫌疑字段不再为 None / Missing
- Git diff 仅含预期的场景/Prefab/脚本小改,没有「顺手重构」
只读复查:<对象列表> 上相关字段是否仍有 None 或 Missing Script?列出异常项。不要修改。
提示词红线
| 不要 | 要 |
|---|---|
| 「随便修到能 Play」 | 先判 A/B/C + 堆栈钉字段 |
大面积 Find 代替引用 | 修序列化字段或显式注入 |
| 未确认就改 Build Settings 顺序 | 先报告当前列表与启动场景 |
| 只说「有个 NRE」 | 贴堆栈前 20~40 行 |
产品边界
- Unity MCP:编辑器内 Console、Hierarchy、脚本与引用——适合本文主轴。
- AI Studio:UI 结构进引擎;重导弄丢引用时按接线文重绑,不要在玩法里 Find UI。
- 证书、商店、厂商 ROM:把日志文本贴进 Cursor 即可协助阅读,不在 MCP 改场景范围内。
扩展:不在主轴但仍常见
以下易与「引用问题」搅在一起,先排除本文主轴再查:
| 现象 | 方向 |
|---|---|
| Development 正常、Release 挂 | Managed Stripping / link.xml;对 MCP:「根据崩溃栈猜测被裁类型,提议 link.xml,先不写文件。」 |
| 仅 Android 原生崩溃(非托管栈) | .so / 权限 / Gradle;贴 logcat 给模型阅读 |
| 非主线程碰 Unity API | 查异步回调是否回到主线程 |
不要把 stripping 和 Missing Script 合成一次「大重构」。
小结
- Editor 能跑、包挂了:先当 引用 / 进包场景 / 路径 / Editor API 查
- 人手固定 Build Settings 与第一条 Error,再让 MCP 只读分类
- 用堆栈钉到脚本行 → 组件字段,确认后最小绑回或删空组件
- 禁止用
Find和重写玩法冒充修复 - 以 Development Build + 只读复查验收
按「现场 → 分层 → 三件套 → 样例同款钉字段」跑,多数真机引用问题会收成可审查的小 diff。
继续阅读
你可能还会喜欢这些文章
Unity Generate UI 与设计进引擎:什么时候用内置生成,什么时候走画布导出
Unity 6 Editor 内 AI/UI 生成与 Figma·PSD→Studio 画布→Prefab 的边界、失败判据与验收步骤;选型文,非 Generate 逐步教程。对齐 MCP 绑逻辑与发布前清单。
- 游戏UI设计
- 游戏开发AI提效
- ui-to-engine
- unity
VberAI Studio:游戏 UI 设计图怎么拆分、导入 Unity / Godot / Cocos
VberAI Studio 把游戏 UI 设计整图按原位置拆成 UI 元素,保留布局与尺寸,导出或推送到 Unity、Godot、Cocos。含官方演示视频、步骤清单与验收要点。
- vberai
- ai-studio
- game-ui
- game-art
AI 怎么生成游戏序列帧和宣传片?拆帧进 Unity / Godot / Cocos
VberAI Studio 用文本、图片或首尾帧生成游戏序列帧与宣传/剧情 CG;落画布后可裁切、拆帧,交付 Unity、Godot、Cocos。含操作录像、验收清单,并说明不能替代 Timeline / Sequencer。
- ai-studio
- game-video
- sequence-frames
- sprite-frames