重构: 将 TypeScript 转为 JavaScript 并优化项目文件结构
- 将 src/IpcManager.ts 和 src/IpcUi.ts 手动转写为干净的 JavaScript,消除编译产物中的 polyfill 代码 - 移动 main.js、scene-script.js、mcp-proxy.js 至 src/ 目录,统一源码管理 - 移动 DEVELOPMENT.md、IPC_MESSAGES.md、UPDATE_LOG.md、注意事项.md 至 docs/ 目录 - 删除 dist/ 编译产物目录和 tsconfig.json - 更新 package.json 入口路径、所有模块引用路径 - 更新 README.md 和 DEVELOPMENT.md 中的架构说明、文件路径引用和项目规范 - 更新 .gitignore 启用 dist 忽略规则
This commit is contained in:
1479
docs/IPC_MESSAGES.md
Normal file
1479
docs/IPC_MESSAGES.md
Normal file
File diff suppressed because it is too large
Load Diff
285
docs/UPDATE_LOG.md
Normal file
285
docs/UPDATE_LOG.md
Normal file
@@ -0,0 +1,285 @@
|
||||
# Cocos Creator MCP Bridge 更新与修复日志
|
||||
|
||||
本文件详细记录了本次开发周期内的所有功能更新、性能改进以及关键问题的修复过程。
|
||||
|
||||
## 新增功能与工具 (2026-02-10)
|
||||
|
||||
### 1. `manage_shader` 工具 (新增)
|
||||
|
||||
- **功能**: 实现了对着色器 (`.effect`) 资源的全生命周期管理。
|
||||
- **操作**: 支持 `create` (带默认模板), `read`, `write`, `delete`, `get_info`。
|
||||
- **意义**: 补全了资源管理链条,使得从编写代码到应用材质的流程可以完全通过 MCP 驱动。
|
||||
|
||||
### 2. 材质管理增强 (`manage_material`)
|
||||
|
||||
- **2.4.x 深度适配**: 彻底重构了材质存储结构,支持 Cocos Creator 2.4.x 的 `_effectAsset` 和 `_techniqueData` 格式。
|
||||
- **新增 `update` 操作**: 支持增量更新材质的宏定义 (`defines`) 和 Uniform 参数 (`props`),无需覆盖整个文件。
|
||||
|
||||
### 3. 组件管理增强 (`manage_components`)
|
||||
|
||||
- **资源数组支持**: 攻克了 `materials` 等数组属性无法通过 UUID 赋值的难题。
|
||||
- **智能异步加载**: 实现了并发加载多个资源 UUID 的逻辑,并在加载完成后自动同步到场景节点。
|
||||
|
||||
---
|
||||
|
||||
## 关键问题修复 (Technical Post-mortem) (2026-02-10)
|
||||
|
||||
### 1. 材质在 Inspector 面板中显示为空
|
||||
|
||||
- **原因**: 初始代码使用了错误的 JSON 字段 (如 `effects`),不符合 2.4.x 的私有属性序列化规范。
|
||||
- **修复**: 将字段改为 `_effectAsset` (UUID 引用) 和 `_techniqueData` (包含 `props` 和 `defines`)。
|
||||
|
||||
### 2. Sprite 材质赋值失效
|
||||
|
||||
- **原因**: 直接向 `cc.Sprite.materials` 赋值字符串数组会导致引擎内部类型不匹配;且直接修改内存属性不会触发编辑器 UI 刷新。
|
||||
- **修复**: 在 `scene-script.js` 中拦截数组型资源赋值,先通过 `cc.AssetLibrary` 加载资源对象,再使用 `scene:set-property` IPC 消息强制刷新编辑器 Inspector 面板。
|
||||
|
||||
### 3. 场景克隆与 `Editor.assetdb` 兼容性
|
||||
|
||||
- **原因**: Cocos 2.4.x 的主进程 `Editor.assetdb` 缺少 `loadAny` 方法,导致原本的 `duplicate` 逻辑崩溃。
|
||||
- **修复**: 改用 Node.js 原生 `fs` 模块直接读取源文件流并创建新资源。
|
||||
|
||||
---
|
||||
|
||||
## 文档与规范化建设 (2026-02-10)
|
||||
|
||||
### 1. 全域本地化 (Simplified Chinese)
|
||||
|
||||
- **代码注释**: 将 `main.js` 和 `scene-script.js` 中所有关键逻辑的英文注释转换为准确的中文说明。
|
||||
- **JSDoc 补充**: 为核心函数补充了详尽的 JSDoc 参数说明,提升代码可读性。
|
||||
- **日志输出**: 所有控制台日志 (`addLog`) 和错误提示均已中文化,方便国内开发者排查。
|
||||
|
||||
### 2. AI 安全守则 (Safety Rules)
|
||||
|
||||
- **守则注入**: 在所有 MCP 工具的描述中注入了【AI 安全守则】,强调“先校验再操作”、“资源赋 UUID”等原则。
|
||||
- **Schema 优化**: 优化了工具的描述文本,使其在 AI 客户端(如 Cursor)中展现更清晰的引导。
|
||||
|
||||
---
|
||||
|
||||
## 纹理与节点变换增强 (Texture & Transform Updates) (2026-02-10)
|
||||
|
||||
### 1. `manage_texture` 工具增强
|
||||
|
||||
- **新增 `update` 操作**: 支持修改现有纹理的类型(如 `texture` -> `sprite`)和九宫格边距 (`border`)。
|
||||
- **Meta 加载健壮性**: 修复了 `Editor.assetdb.loadMeta` 在某些情况下返回空值的问题,增加了读取文件系统 `.meta` 文件的 Fallback 机制。
|
||||
- **多版本兼容**: 针对 Cocos Creator 不同版本 `.meta` 文件结构差异(数组 vs 独立字段),实现了对 9-slice 数据写入的自动兼容。
|
||||
|
||||
### 2. `update_node_transform` 工具增强
|
||||
|
||||
- **新增尺寸控制**: 添加了 `width` 和 `height` 参数,允许 AI 直接调整节点大小(对于测试九宫格拉伸效果至关重要)。
|
||||
|
||||
### 3. 关键 Bug 修复
|
||||
|
||||
- **属性批量应用中断**: 修复了 `scene-script.js` 中 `applyProperties` 函数在处理 Asset 类型属性时错误使用 `return` 导致后续属性(如 `type`)被忽略的问题。现在改为 `continue`,确保所有属性都能被正确应用。
|
||||
|
||||
### 6.2 菜单映射清理
|
||||
|
||||
- **移除冗余**: 清理了 `execute_menu_item` 中过时或不稳定的菜单映射 (如 `File/Save`, `Edit/Delete` 等)。
|
||||
- **规范操作**: 强制引导 AI 使用 `delete-node:UUID` 或专用 MCP 工具 (`save_scene`, `manage_undo`),提高了自动化流程的稳定性。
|
||||
|
||||
## 总结 (2026-02-10)
|
||||
|
||||
本次更新不仅修复了制约生产力的材质与资源同步 bug,还通过引入 `manage_shader` 和全方位的文档中文化,极大提升了开发者(及 AI 助手)在 Cocos Creator 2.4.x 环境下的操作体验。针对菜单执行工具的清理进一步规范了自动化操作流程,减少了潜在的不稳定性。
|
||||
|
||||
---
|
||||
|
||||
## 并发安全与防卡死机制 (2026-02-12)
|
||||
|
||||
### 1. 指令队列 (CommandQueue) — 核心防卡死改造
|
||||
|
||||
- **问题**: AI 客户端连续快速发送 `delete-node` → `refresh_editor` → `search_project` 时,多个请求并发进入 `handleMcpCall`,`AssetDB.refresh()` 与后续操作争夺 I/O 和 IPC 通道,导致编辑器主线程阻塞、Scene 面板无响应。
|
||||
- **修复**: 在 HTTP `/call-tool` 入口新增 `enqueueCommand` / `processNextCommand` 队列机制,所有 MCP 工具调用强制串行执行,前一个指令回调完成后才处理下一个。
|
||||
- **异常保护**: 队列在 `processNextCommand` 的 `catch` 块中有防死锁保护,即使某个指令抛出异常也不会永久阻塞后续指令。
|
||||
- **可观测性**: 每条请求日志中显示 `(队列长度: N)`,方便排查积压问题。
|
||||
|
||||
### 2. IPC 超时保护 (callSceneScriptWithTimeout)
|
||||
|
||||
- **问题**: `Editor.Scene.callSceneScript` 无超时机制,Scene 面板阻塞时回调永不返回,导致 HTTP 连接和队列双重堆积。
|
||||
- **修复**: 新增 `callSceneScriptWithTimeout` 统一包装函数(默认 15 秒超时),覆盖全部 9 处 `callSceneScript` 调用点。
|
||||
- **超时日志**: `[超时] callSceneScript "方法名" 超过 15000ms 未响应`。
|
||||
|
||||
### 3. `batchExecute` 串行化
|
||||
|
||||
- **问题**: 原实现使用 `forEach` 并行派发所有子操作,多个 `AssetDB` 操作同时执行引发编辑器卡死。
|
||||
- **修复**: 改为串行链式执行(`next()` 递归调用),确保每个操作完成后再执行下一个。
|
||||
|
||||
### 4. `refresh_editor` 路径参数优化与警示强化
|
||||
|
||||
- **工具 Schema 强化**: 在 `manage_editor` 的工具描述中加入红色警示符号 (⚠️) 和“极为重要”字样,明确要求 AI 必须指定 `path`。
|
||||
- **AI 安全守则第 4 条**: 在全局 `globalPrecautions` 中新增第四条守则,强制要求 AI 避免刷新全局资源。
|
||||
- **实测效果**: 生产项目中,从默认全量刷新 **172 秒** 降至指定目录刷新 **19 秒**。
|
||||
|
||||
### 5. 杂项修复
|
||||
|
||||
- **清理死代码**: 删除 `/list-tools` 路由中重复的 `res.writeHead / res.end` 调用。
|
||||
- **文档更新**: `注意事项.md` 新增第 9 章「并发安全与防卡死机制」,记录 CommandQueue 和 IPC 超时两个防护机制。
|
||||
|
||||
### 6. 场景与预制体工具增强
|
||||
|
||||
- **新增 `open_prefab` 工具**: 解决了直接打开预制体进入编辑模式的问题。通过使用正确的 IPC 消息 `scene:enter-prefab-edit-mode` (并结合 `Editor.Ipc.sendToAll`),使得 AI 可以精准操控预制体的编辑流程,而不再局限于场景跳转。
|
||||
- **优化预制体创建稳定性 (`create_node` + `prefab_management`)**:
|
||||
- 在创建物理目录后强制执行 `Editor.assetdb.refresh`,确保 AssetDB 即时同步。
|
||||
- 将节点重命名与预制体创建指令之间的安全延迟从 100ms 增加至 300ms,消除了重命名未完成导致创建失败的竞态条件。
|
||||
|
||||
---
|
||||
|
||||
## Token 消耗深度优化 (2026-02-24)
|
||||
|
||||
### 1. 工具描述精简 (`main.js`)
|
||||
|
||||
- **问题**: `globalPrecautions` (AI 安全守则) 被硬编码到所有工具的 `description` 中,导致每次环境初始化或查阅工具列表时浪费约 2200 个 CJK Token。
|
||||
- **优化**: 收束安全守则的广播范围。目前仅针对高风险的**写操作**(如 `manage_components`, `update_node_transform`, `manage_material`, `create_node` 等)保留警告,低风险或只读分析类工具(如 `get_scene_hierarchy`, `get_selected_node`)已悉数移除该文本。
|
||||
- **效果**: `/list-tools` 整体负载字符数缩减近 40%。
|
||||
|
||||
### 2. 长数据截断保护 (`scene-script.js`)
|
||||
|
||||
- **问题**: `manage_components(get)` 会完整序列化多边形坐标集、曲线数据数组以及 Base64 图片,产生极其庞大且对 AI 无用的 JSON 负载。
|
||||
- **优化**:
|
||||
- **数组截断**: 长度超过 10 的数组直接返回 `[Array(length)]`,彻底杜绝数据雪崩。
|
||||
- **字符串截断**: 长度超过 200 的字符串限制为截断显示并附带 `...[Truncated, total length: X]` 提示。
|
||||
|
||||
### 3. 层级树获取瘦身与分页 (`get_scene_hierarchy`)
|
||||
|
||||
- **问题**: 请求场景层级时会一次性返回完整 1000+ 节点的深层结构,包括所有变换矩阵。
|
||||
- **优化**:
|
||||
- 支持 `depth` 深度限制(默认 2 层)。
|
||||
- 支持 `nodeId` 参数,允许 AI 缩小作用域,从指定根节点向下探测。
|
||||
- 添加 `includeDetails` 参数。默认关闭,此时剥离坐标、缩放与尺寸指标,且将冗长的组件详细结构浓缩成简化的名称数组(如 `["Sprite", "Button"]`)。
|
||||
|
||||
### 4. 查找结果精简 (`find_gameobjects`)
|
||||
|
||||
- **优化**: 将原本包含 Transform(位移/缩放/尺寸)全量数据的匹配回传,精简为仅包含核心识别特征的基础集 (`uuid`, `name`, `active`, `components`, `childrenCount`),极大释放了同名大批量查找时的 Token 压力。
|
||||
|
||||
### 5. 底层鲁棒性大修
|
||||
|
||||
- **问题**: 上述优化在应用过程中暴露出遍历未命名根节点(如 `cc.Scene`)时遭遇 `undefined.startsWith` 报错并引发 IPC 悬挂的致命隐患。
|
||||
- **修复**: 在 `dumpNodes` 与 `searchNode` 中增设前置安全屏障,并修复 `cc.js.getClassName(c)` 替代底层的 `__typename` 来兼容 2.4 获取有效类名。修复了 `main.js` 中关于 `get_scene_hierarchy` 的参数传递脱节问题。
|
||||
|
||||
---
|
||||
|
||||
## 脚本管理修复与强化 (2026-02-25)
|
||||
|
||||
### 1. `manage_script` 路径引用错误修复
|
||||
|
||||
- **问题**: AI 在调用 `manage_script` 工具执行 `create` 创建脚本时,出现 `path is not defined` 报错。
|
||||
- **原因**: 传入的变量 `path` 已经被解构重命名为 `scriptPath`,而在后续获取物理路径时,错误地调用了 `path.dirname()`,导致引用错误。
|
||||
- **修复**: 将 `path.dirname` 修正为全局正确引入的 `pathModule.dirname`,彻底解决了使用此工具生成自定义脚本库时的崩溃问题。
|
||||
|
||||
### 2. 强制生成 Script Meta 文件的提示词 (Prompt) 优化
|
||||
|
||||
- **问题**: AI 助手创建或修改脚本后,若不主动触发系统刷新,后续试图通过 `manage_components` 将该新脚本挂载为组件时,会由于缺乏有效的 `.meta` 扫描和 UUID 索引而失败。
|
||||
- **优化**: 在 `main.js` 中的 `manage_script` 工具 `description` 提示词中,将原本建议性质的刷新语气,修改为严格指令:“**创建后必须调用 refresh_editor (务必指定 path) 生成 meta 文件,否则无法作为组件添加**”。
|
||||
- **效益**: 在不增加 Token 开销的前提下,强制规范了大语言模型的行为,保障了脚本创建到组件挂载工作流的健壮性。
|
||||
|
||||
---
|
||||
|
||||
## AI 幻觉容错与调试体验增强 (2026-02-25)
|
||||
|
||||
### 1. `manage_components` 参数容错
|
||||
|
||||
- **问题**: AI 客户端在调用 `manage_components` 等工具时偶尔会产生“幻觉”,将操作类型参数 `action` 错误拼写为含义相近的 `operation`,导致插件抛出“未知的组件操作类型: undefined”等错误而中断执行。
|
||||
- **修复**: 在 `scene-script.js` 及其核心操作流中增加了参数别名映射逻辑,允许将 `operation` 作为 `action` 的后备别名(Fallback)。即使 AI 传参名称发生漂移也能顺畅执行后续流程,大幅提升了对大模型无规律输出错漏的容错率。
|
||||
|
||||
### 2. MCP 请求日志全览解析 (Full Arguments Logging)
|
||||
|
||||
- **问题**: 现有的面板调试终端在记录 AI 工具调用时,只有指令头如 `REQ -> [manage_components]`,无法透视 AI 实际上到底提交了哪些参数。致使类似参数名称写错的幽灵 Bug 极难被常规察觉。
|
||||
- **优化**: 修改了 `main.js` 中的 `/call-tool` 路由逻辑。现在系统拦截不仅会记录动作名称,还会将完整的 `arguments` 以 JSON 序列化的形态连同日志一并输出在面板中:例如 `参数: {"nodeId":"...","operation":"get"}`。
|
||||
- **保护机制**: 为防止类似多边形顶点数据等过大的参数体撑爆编辑器控制台缓存或导致 UI 卡顿,日志处理对超过 500 个字符长度的序列化结果启用了自动截断显示 (`...[Truncated]`)。
|
||||
|
||||
### 3. `manage_components` 类型安全与防呆校验
|
||||
|
||||
- **问题**: 某些不聪明的 AI 会混淆节点树和组件系统,在调用 `manage_components` (action="add") 时错误地将 `cc.Node` 或其他不合法的类名当作组件名传入,导致底层引擎抛出 `Cannot read property 'constructor' of null` 的深层报错并引发 AI 陷入死循环重试。
|
||||
- **修复**: 在 `scene-script.js` 层加固了前置拦截规则:
|
||||
1. **直接拦截节点**: 当检测到传入 `cc.Node` 或 `Node` 作为组件类型时直接驳回,并返回富含指导意义的中文提示词(如“请使用 create-node 创建节点”)。
|
||||
2. **继承链校验**: 提取引擎类定义后,强制要求通过 `cc.js.isChildClassOf` 判断该类必须继承自 `cc.Component`。若不合法则即时截断并提示。
|
||||
- **价值**: 通过将冰冷的底层异常翻译为"手把手教 AI 怎么重试"的指导性异常,彻底根治了 AI 在操作组件时乱认对象、反复撞墙的通病。
|
||||
|
||||
---
|
||||
|
||||
## 面板加载修复 (2026-02-24)
|
||||
|
||||
### 1. `panel/index.js` 语法错误修复
|
||||
|
||||
- **问题**: 面板加载时出现 `SyntaxError: Invalid or unexpected token`,导致 MCP Bridge 插件面板完全无法渲染。
|
||||
- **原因**: `index.js` 中存在非法字符或格式错误,被 Cocos Creator 的面板加载器拒绝解析。
|
||||
- **修复**: 清理了文件中的语法问题,确保面板能够正常加载和初始化。
|
||||
|
||||
---
|
||||
|
||||
## 防止核心属性被篡改崩溃 (2026-02-26)
|
||||
|
||||
### 1. `manage_components` 核心属性保护
|
||||
|
||||
- **问题**: AI 助手在使用 `manage_components` 尝试修改 `Label` 位置时,错误地对组件传参 `{ node: { position: ... } }`,导致 Label 的 `this.node` 强引用被覆写为普通对象。引发渲染报错 (`Cannot read property 'a' of undefined`) 和删除卡死 (`this.node._removeComponent is not a function`)。
|
||||
- **修复**: 在 `scene-script.js` 的 `applyProperties` 中增加了核心属性黑名单机制。强制拦截对 `node`, `uuid`, `_id` 的直接写入并给出警告。彻底杜绝由于组件的节点引用被破坏所引发的场景崩溃和编辑器卡死问题。
|
||||
|
||||
### 2. 资源管理层 `save` 动作幻觉别名兼容
|
||||
|
||||
- **问题**: AI 偶尔会幻觉以为 `prefab_management`/`manage_script`/`manage_material`/`manage_texture`/`manage_shader` 的更新动作为 `save`,而不是标准定义的 `update` 或 `write`,导致抛出"未知的管理操作"报错。
|
||||
- **修复**: 在 `main.js` 所有这些管理工具的核心路由表中,为 `update` 和 `write` 操作均显式添加了 `case "save":` 作为后备兼容,极大地增强了不同大模型在不同提示词上下文环境下的操作容错率。
|
||||
|
||||
---
|
||||
|
||||
## 日志系统持久化与健壮性优化 (2026-02-27)
|
||||
|
||||
### 1. 日志文件持久化
|
||||
|
||||
- **问题**: 插件的所有运行日志只保存在内存中(`logBuffer`),编辑器重启后日志全部丢失,无法进行会话级别的问题回溯。
|
||||
- **优化**: 在 `main.js` 的 `addLog` 函数中新增文件写入逻辑。所有日志实时追加写入项目目录下的 `settings/mcp-bridge.log` 文件(懒初始化路径)。
|
||||
- **实现细节**:
|
||||
- 新增 `getLogFilePath()` 辅助函数,通过 `Editor.assetdb.urlToFspath` 推导项目根目录,将日志存放在 `settings/` 子目录中。
|
||||
- 日志格式统一为 `[时间戳] [类型] 内容`,与面板日志保持一致。
|
||||
- 文件写入使用 `fs.appendFileSync` 同步追加,失败时静默不影响主流程。
|
||||
|
||||
### 2. 日志缓冲区内存保护
|
||||
|
||||
- **问题**: 长时间运行的编辑器会话中,`logBuffer` 数组无限增长,最终导致内存压力。
|
||||
- **优化**: 在 `addLog` 中增加上限检查,当日志条数超过 2000 时自动截断旧日志,仅保留最近 1500 条。
|
||||
|
||||
### 3. 请求关联计数器 (`_requestCounter`)
|
||||
|
||||
- **优化**: 新增全局 `_requestCounter` 变量,为每个 HTTP 请求分配唯一的自增序号,便于在高并发场景下追踪同一请求的完整生命周期(从入队到执行到响应)。
|
||||
|
||||
### 4. CommandQueue 兜底超时保护
|
||||
|
||||
- **问题**: 原有的 `processNextCommand` 队列机制依赖每个指令主动调用 `done()` 回调来释放队列。如果某个工具函数内部逻辑异常导致 `done()` 未被调用,整个队列将永久停滞。
|
||||
- **优化**: 在 `enqueueCommand` 中为每个入队指令注册 60 秒兜底超时定时器 (`setTimeout`)。超时后强制释放队列位置并记录错误日志 `[CommandQueue] 指令执行超时(60s),强制释放队列`,确保后续指令不被阻塞。
|
||||
- **正常路径**: 指令正常完成时通过 `clearTimeout` 取消定时器,无额外开销。
|
||||
|
||||
### 5. 日志仅输出关键信息到编辑器控制台
|
||||
|
||||
- **优化**: `addLog` 函数不再将所有类型的日志输出到编辑器控制台,仅 `error` 和 `warn` 级别日志通过 `Editor.error()` / `Editor.warn()` 输出,防止 `info` / `success` / `mcp` 类型日志刷屏干扰开发者。
|
||||
|
||||
---
|
||||
|
||||
## 性能与可靠性优化 (2026-02-28)
|
||||
|
||||
### 1. CommandQueue 超时保护恢复
|
||||
|
||||
- **问题**: 合并冲突解决时 `enqueueCommand` 中的 60 秒兜底超时保护代码丢失,导致如果工具函数内部异常未调用 `done()`,整个指令队列将永久停滞,后续所有操作将卡死不再响应。
|
||||
- **修复**: 在 `enqueueCommand` 中为每个入队指令注册 `setTimeout(60000)` 超时定时器,正常完成时通过 `clearTimeout` 取消。
|
||||
|
||||
### 2. HTTP 请求体大小限制
|
||||
|
||||
- **问题**: `_handleRequest` 中 `body += chunk` 无上限保护,超大请求体(恶意或异常客户端)可能耗尽编辑器进程内存。
|
||||
- **修复**: 新增 5MB (`5 * 1024 * 1024`) 请求体上限,超出时返回 HTTP 413 并销毁连接。
|
||||
|
||||
### 3. 日志文件轮转机制
|
||||
|
||||
- **问题**: `settings/mcp-bridge.log` 文件持续追加写入,长期使用会无限增长占用磁盘空间。
|
||||
- **修复**: 在 `getLogFilePath()` 初始化时检查文件大小,超过 2MB 自动将旧日志重命名为 `.old` 备份后创建新文件。
|
||||
|
||||
### 4. 清理冗余调试日志
|
||||
|
||||
- **问题**: `scene-script.js` 中 `update-node-transform` 和 `applyProperties` 共有 8 处 `Editor.log` 调试日志,每次操作都输出到编辑器控制台造成刷屏。
|
||||
- **修复**: 移除所有冗余 `Editor.log` 调试输出,保留必要的 `Editor.warn` 警告(如资源加载失败、属性解析失败等)。
|
||||
|
||||
### 5. `applyProperties` 逻辑修复
|
||||
|
||||
- **问题**: `applyProperties` 启发式资源解析分支中使用了 `return` 而非 `continue`,导致处理到该分支后会直接退出整个 `for...of` 循环,跳过后续属性的设置。
|
||||
- **修复**: 将 `return` 改为 `continue`,确保多属性同时更新时所有属性都能被正确处理。
|
||||
|
||||
### 6. `instantiate-prefab` 统一使用 `findNode`
|
||||
|
||||
- **问题**: `instantiate-prefab` 中查找父节点直接调用 `cc.engine.getInstanceById(parentId)`,绕过了 `findNode` 函数的压缩 UUID 解压与兼容逻辑。
|
||||
- **修复**: 统一改用 `findNode(parentId)`,确保所有场景操作对压缩和非压缩 UUID 格式的兼容性一致。
|
||||
155
docs/注意事项.md
Normal file
155
docs/注意事项.md
Normal file
@@ -0,0 +1,155 @@
|
||||
# Cocos Creator 插件开发注意事项
|
||||
|
||||
## 1. 资源与预制体管理
|
||||
|
||||
### 1.1 禁止手动干预 `.meta` 文件
|
||||
|
||||
- **问题**:手动使用 `manage_asset` 创建或修改以 `.meta` 结尾的文件会导致编辑器报错(如 `Invalid assetpath, must not use .meta as suffix`)。
|
||||
- **原因**:Cocos Creator 资源数据库会自动识别新资源并生成对应的 `.meta` 文件。外部强行介入会破坏资源索引一致性。
|
||||
- **最佳实践**:始终使用高级资源工具(如 `prefab_management`)来处理资源,让编辑器自行管理 `.meta` 文件。
|
||||
|
||||
### 1.2 预制体的正确创建流程
|
||||
|
||||
- **推荐工具**:使用 `prefab_management` 的 `create` 操作。
|
||||
- **核心逻辑**:该工具会同步处理节点的序列化、db 路径映射以及资源刷新(Refresh),确保预制体及其配套的 `.meta` 文件原子化生成。
|
||||
|
||||
---
|
||||
|
||||
## 2. 脚本属性(Inspector)关联
|
||||
|
||||
### 2.1 路径与 UUID 的区别
|
||||
|
||||
- **问题**:在 Inspector 面板中,脚本属性(如 `cc.Prefab` 或 `cc.Node`)若通过路径关联,经常会出现 "Type Error"。
|
||||
- **原因**:编辑器 Inspector 期望获得的是引擎内部的对象引用。虽然 `db://` 路径可以指向文件,但在属性赋值层面,编辑器无法自动将字符串路径转换为对应的类实例。
|
||||
- **最佳实践**:
|
||||
1. 通过 `manage_asset -> get_info` 获取资源的 **UUID**。
|
||||
2. 在调用 `manage_components -> update` 时,**优先使用 UUID** 进行赋值。
|
||||
3. UUID 是底层唯一标识,能确保编辑器精准识别资源类型并正确完成引用链接。
|
||||
|
||||
---
|
||||
|
||||
## 3. 场景同步与编辑器状态
|
||||
|
||||
### 3.1 刷新与编译
|
||||
|
||||
- **注意事项**:创建新脚本后,必须调用 `manage_editor -> refresh_editor` 或等待几秒钟以触发编译。
|
||||
- **风险**:在脚本编译完成前尝试将其作为组件添加到节点,会导致 `添加组件失败: Cannot read property 'constructor' of null` 或找不到脚本组件的问题。
|
||||
|
||||
### 3.2 节点删除 (IPC 协议)
|
||||
|
||||
- **正确协议**:应使用 `Editor.Ipc.sendToMain('scene:delete-nodes', uuid_or_array)`。
|
||||
- **注意**:不要误用 `scene:delete-selected`,因为它在某些版本的编辑器底层不接受参数或行为不一致。
|
||||
- **技巧**:在 `mcp-bridge` 中,调用 `execute_menu_item("delete-node:NODE_UUID")` 会走场景脚本的直连删除,而 `execute_menu_item("Delete")` 则会走主进程的 `scene:delete-nodes` 并自动带上选中的节点。
|
||||
|
||||
---
|
||||
|
||||
## 4. MCP Bridge 源码补丁说明
|
||||
|
||||
### 4.1 属性解析增强 (Asset 序列化修复)
|
||||
|
||||
- **改进点**:在 `scene-script.js` 的 `applyProperties` 中通过 `cc.AssetLibrary.loadAsset` 解决了资源属性在 Inspector 报错 "Type Error" 的问题。
|
||||
- **原理**:
|
||||
- **问题根源**:在场景进程中直接将 UUID 字符串赋给资源属性(如 `comp.prefab = "uuid"`),会导致 `.fire` 文件将其保存为纯字符串而非对象格式。编辑器 Inspector 期望的是资源引用结构 `{ "__uuid__": "..." }`,类型不匹配产生 Type Error。
|
||||
- **修复逻辑**:
|
||||
1. **真实加载**:使用 `cc.AssetLibrary.loadAsset(uuid, callback)` 在场景进程中异步加载真实的资源实例。
|
||||
2. **实例赋值**:在回调中将加载到的 `asset` 对象赋予组件(`component[key] = asset`),这确保了场景保存时能生成正确的序列化对象。
|
||||
3. **UI 同步**:同步发送 IPC `scene:set-property`,使用 `{ uuid: value }` 格式通知编辑器面板更新 Inspector UI。
|
||||
- **Node/Component**: 对于节点 or 组件引用,通过 `findNode` 查找实例并直接赋值实例对象,而非 UUID 字符串。
|
||||
|
||||
---
|
||||
|
||||
## 5. AI 操作安全守则 (Subject Validation Rule)
|
||||
|
||||
### 5.1 确定性优先
|
||||
|
||||
- **核心法则**:任何对节点、组件、属性的操作,都必须建立在 **“主体已确认存在”** 的基础上。
|
||||
- **具体流程**:
|
||||
1. **节点校验**:在操作前必须调用 `get_scene_hierarchy` 确认 `nodeId`。
|
||||
2. **组件校验**:在 `update` 或 `remove` 前必须调用 `manage_components(action: 'get')` 确认目标组件存在。
|
||||
3. **属性校验**:严禁猜测属性名。在 `update` 前,应通过读取脚本定义或 `get` 返回的现有属性列表来确定准确的属性名称。
|
||||
- **禁止行为**:禁止基于假设进行盲目赋值或删除。如果发现对象不存在,应立即报错或尝试重建,而非继续尝试修改。
|
||||
|
||||
### 5.2 传参精准与别名容错
|
||||
|
||||
- **传参风险**:大语言模型在生成 JSON 时可能会出现操作类型字段名“幻觉”(例如在调用 `manage_components` 时将本应是 `action` 的参数写为含义相近的 `operation`)。
|
||||
- **优化机制**:底层脚本 (`scene-script.js`) 已经全面引入参数别名回落机制(如 `action = action || operation`)。
|
||||
- **提示开发**:尽管底层具备一定的容错率,在维护 MCP 工具说明书(Schema)时,仍应严格要求 AI 书写标准参数名,避免纵容产生更大的幻觉偏移。
|
||||
|
||||
---
|
||||
|
||||
## 6. 常见资源关键字
|
||||
|
||||
- **资产识别启发式**:当通过 `manage_components` 赋值时,如果属性名包含以下关键字,插件会尝试将其作为 UUID 资源处理:
|
||||
`prefab`, `sprite`, `texture`, `material`, `skeleton`, `spine`, `atlas`, `font`, `audio`, `data`
|
||||
- **建议**:如果资源未正确加载,请检查属性名是否包含以上关键字,或手动确认该 UUID 不属于任何节点。
|
||||
|
||||
---
|
||||
|
||||
## 7. 搜索工具 (search_project) 使用建议
|
||||
|
||||
- **性能建议**:尽量指定 `path` 参数缩小搜索范围(如 `db://assets/scripts`),避免全项目大面积搜索,尤其是在包含大量旧资源的 Library 目录(虽然插件已过滤)。
|
||||
- **正则表达式**:在使用 `useRegex` 时,确保正则模式的语法正确。如果正则匹配失败,工具会返回详细的错误提示。
|
||||
- **模式选择**:
|
||||
- 查找具体逻辑代码:使用 `matchType: "content"`。
|
||||
- 定位资源文件:使用 `matchType: "file_name"` 并配合 `extensions` 过滤。
|
||||
- 重构目录结构前:使用 `matchType: "dir_name"` 检查目录名冲突。
|
||||
|
||||
---
|
||||
|
||||
## 8. Undo/Redo (撤销/重做) 使用指南
|
||||
|
||||
### 8.1 事务分组
|
||||
|
||||
- **背景**:连续执行多次修改(如同时移动并缩放)时,通常希望一次“撤销”能回滚所有更改。
|
||||
- **最佳实践**:
|
||||
1. 调用 `manage_undo(action: 'begin_group', description: '操作描述')`。
|
||||
2. 执行多次修改(如调用 `update_node_transform`)。
|
||||
3. 调用 `manage_undo(action: 'end_group')`。
|
||||
- **注意**:`undo-record` 需要在 `begin_group` 时明确关联节点 ID,否则可能导致撤销栈无法精准匹配对象。
|
||||
|
||||
### 8.2 属性修改方式
|
||||
|
||||
- **核心规则**:在 `scene-script.js` 中严禁直接使用 `node.x = 100`。
|
||||
- **正确做法**:必须通过 `Editor.Ipc.sendToPanel('scene', 'scene:set-property', ...)`。只有这样,修改才会被 Cocos Creator 的 UndoManager 捕获,从而支持撤销。
|
||||
|
||||
---
|
||||
|
||||
## 9. 并发安全与防卡死机制
|
||||
|
||||
### 9.1 指令队列 (CommandQueue)
|
||||
|
||||
- **背景**:AI 客户端可能在短时间内连续发送多个 MCP 请求(如 `delete-node` → `refresh_editor` → `search_project`),如果并发执行,`AssetDB.refresh()` 等异步重操作会与后续请求产生 I/O 和 IPC 通道冲突,导致编辑器主线程阻塞。
|
||||
- **解决方案**:在 `/call-tool` HTTP 入口处引入 `enqueueCommand` 机制,将所有 MCP 工具调用**串行化**执行。前一个指令的回调完成后,才会出队并处理下一个指令。
|
||||
- **注意事项**:
|
||||
1. 队列在 `processNextCommand` 的 `catch` 块中有防死锁保护,即使某个指令抛出异常也不会永久阻塞后续指令。
|
||||
2. `batchExecute` 内部也已从并行 `forEach` 改为串行链式执行。
|
||||
3. 队列长度会在日志中显示(`REQ -> [toolName] (队列长度: N)`),可用于排查积压问题。
|
||||
|
||||
### 9.2 `refresh_editor` 路径要求
|
||||
|
||||
- **⚠️ 必须带路径**:在调用 `manage_editor` 的 `refresh_editor` 时,务必通过 `properties.path` 指定精确的文件或目录(如 `db://assets/scripts/Test.ts`)。严禁空参数进行全局刷新,在生产项目中会导致数分钟的编辑器卡死。
|
||||
|
||||
### 9.3 IPC 超时保护 (callSceneScriptWithTimeout)
|
||||
|
||||
- **背景**:`Editor.Scene.callSceneScript` 的回调依赖 Scene 面板响应 IPC 消息。如果主线程阻塞,Scene 面板无法处理消息,导致 callback 永远不返回,HTTP 连接堆积。
|
||||
- **解决方案**:所有 `callSceneScript` 调用均通过 `callSceneScriptWithTimeout` 包装,默认 15 秒超时。超时后自动返回错误,释放 HTTP 连接和队列位置。
|
||||
- **日志标识**:超时会记录 `[超时] callSceneScript "方法名" 超过 15000ms 未响应`。
|
||||
|
||||
---
|
||||
|
||||
## 10. Token 消耗与长数据保护防爆机制
|
||||
|
||||
### 10.1 `get_scene_hierarchy` 深度与层级限制
|
||||
|
||||
- **背景**:在一两千个节点的大型 UI 场景中,无限制地获取全场景树会瞬间消耗十万以上的 Token,导致 AI 丢失上下文甚至触发截断报错。
|
||||
- **最佳实践**:
|
||||
- **默认使用 `depth: 2`** (默认限制) 来逐步探查。
|
||||
- **结合 `nodeId` 参数**:找到关键模块(例如 `Canvas/LoginPanel`)的 UUID 后,再单独向该 `nodeId` 请求下一层的结构,而非每次从根部拉取。
|
||||
|
||||
### 10.2 大对象与长数组截断
|
||||
|
||||
- **背景**:在读取某些特定组件数据(如多边形顶点坐标、Sprite 曲线数据或序列化的内联 Base64 图片)时,JSON 可能会异常庞大。
|
||||
- **保护机制**:
|
||||
- `scene-script.js` 内部在执行 `manage_components(get)` 序列化时,对于**长度超过 10 的 Array** 会强制截断,返回字面量字符串 `"[Array(X)]"`。
|
||||
- 对于**长度大于 200 的长字符串**,也会强制缩略并追加 `...[Truncated, total length: X]`。
|
||||
- **应对策略**:如果 AI 看到截断提示,这意味着此处为海量无语义数据,**请勿**尝试盲目通过 `update` 覆盖或还原被截断的字段,极易导致源数据被破坏。请仅修改自己能够完全看清的轻量级属性(如 `name`, `x`, `scale` 等)。
|
||||
Reference in New Issue
Block a user