prefab-script
用 TypeScript 脚本读写 Cocos Creator 3.8 的 .prefab 文件。
适合把这件事交给 AI 或自己写构建脚本:不要手改 prefab JSON,也不要让模型直连编辑器拖节点。
English
Github: https://github.com/chhmomoyu/prefab-script
它解决什么问题
Creator 的 .prefab 是一份带 __id__ 交叉引用的 JSON。人可以在编辑器里拖;程序或大模型去改这份 JSON,很容易把引用写坏(嵌套预制体展开失败、节点被挂到 Scene 上、保存时报循环引用等)。
思路是加一层转接:
-
你(或 AI)只写「建节点、贴图、套现成模板、保存」
-
库负责编号、组件、图集 uuid、嵌套实例格式
-
save()写出标准.prefab+.meta -
Creator 刷新后打开,和手拖出来的资源一样
它不是编辑器扩展,不启动 Creator,不走场景 IPC。就是 Node 脚本 + 文件。
写脚本 → PrefabDoc 内存模型 → 写出 .prefab → Creator 打开
环境
-
Cocos Creator 3.8(在 3.8.7 上验证)
-
Node.js 18+
-
库放在工程里即可,例如
extensions/prefab-script/(即便在 extensions 目录,也不用在扩展管理器里启用)
cd extensions/prefab-script
npm install
npm test
快速开始
完整可运行示例:examples/create-demo.ts
cd extensions/prefab-script
npm install
npx ts-node examples/create-demo.ts
会生成 examples/out/DemoWin.prefab(不依赖业务图集)。把脚本里的 out 改到工程 assets/ 下,Creator 刷新后即可打开。
贴图、套顶栏等写法见下文 API;instantiateSample 需要你自己的模板目录(默认 assets/sample_UI/)。
两种搭法
| 方式 | API | 文件里实际有什么 |
|------|-----|------------------|
| 真的造节点 | createChild + setSprite / setLabel | 这份 prefab 里完整的 Node / Sprite / Label |
| 套现成模板 | instantiateSample("title_top") | 只写嵌套实例:指向已有 prefab 的 uuid,打开时由 Creator 展开 |
第二种不会复制模板里的子节点。像 Word 插入页眉:文档里存引用,打开时再展开。因此:
-
不要对实例再
createChild(没有可写的_children) -
改坐标用创建时传入
position,或之后setPosition(走属性覆盖) -
save()会把所有嵌套实例登记到根节点的nestedPrefabInstanceRoots。缺这一项时,编辑器展开失败,可能出现Converting circular structure to JSON
模板默认从工程的 assets/sample_UI/<名字>.prefab 读取。没有这个目录就把自己的常用弹窗、顶栏、按钮做成预制体放进去,或改 src/instantiate.ts 里的路径。
API 摘要
PrefabDoc
| 方法 | 作用 |
|------|------|
| create(name, path) | 新建。根节点默认 1080×1920,Widget 四边距 0(alignFlags = 45),带 BlockInputEvents |
| load(path) | 打开已有 prefab |
| createChild(name, options) | 在根(或 options.parent)下建子节点 |
| instantiateSample(name, options) | 嵌套实例化 sample_UI |
| applyRootLayout() | 给旧文件补根布局 |
| dumpTree() | 打印节点树,便于自检 |
| save() | 写 .prefab;没有 .meta 时补一份 |
PrefabNode
| 方法 | 作用 |
|------|------|
| setPosition / setSize / setScale / setAnchor | 变换与尺寸 |
| setSprite(path 或 uuid) | 散图:读对应 .meta 的 sprite-frame |
| setSpriteFrame(图集名, 帧名) | 从图集 .plist.meta 查帧 |
| setOpacity | Sprite 透明度 0–255 |
| setLabel / setLabelSize | 文本 |
| setWidget | Widget 边距 |
| addComponent / getComponent | 组件 |
支持的组件:UITransform、Sprite、Label、Button、EditBox、Widget、BlockInputEvents。
查图集
npx ts-node src/cli.ts atlas <图集短名>
npx ts-node src/cli.ts dump path/to/Xxx.prefab
npx ts-node src/cli.ts get path/to/Xxx.prefab 节点名
setSpriteFrame("图集短名", "帧名") 会在 src/assets.ts 配置的目录里找 .plist.meta。默认带了一组常见路径(assets/ui3/common 等),换成你工程的图集目录。帧名以 meta 里 subMetas[].name 为准。
接到你自己的工程
-
根画布默认 1080×1920:改
factories.ts的ROOT_SIZE,或create()之后setSize -
模板目录:改
instantiate.ts的SAMPLE_DIR(默认assets/sample_UI/) -
图集搜索路径:改
assets.ts -
写出路径落在
assets/下时会自动识别工程根;否则设doc.projectRoot
硬性规则
-
不要手改
.prefab文本,不要自己排__id__。 -
只追加对象,保存时不要重排已有
__id__(load后再改也遵守这一点)。 -
嵌套实例上不要
createChild。 -
生成后在 Creator 里打开看一眼。
dumpTree()只能检查结构和尺寸,看不出贴图对不对。
局限
-
不覆盖 ScrollView、Layout、Mask、自定义脚本组件等。需要的话可对
getComponent拿到的对象改字段,或扩展factories.ts。 -
不能替代编辑器做视觉微调、动画、预制体关联。
-
给 AI 用时,建议再写一份项目内的 Skill / 规范(画布尺寸、模板清单、图集目录),否则模型仍会猜帧名。
目录
prefab-script/
src/prefab-doc.ts # 对外 API
src/factories.ts # 节点 / 组件 JSON
src/instantiate.ts # 嵌套预制体
src/assets.ts # 图集与 .meta
src/cli.ts # dump / atlas
examples/create-demo.ts

