修复: create_prefab IPC 调用签名错误导致预制体创建失败

- 修复 create_prefab 使用错误的 sendToMain 改为 sendToPanel

- 修复节点 ID 未包裹数组及传入完整路径而非目录路径的问题

- 修复 prefabManagement 的 create 分支中 targetDir 未定义的 Bug

- 更新 UPDATE_LOG.md、注意事项.md、IPC_MESSAGES.md 文档
This commit is contained in:
火焰库拉
2026-02-28 23:07:04 +08:00
parent a2fbc3568f
commit 74d49d79c1
4 changed files with 2641 additions and 2589 deletions

View File

@@ -826,6 +826,18 @@
- **类型**: 主进程监听
- **状态**: 可用
### `scene:create-prefab`
- **用途**: 将场景中的节点保存为预制体资源
- **参数**: 节点UUID数组 (`[uuid]`)、目标目录路径 (db:// 格式,如 `db://assets`)
- **返回值**: 无
- **类型**: 渲染进程监听 (需使用 `sendToPanel("scene", ...)`)
- **状态**: 可用
- **⚠️ 注意事项**:
1. 必须使用 `Editor.Ipc.sendToPanel("scene", "scene:create-prefab", ...)` 而非 `sendToMain`
2. 第一个参数为**数组**(即使只有单个节点也必须包裹在数组中)。
3. 第二个参数为目标**目录路径**(不含文件名),如 `db://assets`。预制体文件名取决于节点名称。
### `scene:new-property`
- **用途**: 创建新属性

View File

@@ -305,3 +305,24 @@
- **问题**: 当 AI 大模型尝试给 `cc.Sprite` 等组件的 `spriteFrame` 属性赋值时,常常会错误传递为其父级 `Texture2D` (原图) 的 UUID。Cocos 引擎由于类型不匹配会导致赋值无效,且静默失败(或陷入 IPC 死锁导致编辑器卡死)。
- **优化**: 在 `scene-script.js` 中的 `applyProperties` 环节新增了类型容错机制。当识别到传入的 UUID 对应 `Texture2D` 但该属性(例如含 `sprite` 关键字)需要 `SpriteFrame` 时,脚本会利用 Node.js `fs` 直接读取对应的 `.meta` 文件,提取出实际子资源 (`SpriteFrame`) 的正确 UUID从而实现自动转换与安全赋值。
- **降级**: 若自动转换失败(如 `meta` 结构改变或读取失败),则会通过 `Editor.warn` 在控制台明确提示类型错误,拦截强制赋值操作,彻底消除潜在的隐性崩溃。
---
## 预制体创建 IPC 调用签名修复 (2026-02-28)
### 1. `create_prefab` IPC 调用方式修复 (`src/main.js`)
- **问题**: `create_prefab` 工具调用创建预制体时,控制台报 `Error: Invalid path: null``TypeError: e.reply is not a function`,预制体创建失败。
- **原因**: 原代码使用了错误的 IPC 调用签名:
-`Editor.Ipc.sendToMain("scene:create-prefab", nodeId, fullFilePath)` — 错误使用了 `sendToMain`,且参数格式不正确。
- **修复**: 修正为 Cocos Creator 2.4.x 的正确签名:
-`Editor.Ipc.sendToPanel("scene", "scene:create-prefab", [nodeId], dirPath)` — 三个关键修正:
1. 使用 `sendToPanel` 而非 `sendToMain`(该消息由 Scene 面板的渲染进程处理)。
2. 节点 ID 必须包裹在数组中 `[nodeId]`(支持多选创建场景)。
3. 第二个参数必须是 **目录路径**(如 `db://assets`),而非完整文件路径(如 `db://assets/XXX.prefab`)。
- **补充**: 创建前先通过 `scene:set-property` 将节点重命名为目标预制体名称,确保生成的 `.prefab` 文件名与节点名一致。
### 2. `prefabManagement` 创建功能 `targetDir` 未定义修复 (`src/main.js`)
- **问题**: `prefabManagement``create` 分支中,`targetDir` 变量在使用时未被定义,导致创建预制体时目录路径为 `undefined`
- **修复**: 在使用前从 `prefabPath` 中正确提取目录路径:`const targetDir = prefabPath.substring(0, prefabPath.lastIndexOf("/"))`

View File

@@ -10,8 +10,13 @@
### 1.2 预制体的正确创建流程
- **推荐工具**:使用 `prefab_management``create` 操作。
- **推荐工具**:使用 `prefab_management``create` 操作,或 `create_prefab` 工具
- **核心逻辑**该工具会同步处理节点的序列化、db 路径映射以及资源刷新Refresh确保预制体及其配套的 `.meta` 文件原子化生成。
- **⚠️ IPC 签名要点**:底层使用的 `scene:create-prefab` 消息有严格的参数格式要求:
1. 必须使用 `Editor.Ipc.sendToPanel("scene", ...)` 而非 `sendToMain`(该消息由 Scene 面板渲染进程处理)。
2. 节点 ID 必须包裹在**数组**中:`[nodeId]`
3. 第二个参数必须是 **db:// 目录路径**(如 `db://assets`),而非完整文件路径。
4. 预制体文件名取决于节点名称,因此创建前需先通过 `scene:set-property` 重命名节点。
---

View File

@@ -1155,11 +1155,23 @@ module.exports = {
});
break;
case "create_prefab":
const prefabUrl = `db://assets/${args.prefabName}.prefab`;
Editor.Ipc.sendToMain("scene:create-prefab", args.nodeId, prefabUrl);
case "create_prefab": {
const prefabDir = "db://assets";
// 先重命名节点以匹配预制体名称
Editor.Ipc.sendToPanel("scene", "scene:set-property", {
id: args.nodeId,
path: "name",
type: "String",
value: args.prefabName,
isSubProp: false,
});
// scene:create-prefab 的正确签名: ([nodeUuids], dirPath)
setTimeout(() => {
Editor.Ipc.sendToPanel("scene", "scene:create-prefab", [args.nodeId], prefabDir);
}, 300);
callback(null, `命令已发送:正在创建预制体 '${args.prefabName}'`);
break;
}
case "open_scene":
isSceneBusy = true; // 锁定
@@ -1623,6 +1635,8 @@ export default class NewScript extends cc.Component {
if (Editor.assetdb.exists(prefabPath)) {
return callback(`预制体已存在: ${prefabPath}`);
}
// 从完整路径中提取 db:// 目录路径
const targetDir = prefabPath.substring(0, prefabPath.lastIndexOf("/"));
// 确保父目录存在
const absolutePath = Editor.assetdb.urlToFspath(prefabPath);
const dirPath = pathModule.dirname(absolutePath);