ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Claude Code + MCP:从空文件夹到可玩Unity游戏原型

Claude Code + MCP:从空文件夹到可玩Unity游戏原型 1. 从空文件夹到可玩原型这套组合到底在做什么第一次看到“Claude Code MCP让一个空文件夹变成了能玩的 Unity 游戏”这个说法我第一反应是怀疑。一个空文件夹意味着没有场景、没有预制体、没有脚本、没有材质连 Unity 工程最基本的Assets、ProjectSettings、Packages目录都不存在。正常流程下你得先打开 Unity Hub 建工程等它编译完默认包再手动拖控件、写脚本、调参数。这套流程少说也要折腾小半天才能跑出一个能动的方块。但把 Claude Code 和 MCP 这两个东西放在一起看逻辑就通了。Claude Code 是跑在终端里的编码代理它能读写文件、执行命令、理解项目结构MCPModel Context Protocol是一套让模型和外部工具对话的协议相当于给模型装上了“手”和“眼睛”让它能调用 Unity 编辑器、文件系统、版本控制这些外部能力。两者叠加等于让一个懂代码的助手直接在你的机器上操作 Unity 工程。我拿这个思路实测了一遍从零开始用一个完全空的目录最后跑出了一个能控制角色移动、有地面、有相机跟随、还能捡金币的 3D 小场景。整个过程没有手动打开过 Unity 编辑器去拖任何东西全部通过终端指令和 MCP 工具调用完成。这篇文章就把这套流程拆开讲清楚MCP 到底是什么、Claude Code 怎么装怎么配、Unity 工程怎么从零生成、脚本怎么自动写进去、以及我踩过的那些坑。适合谁看如果你是有一定 Unity 基础、想提升开发效率的开发者或者是对 AI 辅助编码感兴趣、想看看这套工具链到底能做到什么程度的人这篇内容应该能给你不少参考。完全没接触过 Unity 的也能看但部分编辑器操作的概念需要你边看边查。2. 先搞懂 MCP它凭什么让模型能操作 Unity2.1 MCP 协议的本质给模型一套标准工具接口MCP 全称 Model Context Protocol翻译过来叫模型上下文协议。名字听着玄乎其实核心就一件事定义了一套标准格式让 AI 模型能够发现、调用外部工具并拿到返回结果。你可以把它理解成 USB 接口——以前每个外设都有自己的插头现在统一成 USB-C谁都能插。在没有 MCP 之前想让模型操作 Unity你得自己写一堆胶水代码模型输出一段文本你解析这段文本判断它想干什么再调用对应的 Unity API。每个模型输出格式还不一样换个模型就得重写解析逻辑。MCP 把这个过程标准化了工具提供方按照 MCP 规范暴露自己的能力模型按照 MCP 规范去调用中间不需要你写解析层。具体到 Unity 场景MCP 工具会暴露这些能力创建 GameObject、添加组件、设置 Transform、创建材质、写入脚本文件、触发编译、读取控制台日志。模型通过 MCP 调用这些工具就像在 Unity 编辑器里手动操作一样只不过操作指令是模型生成的。2.2 为什么是 Claude Code 而不是普通对话模型普通对话模型只能输出文本你复制粘贴到 Unity 里还得自己判断放哪、怎么改。Claude Code 不一样它本身就是一个跑在终端里的代理具备文件系统读写、命令执行、代码搜索这些基础能力。再叠加 MCP 工具它就能形成完整闭环读工程结构 → 生成代码 → 写入文件 → 调用 Unity 编译 → 读取报错 → 修复 → 再编译。这个闭环很关键。我试过用普通对话模型生成 Unity 脚本生成出来的代码经常有 API 版本不匹配的问题比如用了旧版的Input系统但工程配置的是新 Input System或者Rigidbody的某个属性在新版本里改了名。普通模型没法验证只能靠你自己试。Claude Code 能直接触发编译拿到报错信息后自己改改完再编译直到通过。这个迭代能力是它和普通对话模型最大的区别。2.3 Unity 侧需要什么一个能接收指令的桥梁Unity 本身不会主动跟外部工具通信你需要一个桥梁。常见做法是写一个 Unity 编辑器扩展Editor Window 或 MenuItem在编辑器里开一个本地服务端口接收外部发来的指令解析后调用 Unity API 执行。这个扩展就是 MCP 工具在 Unity 侧的落地实现。我用的方案是在 Unity 工程里放一个Editor目录下的 C# 脚本启动一个轻量级的 HTTP 服务监听本地端口。Claude Code 通过 MCP 调用这个服务发送 JSON 格式的指令比如{action: create_gameobject, name: Player, components: [Rigidbody, BoxCollider]}Unity 侧解析后执行返回执行结果。这个桥梁写一次就行后续所有操作都走这个通道。注意这个本地服务只监听本机回环地址不要暴露到外网。端口选一个不常用的避免和其他开发工具冲突。我用的 17890实测没碰到过占用。3. 环境准备从零搭好这套工具链3.1 Claude Code 的安装与配置Claude Code 的安装方式取决于你的操作系统。macOS 和 Linux 下用 npm 全局安装最省事npm install -g anthropic-ai/claude-codeWindows 下建议用 WSL2原生 Windows 支持一直不太稳定。装完之后在终端输入claude就能启动。首次启动会引导你配置 API 密钥或者登录账号按提示走就行。配置方面我建议在项目根目录放一个.claude/settings.json把常用配置写进去。比如指定模型、设置超时时间、配置 MCP 服务器地址。这个文件不要提交到版本控制因为里面可能包含密钥信息。{ model: claude-sonnet-4-20250514, mcpServers: { unity: { command: node, args: [./mcp-unity-server/index.js], env: { UNITY_PORT: 17890 } } } }这段配置的意思是告诉 Claude Code有一个叫unity的 MCP 服务器通过 node 启动启动脚本在./mcp-unity-server/index.js环境变量里指定 Unity 侧监听的端口是 17890。3.2 Unity 工程的初始化策略空文件夹直接让 Claude Code 生成完整 Unity 工程是可行的但有几个前提。第一你机器上得装了 Unity并且知道 Unity 编辑器的可执行文件路径。第二你得接受生成的工程是最小化的没有默认的 SampleScene、没有标准资源包。我的做法是分两步先用 Unity Hub 命令行创建一个空工程再用 Claude Code 往里填内容。Unity Hub 支持命令行创建工程/Applications/Unity Hub.app/Contents/MacOS/Unity Hub -- --headless create --name MyGame --path ./MyGame --template 3dWindows 下路径换成对应的Unity Hub.exe位置。这个命令会生成一个标准的 3D 工程结构包含Assets、Packages、ProjectSettings三个核心目录。有了这个基础结构Claude Code 后续操作就有据可依了。如果你想让 Claude Code 完全从零生成也不是不行但需要它自己创建ProjectSettings里的各种配置文件这些文件格式复杂且版本相关容易出错。我试过一次生成的工程 Unity 打不开报了一堆配置错误。所以建议还是用 Unity Hub 先建好骨架。3.3 MCP 服务端的搭建MCP 服务端是一个独立的 Node.js 进程负责在 Claude Code 和 Unity 之间转发指令。它的核心逻辑是接收 Claude Code 的 MCP 调用请求转换成 Unity 能理解的 JSON 格式通过 HTTP 发给 Unity 编辑器里的本地服务拿到结果后再返回给 Claude Code。服务端代码不复杂核心就是几个路由处理。我用的是modelcontextprotocol/sdk这个官方包它封装了 MCP 协议的细节你只需要定义工具列表和处理函数。import { Server } from modelcontextprotocol/sdk/server/index.js; import { StdioServerTransport } from modelcontextprotocol/sdk/server/stdio.js; const server new Server({ name: unity-mcp, version: 1.0.0 }, { capabilities: { tools: {} } }); server.setRequestHandler(tools/list, async () ({ tools: [ { name: create_gameobject, description: 在 Unity 场景中创建一个 GameObject, inputSchema: { type: object, properties: { name: { type: string }, components: { type: array, items: { type: string } } } } } ] })); server.setRequestHandler(tools/call, async (request) { const { name, arguments: args } request.params; if (name create_gameobject) { const result await fetch(http://127.0.0.1:17890/execute, { method: POST, body: JSON.stringify({ action: create_gameobject, ...args }) }); return { content: [{ type: text, text: await result.text() }] }; } }); const transport new StdioServerTransport(); await server.connect(transport);这段代码定义了一个create_gameobject工具Claude Code 调用它时服务端会把请求转发给 Unity 的本地服务。实际使用中我会定义十几个工具覆盖场景操作、脚本写入、编译触发、日志读取这些常用能力。4. 实操全流程从空目录到能跑的游戏4.1 第一步让 Claude Code 理解工程结构工程骨架建好后第一件事是让 Claude Code 扫描一遍目录建立对工程的认知。在终端里进入工程目录启动 Claude Code然后给它一个明确的指令扫描当前 Unity 工程结构告诉我 Assets 目录下有哪些文件夹ProjectSettings 里配置了哪些关键项Packages 里装了哪些包。Claude Code 会调用文件系统工具遍历目录读取ProjectSettings/ProjectVersion.txt确认 Unity 版本读取Packages/manifest.json确认依赖包。这一步很重要因为后续生成代码时需要知道 Unity 版本不同版本的 API 有差异。比如 Unity 2021 和 Unity 6 在渲染管线、Input 系统上的默认配置就不一样。我实测时用的是 Unity 2022.3 LTSClaude Code 扫描后正确识别出了版本号并在后续生成脚本时自动避开了新版本才有的 API。这个细节让我省了不少事。4.2 第二步生成场景与基础物件接下来让 Claude Code 创建场景。指令可以写得具体一些创建一个新场景 Main保存到 Assets/Scenes/ 下。在场景里创建一个 Plane 作为地面位置在原点缩放为 (10, 1, 10)。创建一个 Cube 作为玩家位置在 (0, 1, 0)添加 Rigidbody 和 BoxCollider 组件。创建一个 Camera位置在 (0, 5, -10)朝向玩家。Claude Code 会通过 MCP 工具依次调用 Unity 侧的接口。Unity 侧收到指令后用EditorSceneManager.NewScene创建场景用GameObject.CreatePrimitive创建基础物件用AddComponent添加组件最后用EditorSceneManager.SaveScene保存。这里有个细节创建场景后需要设置为当前活动场景否则后续操作会作用到默认场景上。我在 Unity 侧的桥接脚本里加了一个set_active_scene的 action确保每次创建场景后都切换过去。实操心得让 Claude Code 分步执行不要一次性给太多指令。我试过一条指令里让它创建场景、加物件、写脚本、挂脚本结果中间某一步失败后后面的步骤全乱了。分步执行每步确认结果出问题好定位。4.3 第三步自动生成并挂载控制脚本场景有了接下来是让角色动起来。给 Claude Code 的指令在 Assets/Scripts/ 下创建 PlayerController.cs实现以下功能用 WASD 控制角色在水平面移动移动速度 5 单位每秒用 Rigidbody 的 velocity 实现移动不要用 Transform.Translate。脚本写完后挂到 Player 这个 GameObject 上。Claude Code 生成脚本时会考虑几个点用Rigidbody.velocity而不是Transform.Translate是因为前者走物理系统能和碰撞体正确交互移动速度用public float moveSpeed 5f暴露出来方便在 Inspector 里调输入检测用Input.GetAxis还是新 Input System取决于工程配置。我实测时工程用的是旧 Input 系统Claude Code 扫描ProjectSettings后正确选择了Input.GetAxis。脚本写完后Claude Code 通过 MCP 调用 Unity 侧的attach_script接口把脚本挂到指定 GameObject 上。Unity 侧用AssetDatabase.LoadAssetAtPath加载脚本用AddComponent挂载。挂载完成后触发一次编译确保脚本没有语法错误。using UnityEngine; public class PlayerController : MonoBehaviour { public float moveSpeed 5f; private Rigidbody rb; void Start() { rb GetComponentRigidbody(); } void FixedUpdate() { float h Input.GetAxis(Horizontal); float v Input.GetAxis(Vertical); Vector3 movement new Vector3(h, 0, v) * moveSpeed; rb.velocity new Vector3(movement.x, rb.velocity.y, movement.z); } }这段代码是 Claude Code 生成的我检查了一遍逻辑没问题。FixedUpdate里处理物理移动是标准做法rb.velocity.y保留了重力影响不会让角色悬空。4.4 第四步相机跟随与场景完善角色能动了但相机是固定的角色跑出视野就看不见了。继续给指令修改 Camera让它跟随 Player。创建一个 CameraFollow.cs 脚本实现平滑跟随偏移量 (0, 5, -10)平滑系数 0.1。挂到 Camera 上。Claude Code 生成的跟随脚本用Vector3.Lerp做平滑using UnityEngine; public class CameraFollow : MonoBehaviour { public Transform target; public Vector3 offset new Vector3(0, 5, -10); [Range(0.01f, 1f)] public float smoothFactor 0.1f; void LateUpdate() { if (target null) return; Vector3 desiredPosition target.position offset; transform.position Vector3.Lerp(transform.position, desiredPosition, smoothFactor); transform.LookAt(target); } }这里用LateUpdate而不是Update是因为相机跟随要在角色移动之后执行否则会出现相机抖动。smoothFactor用Range属性限制在 0.01 到 1 之间防止在 Inspector 里被设成负数或过大值。挂载脚本后还需要设置target引用。Claude Code 通过 MCP 调用 Unity 侧的set_reference接口把 Player 的 Transform 赋给 CameraFollow 的 target 字段。这个操作在 Unity 里对应的是拖拽赋值通过代码实现就是cameraFollow.target playerTransform。4.5 第五步加个金币收集玩法基础移动和相机都有了加个简单的收集玩法让场景更有游戏感。指令创建 5 个金币用 Cylinder 缩放成扁圆形位置随机分布在地面上方。创建 Coin.cs 脚本实现角色碰到金币后金币消失并在控制台输出收集数量。金币需要添加 Collider 并设置为 Trigger。Claude Code 会生成金币创建逻辑和收集脚本。金币用GameObject.CreatePrimitive(PrimitiveType.Cylinder)创建缩放设为(0.5, 0.05, 0.5)变成扁圆。Collider 的isTrigger设为 true这样角色穿过时触发OnTriggerEnter而不是物理碰撞。using UnityEngine; public class Coin : MonoBehaviour { private static int collectedCount 0; void OnTriggerEnter(Collider other) { if (other.CompareTag(Player)) { collectedCount; Debug.Log($金币已收集: {collectedCount}); gameObject.SetActive(false); } } }这里用CompareTag(Player)而不是other.name Player是因为 Tag 比较性能更好而且不受 GameObject 改名影响。金币消失用SetActive(false)而不是Destroy是为了后续可能的重置功能留余地。注意角色需要设置 Tag 为 Player否则触发检测不生效。Claude Code 在生成金币脚本后会自动通过 MCP 调用设置 Tag 的接口。如果忘了这步金币碰了没反应排查时优先检查 Tag。5. 踩坑记录与问题排查5.1 编译报错API 版本不匹配最常见的问题是生成的脚本用了当前 Unity 版本不支持的 API。我碰到过一次Claude Code 生成了FindObjectOfType但工程用的是 Unity 6这个 API 已经标记为过时推荐用FindFirstObjectByType。编译时报警告虽然不影响运行但控制台一堆黄字看着难受。解决办法是在 Claude Code 的配置里明确指定 Unity 版本或者在指令里加上“使用当前 Unity 版本推荐的 API避免已过时的写法”。Claude Code 拿到编译日志后也能自己修复但提前说明能减少一轮迭代。5.2 MCP 连接失败端口占用与权限问题MCP 服务端启动后连不上 Unity报ECONNREFUSED。排查下来通常是两个原因Unity 编辑器没启动或者本地服务没监听成功。Unity 侧的桥接脚本需要在编辑器启动后手动触发一次初始化我把它做成了[InitializeOnLoad]静态构造函数编辑器一加载就自动启动服务。另一个坑是端口占用。17890 这个端口如果被其他程序占了服务起不来。我在桥接脚本里加了端口检测如果占用就自动切换到 17891、17892直到找到可用端口。MCP 服务端配置里也要对应改或者让 Unity 侧把实际端口写到一个临时文件里MCP 服务端读取这个文件获取端口。5.3 脚本挂载失败GUID 与路径问题通过 MCP 挂载脚本时偶尔会遇到AddComponent返回 null 的情况。排查发现是脚本路径不对AssetDatabase.LoadAssetAtPath没加载到资源。Unity 里每个资源都有唯一的 GUID路径变了但 GUID 不变。如果 Claude Code 生成的路径和实际保存路径不一致就会加载失败。解决办法是在写入脚本后先调用AssetDatabase.Refresh()强制刷新资源数据库再用AssetDatabase.LoadAssetAtPath加载。路径统一用相对于工程根目录的格式比如Assets/Scripts/PlayerController.cs不要用绝对路径。5.4 常见问题速查表问题现象可能原因排查方向解决方法MCP 连接被拒绝Unity 未启动或服务未监听检查 Unity 编辑器状态查看端口监听启动 Unity确认桥接脚本已初始化脚本编译报错API 版本不匹配查看控制台报错信息指定 Unity 版本让 Claude Code 用兼容 API脚本挂载后无效果脚本路径错误或未刷新检查 AssetDatabase 加载结果写入后先 Refresh 再加载金币触发不生效Player Tag 未设置检查 Player 的 Tag 属性通过 MCP 设置 Tag 为 Player相机抖动跟随逻辑放在 Update检查脚本的 Update 方法改用 LateUpdate角色穿模Collider 配置不当检查 Rigidbody 和 Collider 参数调整 Collision Detection 为 Continuous6. 这套流程的边界与后续扩展6.1 目前能做到什么程度实测下来这套组合能完成的工作包括创建基础几何体、添加和配置组件、生成并挂载 C# 脚本、设置引用关系、触发编译、读取控制台日志、保存场景。对于原型开发来说这些能力已经覆盖了大部分重复性劳动。一个简单的 3D 收集类游戏从空目录到可玩我用了大约 40 分钟其中大部分时间花在调试 MCP 连接和确认生成结果上。熟练之后应该能压缩到 15 分钟以内。但它也有明显的边界。复杂的材质和 Shader 编写、粒子特效调参、动画状态机配置、UI 布局这些目前通过 MCP 操作起来还很吃力。这些工作涉及大量视觉反馈和精细调整纯靠文本指令描述不清楚。我的做法是让 Claude Code 生成基础结构和占位资源精细调整还是回 Unity 编辑器手动做。6.2 可以继续扩展的方向一个自然的扩展是接入版本控制。让 Claude Code 在每次修改后自动提交一次 Git这样出问题可以随时回滚。MCP 工具里加一个git_commit的能力就行实现上就是调用git add和git commit。另一个方向是接入本地模型。Claude Code 支持配置第三方 API如果你有本地跑的大模型可以通过兼容接口接进来。这样在离线环境下也能用而且成本更低。配置方式是在settings.json里改baseUrl和apiKey指向本地服务地址。还可以把常用的操作序列封装成模板。比如“创建一个带移动控制的角色”这个操作涉及创建 GameObject、加组件、写脚本、挂脚本、设置引用好几步。把这套流程写成一个 MCP 工具Claude Code 调用一次就能完成全部步骤减少来回交互的次数。6.3 一些个人体会这套工具链最大的价值不是“让 AI 替你写代码”而是“让 AI 替你处理那些你不想手动做的重复操作”。创建 GameObject、挂脚本、设引用这些事技术上没难度但做多了很烦。交给 Claude Code 通过 MCP 去执行你只需要用自然语言描述你想要什么它去落实。这个体验和以前“复制粘贴代码”完全不一样。但前提是你得懂 Unity。Claude Code 生成的代码不一定对你得能看懂它在干什么出问题了知道往哪个方向排查。完全不懂 Unity 的人用这套流程遇到报错就卡住了因为不知道是 API 问题、配置问题还是逻辑问题。所以我的建议是先有 Unity 基础再用这套工具提效而不是反过来。最后分享一个小技巧给 Claude Code 的指令里尽量包含具体的数值和明确的约束。比如“移动速度 5 单位每秒”比“移动速度适中”好得多“用 Rigidbody 的 velocity 实现”比“实现移动”好得多。指令越具体生成结果越接近你的预期迭代次数越少。这个经验是我反复试错后总结出来的希望对你有用。
返回列表