关于 creator-hub-mcp
creator-hub-mcp 是面向 Creator Hub 场景编辑的技能说明,指导 Agent 通过 MCP 操作编辑器中的实时场景,并遵循安全的场景修改流程。它还涵盖资源、智能物件目录和文件处理规则。
主要功能
- 01通过 MCP 编辑实时场景
- 02优先查找并放置智能物件
- 03处理提示词附件与本地资源
- 04遵循可撤销的场景修改流程
适用场景
- 01在 Creator Hub 中添加或修改场景实体
- 02将用户提供的模型或图片用于场景
- 03判断何时连接 MCP 或编辑文件
MCP 相关
Creator Hub 在应用内运行 MCP 服务,提供读取和修改打开场景的工具;内置 AI 助手及外部 MCP 客户端均可使用。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ decentraland/ sdk-skills --skill creator-hub-mcp安装后在 Claude Code 中输入/creator-hub-mcp确认已加载。
附带文件reference/connect.md
详细介绍
Creator Hub MCP — 实时场景编辑
Creator Hub 在应用内运行 MCP 服务(localhost、可流式传输的 HTTP、Bearer 令牌)。其工具可读取和修改编辑器中打开的场景:更改会应用到实时引擎,立即显示在视口中,自动保存到 assets/scene/main.composite,并且每项更改都会成为用户可撤销的常规步骤。同一服务也为 Creator Hub 内置的 AI 助手提供支持,并可开放给任何支持 MCP 的外部工具。
你可能处于以下两种运行方式之一:
| 你所处的位置…… | 工具如何连接到你 |
|---|---|
| 在 Creator Hub 的 AI 助手中(Settings > AI > Enable AI Assistant;自 Creator Hub 0.50.0 起默认启用——不再是实验性功能) | 已预先接好。应用会启动你的 claude / codex / cursor-agent / gemini CLI,并将服务注册为 creator-hub,把这些技能链接到场景中,并注入与此技能相同的规则。四种提供方均无需进行任何设置。 |
| 在其他工具中(Claude Code 终端或 VS Code 扩展、Cursor、Codex、Claude Desktop,……) | 连接到正在运行的 Creator Hub——请参阅 reference/connect.md。用户从 Settings > AI > Expose AI assistant MCP server 复制 JSON 片段。此处不会为你接入技能——请参阅技能的来源。 |
在 Claude Code 中,工具显示为 mcp__creator-hub__<tool>;在 Creator Hub 的助手和其他客户端中,它们以原始名称显示(scene_state、create_entity,……)。已连接的工具会自我描述——请以实时目录为准,而非下表。
用户附加到提示词的文件
在 Creator Hub 的助手中,用户可以在一轮对话中附加文件(creator-hub 3395b643):输入框左侧的Attach files回形针按钮会打开多选器;文件可以拖到输入框上(覆盖层提示:Drop files to attach);也可以从剪贴板粘贴图像。附件会显示为可移除的标签;每条提示词最多 8 个。这对你意味着:
- 从磁盘选择或拖入的文件会以真实的绝对路径传入——不会复制文件、进行 Base64 往返转换,也没有大小限制。请直接读取文件;不要让用户重新粘贴文件内容,或将文件移入项目。粘贴的(剪贴板)图像没有路径,因此应用会将其写入临时文件,并将该路径传给你。
- **接受任何文件类型。**应用只会根据文件类型为标签图标分类:
image(png、jpg、jpeg、gif、webp、bmp、svg、avif)、model(glb、gltf)、audio(mp3、wav、ogg、m4a、flac),其他文件均为file。 - **这是交接参考图像或 GLB 的自然方式。**拖入的
.glb是用户想放入场景的模型:它仍在项目外部,因此在通过GltfContainer引用之前,请先将其复制到assets/Models/下(边界框和碰撞体审查请参阅 add-3d-models)。参考图像通常用于说明 UI 或材质的艺术方向,而不是要导入的文件。 - 提示词可能只有附件而完全没有文字——附件本身就是请求。请询问用户要如何处理,不要自行猜测。
用户从 Local Assets 面板提及的资源
第二种不同的通道(creator-hub d25eff1b8):在检查器的 Local Assets 面板中双击资源(树状视图或卡片),会将其作为标签附加到下一条提示词中,紧挨着实体选择项。多项资源和当前选择可以一并附加到一条提示词;发送后或聊天关闭时,提及内容会清除。该资源在本轮中以 [Editor context] 的形式传入,因此:
- 被提及的文件会以项目相对路径的形式传入,且已存在于场景中——直接引用,不要复制或重新导入。
- 被提及的内置化身动画会以名称而非路径的形式传入:它没有对应文件。使用
triggerEmote({ predefinedEmote: '<name>' })播放(参见 avatar-animations)。寻找对应的.glb文件正是此通道旨在避免的错误做法。 - 标签只是指针,不是指令。即便带有标签,“这个”仍需要一个动词——如果请求含糊不清,请先询问。
规则 — 更改场景图时应使用 MCP;文件只是后备方案
**Creator Hub MCP 可用时,绝不要手动写入 assets/scene/main.composite、main.crdt 或 scene.json。**原因如下,均已在 Creator Hub 源码中验证:
- 这些文件由编辑器管理。每次自动保存时(任何编辑器事务后约 100 ms),编辑器都会根据内存中的引擎状态完整重新生成
main.composite,且不会重新读取磁盘上的文件。对已打开场景进行的手动编辑会悄无声息地丢失;不会报错。 - 这些工具会处理文件工作流中需要手动完成的记录工作:
inspector::Nodes注册、core-schema::Name、inspector::TransformConfig、entity-names.ts、实体 ID 分配,以及非核心组件上的jsonSchema。 - 用户可以撤销每次更改(Ctrl+Z / 助手的撤销 AI 更改按钮)。文件编辑无法撤销。
决策顺序——选择第一个符合条件的条目:
- 工具存在且能正常响应(
get_selection或get_scene_settings能返回结果——使用路由到编辑器的工具进行探测,而非scene_state;即使场景已打开,外部客户端调用scene_state也会返回No scene is open.;参见“注意事项”)→ 所有实体、组件和设置更改都使用这些工具。仅将磁盘上的 composite 作为只读交叉检查。 - 工具存在但无法正常工作(
No editor window is open.、连接被拒绝、401)→ Creator Hub 已关闭、已重启(URL 和令牌会在每次启动时轮换),或没有打开场景。说明这一点,并请用户在 Creator Hub 中打开场景(或重新复制连接代码片段)。不要悄悄退回到直接编辑文件。 - 工具不存在,但用户有 Creator Hub → 告知用户 MCP 是安全的做法,并引导他们查看
reference/connect.md。只有用户拒绝时,才手动编辑文件;且必须先在 Creator Hub 中关闭场景(此时应全面遵循 composites 技能的编辑模式规则)。如果场景已打开或可能处于打开状态,请列出三个选项——关闭场景、连接 MCP,或明确接受在代码中构建静态实体(这些实体在编辑器中不可见)——并等待用户答复;先完成不依赖这些选项的工作。绝不要自行选择代码后备方案,即便是在非交互会话中也不行:在 2026-10-23 的一次会话中,系统没有询问用户,而是在src/中构建了整个房间,结果遭到创作者拒绝。权威规则:sdk-scenes → Agent Behavioral Guidelines,第 5 项。 - 不涉及 Creator Hub(仅 CLI 的项目、CI)→ 适用 composites 技能的文件工作流。
仍可直接在文件中编辑的内容:src/**(场景代码;保存后会自动触发重新构建)、assets/Scripts/*.tsx(脚本组件——写入文件后再调用 attach_script),以及你添加到 assets/Models/、assets/Images/ 等目录下的资源文件。
静态几何应由编辑器管理,而不是放在 src/ 中。 墙壁、地板、家具和道具——无论是基础几何体还是 GLB——都应通过这些工具放入场景(create_entity + set_component MeshRenderer / GltfContainer,或 place_smart_item),绝不能在场景代码中调用 engine.addEntity()。用代码构建的房间会在预览中渲染,但在 Hub 的视口和实体树中不可见,也无法选中,创作者的第一个问题就是“我的办公室在哪?”(2026-10-08:需要重做,大约要调用 60 次 set_component)。这是 sdk-scenes 的组合优先规则,通过 MCP 实施。没有 MCP 但场景已打开时也一样:停下来询问(梯级第 3 行)——只有创作者明确选择时,才可以接受用代码构建静态几何体(2026-10-23:一次会话未经询问,就用代码构建了房间、一把椅子和约 60 个道具;创作者说:“未经警告,绝 NEVER 这样做。”)。
保存并不能证明运行中的 bundle 包含了你的改动。 预览的开发服务器(sdk-commands start)会监视 src/**,并在每次保存时重写 bin/index.js(位于 @dcl/sdk-commands 的 logic/bundle.ts)。开发服务器运行时,手动执行 sdk-commands build 也会写入同一个文件,两者会发生竞争;如果恰好在编辑过程中保存,就会打包一半写好的代码(出现 SyntaxError,场景卸载)——unity-explorer-mcp 中的每次改动只写入一次规则同样适用。如果你改动的内容没有显示在游戏世界中,调试场景之前先在 bin/index.js 中用 grep 搜索编辑内容中的字符串字面量;如果找不到,就触碰该文件,并等待下一条 Bundle saved。(2026-10 会话:一个 Agent 声称改动已完成,但过时的 bundle 中根本没有该改动;创作者发现了这一点。)
规则 — 手动构建任何标准对象前,先搜索目录
创建实体并使用 create_entity + set_component 手动组装其组件前,始终先执行 search_catalog,检查目录中是否已有该对象的 Smart Item。尤其适用于:
- 灯具 — 目录的
lights类别中有 Spotlight 和 Point Light Smart Item,内含真实 GLB 模型、预配置的LightSource组件,以及内置的 Turn On / Turn Off / Toggle 操作。手动创建LightSource实体会缺少可视模型、检查器集成和操作连线。 - 交互式家具 — 门、椅子、平台、箱子、按钮、拉杆等。较新的脚本型物品:Floor Pressure Button(
buttons,任何人站在上面时都会按下,默认在玩家之间共享)、Button Pedestal(buttons)、Lab Vault Door / Lab Capsule Door(doors)、Lab Stair Platform(platforms,活塞)、Water Plane / Water Cylinder(materials,玩家进入时产生水花)。 - 媒体 — 屏幕、图像显示器、NFT 画框。
- 触发器 — 触发区域、点击触发器。
utils类别中恰好只有一个名为 "Trigger Area"(e9fa0eab-44de-4efe-af77-a71171a1a73f)的条目,这是一个脚本型物品:用户可以放置并调整其大小的不可见方框或球体,带有一个控件,可将描述进入/离开时应发生什么的提示词填入 AI 助手的编辑框。旧的同名非脚本物品(1ab2733f-1782-4521-9eda-6aa8ad684277)和过渡标签 "Trigger Area (Script)" 均已在 creator-hube43441b5中移除;不要搜索它们。
place_smart_item 会处理手动调用 set_component 时遗漏的所有样板工作:
- 下载物品的 GLB 文件,并将
asset-packs::Placeholder解析为磁盘上的真实路径(例如assets/asset-packs/spotlight/spotlight.glb)。 - 设置
asset-packs::Script、asset-packs::Actions和inspector::Config组件,让物品在 Creator Hub UI 中能够正常工作,并支持配置操作和触发器。 - 自动将实体注册到
inspector::Nodes。
仅在目录中没有符合需求的物品时才手动构建。
如果用户已有媒体文件,请告诉他们将文件从 Local Assets 选项卡拖到视口中。 自 creator-hub 062ed0a2 起,这是最快的方式,并且生成的是指向用户文件的目录物品,而不是裸组件 — 实体会带有与手动放置物品相同的组件集和 basic-view inspector::Config:
| 拖入的文件 | 生成的物品 | 会重新指向的内容 |
|---|---|---|
.png / .jpg / .jpeg | Image(37460a1e-affc-4f87-b725-118cc11d86fc) | Material PBR 纹理的 src;平面还会被抬高 +0.5 m,使其立在地面上,而不是半埋在地里 |
.mp3 / .ogg / .wav | Ambient Sound - Forest Birds(5c8b4646-6ec0-41a0-8e9b-415a58728a9e) | AudioSource.audioClipUrl |
.mp4 | Video Screen(0201653b-bd38-48af-b9ef-a902a7e8bc9c) | VideoPlayer.src 以及 asset-packs::VideoScreen.defaultURL — 管理员消息总线会在运行时根据 defaultURL 重新设置 src,因此只设置 src 会被悄然还原 |
实体名称取自文件名(去掉扩展名),并会与现有名称去重;导入时会跳过模板自带的占位媒体文件。.glb / .gltf 仍会作为普通模型拖入。你可以通过工具复现此操作(对同一资产 ID 调用 place_smart_item,然后对上述字段调用 set_component),但拖放只需用户一个动作 — 用户在键盘前时,优先采用这种方式。
工具目录
名称是在 creator-hub 服务(packages/creator-hub/main/src/modules/scene-mcp.ts)上注册的名称。
| 分组 | 工具 | 功能 |
|---|---|---|
| 读取 | get_project_info | 获取 scene.json 元数据(名称、地块、基地区域、生成点)、SDK 版本和依赖项。用于第 0 步确定边界。 |
| 读取 | scene_state | 已创建实体列表:id、名称、类型、世界变换、组件列表、GLTF src、Smart-Item 标志。最多显示前 200 个实体。 |
| 读取 | entity_detail | 按 id 或 Name 查看某个实体上的所有组件值。在调用 set_component 前,使用它了解组件的确切结构。 |
| 读取 | get_selection | 获取编辑器中当前选中的实体。执行操作前,用它解析“这个”/“选中的那个”。Scene 根节点永远不会被报告(creator-hub d25eff1b8):如果只选中了根节点,结果会为空,与未选中任何内容时完全相同。因此,结果为空并不表示用户取消了所有选择,而且“这个”仍可能指整个场景。Player 和 Camera 会正常报告。 |
| 读取 | get_scene_metrics | 获取实时预算(三角形、实体、物理体、材质、纹理)与场景限制的对比,以及超出边界的实体。 |
| 读取 | editor_screenshot | 编辑器视口截图(无需预览)。 |
| 修改 | create_entity | 创建新实体,可选指定 name 和 parent id。返回实体 id。 |
| 修改 | remove_entity | 删除实体及其子实体。 |
| 修改 | set_parent | 重新设置父级(保留世界位置)。parent: 0 表示场景根节点。 |
| 修改 | set_component | 创建或更新组件。component 接受简写(Transform)或完整名称(core::GltfContainer);value 与复合数据存储的 JSON 相同。更新时,传入的键会合并。 |
| 修改 | remove_component | 按名称移除组件。 |
| 资源 | search_catalog | 按名称/类别/标签搜索 Creator Hub 资源包目录。虽然名称如此,它同时涵盖静态物品和 Smart Items。省略 query 可列出所有内容。类别包括 buildings(完整建筑,列在 structures 之后)和 materials(Water Plane/Water Cylinder 物品),以及 Avatar Animations 资源包(45 个 _emote.glb 动画片段 + 32 个内置表情名称)——仅文件资源,参见 place_smart_item。这些新增内容也离线收录于 add-3d-models → references/asset-pack-catalog.md 和 avatar-animations → references/animation-catalog.md。**名称、类别、标签和说明文字都是生成的元数据,并非预览:**搜索 "man" 时,search_catalog 会返回 Human(decorations,标签为 man, person, figure, humanoid…,说明文字为 "Human figure in mid-action"),但它的 GLB 实际上是用 3D 字母拼成的单词 HUMAN(packs/cyberpunk/assets/human/Word_Human.glb,creator-hub origin/main 2026-10-19;在 2026-10-12 的会话中被当作角色放置)。放置尚未看过的物品前,请查看其 thumbnail.png——下载后位于 assets/asset-packs/<pkg>/ 下,与 data.json 同目录;或在 creator-hub 仓库的 packages/asset-packs/packs/<pack>/assets/<item>/ 下查看——也可以使用 add-3d-models 中的 GLB 包围盒审计功能。 |
| 资源 | place_smart_item | 按 assetId 在世界 position 放置目录中的物品(默认为 8,0,8)。将物品文件下载到 assets/asset-packs/<pkg>/ 并生成实体——Smart Items 会自带行为。现在大多数物品都以 asset-packs::Script 代码的形式提供(没有 Triggers);请通过 Script 的参数进行配置,并通过可选的 ActionCallback 参数连接“When X”钩子。参见 script-components。不接受仅文件资源(Avatar Animations 资源包中没有可放置的实体):对于内置表情,错误信息会指出应使用的 triggerEmote({ predefinedEmote }) 调用;对于动画片段,请用户将卡片拖到视口中(会将文件添加到 assets/asset-packs/<pkg>/,但不创建实体),或按照 avatar-animations → references/animation-catalog.md 下载,然后通过代码中的 triggerSceneEmote 播放。 |
| 脚本 | attach_script | 添加指向文件的 asset-packs::Script 组件。先编写文件(放在 assets/Scripts/ 下),再调用此工具。priority 为可选项。 |
| 设置 | get_scene_settings / set_scene_settings | 读取/更改 scene.json 字段(名称、描述、类别、标签、年龄分级、生成点、天空盒、地形、layout.parcels、标志)。每个传入字段都会整体替换当前值——请先读取。绝不能向它传入 spawnPoints:它的输入采用 scene.json 格式,会未经转换地写入元数据组件,导致数据层失效或在 scene.json 中写入 "position": {}——请改用 set_component 在实体 0 上写入生成点,参见下方的数据层规则。此工具的输入模式中不包含 thumbnail(thumbnail 键会被静默丢弃)——请用 set_component 在实体 0 的 inspector::SceneMetadata-v* 上设置,或在编辑器的 Scene settings → Thumbnail 中设置;切勿将封面写入 assets/Images/autogenerated-thumbnail.png:参见注意事项。 |
| 预览 | launch_preview、preview_status、stop_preview | 在启用 MCP 服务的 Decentraland Explorer 中启动/轮询/停止场景。 |
| 预览 | explorer_<name>(动态)、explorer_call | 预览运行时,Explorer 的运行时工具(explorer_screenshot、explorer_walk、explorer_click_entity、explorer_get_scene_logs,等等)会实时注册;如果这些工具尚未出现,可使用 explorer_call(tool, arguments) 作为备用方式。 |
| 聊天 | ask_user | 等待 Creator Hub 聊天中显示的问题得到答复。仅在嵌入式助手中有意义。10 分钟无答复后超时,并按关闭处理(packages/creator-hub/main/src/modules/scene-mcp.ts 中的 ASK_TIMEOUT_MS = 10 * 60_000,已在 origin/main 2026-10-15 核实)。超时后,聊天中的提示词也会关闭("This question is no longer active."),之后收到的任何答复都会被丢弃——超时的 ask_user 永远无法事后答复(creator-hub dc9d076be)。如果创作者可能已离开,切勿让工作轮次一直等待它;请改在最终消息中提出问题。 |
工作流
先阅读,再编写。 使用 get_project_info 获取场景边界(按 composites 技能的步骤 0 精确计算边界——这些工具不会阻止你将实体放在场景之外,而 get_scene_metrics 的安全保障并没有看起来那么可靠——请参阅下文 Bevy 渲染器的注意事项)。使用 scene_state 查看现有内容,避免名称重复。用户请求涉及其所选内容时,使用 get_selection。
添加模型。
- 目录项 → 使用
search_catalog,然后使用place_smart_item。文件会自动放入assets/asset-packs/<pkg>/。 - 建筑结构(房间、走廊、门道,以及任何 avatar 可以走过或进入的空间)→ 放置前,先按第三人称摄像机的需求确定空间包络尺寸;真实比例的尺寸在场景中会显得局促。相关尺寸见 add-3d-models → “RULE: Scale interiors up for the third-person camera”。
- 用户已有的模型或你制作的模型 → 将 GLB 放在
assets/Models/下(Blender 制作和包围盒检查请参阅 add-3d-models 技能),然后调用create_entity(带上name),调用set_component设置Transform({position:{x,y,z}, rotation:{x,y,z,w}, scale:{x,y,z}}),再调用set_component设置core::GltfContainer({src, visibleMeshesCollisionMask, invisibleMeshesCollisionMask}——add-3d-models 中的遮罩规则以及动画/碰撞体检查仍然适用;GLB 包含动画片段时,添加core::Animator)。 - 灯光 → 使用类别为
lights的search_catalog查找 Spotlight 和 Point Light Smart Item,然后使用place_smart_item。这些项目包含灯光模型、LightSource和切换操作。只有在需要不可见光源或非标准参数时,才手动创建单独的LightSource实体——完整的LightSourceAPI 和 Smart Item 规则请参阅 lighting-environment。 - 为它添加行为 → 如果有合适的 Smart Item,就使用它(先调用
search_catalog);否则,在assets/Scripts/下编写脚本并调用attach_script(规则见 script-components),或者在src/代码中按名称引用实体(engine.getEntityOrNullByName)。
组件结构。 set_component 会根据实际架构验证组件。首次写入某种组件前,对已有该组件的任意实体调用 entity_detail,或查阅 composites 格式目录中的对应条目。对于 asset-packs::Script,参数按位置放在 layout 中(见 script-components);优先使用 attach_script,让编辑器生成布局。
写入后。 只要数据层仍在运行,写入后读取就是安全的——服务器会在变更操作返回前等待自动保存完成,因此后续调用 scene_state 获取的是最新状态。进程一旦终止(见下一条规则),这种做法就不再安全;所以应检查磁盘上的数据,而不是工具返回的结果。添加几何体后,检查 get_scene_metrics。editor_screenshot 可在不启动预览的情况下显示结果;需要运行中的场景时,使用 launch_preview + explorer_*(行走、点击、日志、FPS)。unity-explorer-mcp 技能中的迭代循环、摄像机取景和性能参考同样适用于 explorer_* 工具——跳过该技能的 Setup 部分(无需 claude mcp add,也无需 bind gate),因为这些工具由 creator-hub 服务提供。完成后,将摄像机留在场景预期的零售模式下(通常为第三人称,除非场景要求第一人称);如果启动预览只是为了检查,则调用 stop_preview。
如果你无法查看运行时状态,只需说明一次,并标明你无法看到的内容。 从外部客户端看不到 explorer_* 工具,而 unity-explorer-mcp 服务拒绝连接只表示 Explorer 未运行(该技能的 Setup 会启动它)。主动提出帮忙完成设置;在收到截图或创建者确认视觉结果之前,都应报告为未经验证(“屏幕平面现在应该位于边框内——我还没有看到”),绝不能说已经完成。两次针对同一场景的会话(2026-10)中,每个视觉缺陷——屏幕悬浮在显示器前方、门与门框发生穿插、墙面 z-fighting、材质呈白色——都先由所有者发现,因为修复只根据代码就被报告为已完成。
绝不要通过代码固定编辑器实体的位置。 如果场景代码在每次加载时写入编辑器拥有的实体的 Transform,以此“纠正”其位置,就会悄无声息地覆盖创建者随后在 Hub 中进行的所有移动:他们把一个托盘拖到传送带上,但托盘却总是在空中偏移 2 m 后重新出现(所有者报告的症状;原因可在场景自身代码中找到,2026-10-11)。代码可以读取编辑器实体的 Transform;如果需要自行放置实体,就创建一个专属实体。
嵌套实体上的变换是相对于父级的。 Hub 将实体嵌套到组下时,该实体报告的 Transform.position 是相对于该组的位置,而非相对于场景的位置,因此,在用位置进行距离检查或将物体放置在其旁边之前,必须解析完整的父级链(在 assets/scene/main.composite 中发现,2026-10-11——该场景中之所以没有问题,只是因为这些组位于原点)。
错误处理。 撤销由用户操作——告诉他们应撤销什么,或者使用 remove_entity / set_component 恢复之前的值。绝不要通过编辑 main.composite 来“修复”错误。
规则 — 确认一批更改已写入磁盘;数据层可能会悄无声息地崩溃
负责承载编辑器引擎并写入 assets/scene/main.composite 的组件是 @dcl/inspector data layer;在 Bevy 渲染器下,它运行于单独的子进程中——应用会将其记录为 [UtilityProcess] Running "sdk-commands start --port <n> --no-browser --no-client --data-layer"(在 main/src/modules/bevy-realm.ts 中组装;端口是临时分配的,可执行文件位于场景自身的 node_modules/@dcl/sdk-commands)。在 Babylon 渲染器下,同一数据层则运行于 inspector iframe 内。无论哪种情况,Electron 主进程都不会写入 composite,只会读取它。
数据层崩溃后,Electron 应用中的 MCP 服务仍会运行,并且会继续对每次调用作出响应,仿佛一切正常。工具结果中不会有任何提示表明场景已不再变化。
因此,每批修改后都应检查文件,而不是工具: assets/scene/main.composite 的修改时间必须更新(使用 ls -l / stat 检查)。一批修改前后 mtime 没有变化,意味着这些编辑只存在于一个已经消失的进程中。
stat -f '%m %N' "assets/scene/main.composite" # macOS; coreutils: stat -c '%Y %n'
(Get-Item "assets\scene\main.composite").LastWriteTime # Windows (PowerShell)
数据层崩溃时的已观察症状(2026-10-08 会话;mtime 未更新时请检查以下症状):
set_component、create_entity、place_smart_item等工具仍会返回成功。scene_state/entity_detail仍会返回崩溃前的值——回读结果“确认”了你的写入,实际上确认的却是旧快照。editor_screenshot返回空白图像。get_scene_metrics返回的值全为零,且entitiesOutOfBoundaries为空——但不要把这当作判断依据——在 Bevy 渲染器下,这些字段本来就会被硬编码为零(参见 Gotchas)。mtime 检查才是可靠的判断方法。 恢复操作由用户负责,内存中的编辑会丢失。 没有工具可以重启数据层。停止写入,查看 Creator Hub 主日志(macOS:~/Library/Logs/creator-hub/main.log;Windows:%APPDATA%\creator-hub\logs\main.log),查找Exiting "sdk-commands start … --data-layer" … exit code=1这一行——运行grep -n "exit code=1\|reading 'deserialize'" main.log,不要只粗略浏览:2026-10-08 的会话中,崩溃日志行位于 241 KB 的 grep 结果中,却只读取了开头的 2 KB——告知创作者在 Creator Hub 中关闭并重新打开场景,然后重新应用崩溃后所做的每一项修改——与磁盘上的组合文件进行比较,找出内容从哪里开始不一致。离开编辑器页面也会终止该场景的预览服务(Hub 的EditorPage中的handleBack→killPreview),因此重新打开后,创作者需要再次按下 Play——或者你再次调用launch_preview——然后才能期待世界中出现任何新内容。
为什么 set_scene_settings + spawnPoints 会杀死数据层或清空位置——请阅读源代码(creator-hub origin/main d25eff1b,2026-10-19;@dcl/ecs main)。 工具的输入架构采用 scene.json 的形式接收 position——x: number | [min, max](main/src/modules/scene-mcp.ts)——而检查器的处理程序会将补丁原样合并到根实体的 inspector::SceneMetadata-v* 组件中({ ...current, ...patch },packages/inspector/src/lib/rpc/scene/server.ts)。该组件的 position.x/y/z 是 Schemas.OneOf({ single, range }),要求采用 { $case: 'single', value: 8 } 或 { $case: 'range', value: [a, b] } 的形式(lib/sdk/components/SceneMetadata.ts)。两种形式之间没有任何转换,因此普通数字会被放进 OneOf 槽位,而 CRDT 序列化器看不到 $case。Hub 自带的检查器运行的是 @dcl/ecs 7.29.0(根目录的 package.json),其 OneOf 序列化器会为没有 $case 的值写入一个空 case(js-sdk-toolchain 0dce4d2d,#1570,随 7.28.0+ 发布)。接下来会发生什么,取决于场景自身 node_modules/@dcl/inspector 中的数据层:如果 @dcl/ecs 低于 7.28.0,其 OneOf 反序列化器无法读取这个空 case(specs[specKeys[0 - 1]] 为 undefined),数据层就会崩溃——这就是 tooling-entrypoint.js 中的 TypeError: Cannot read properties of undefined (reading 'deserialize')(Object.deserialize → updateFromCrdt → receiveMessages)。2026-10-08 使用点值出生点时曾两次出现该错误:Hub 的写入方与场景较旧的读取方存在版本不匹配。使用匹配的 @dcl/ecs 时,写入会保留,但读取结果为 {},数据层的 scene.json 写入器(data-layer/host/utils/component.ts)会输出 "position": {}——2026-10 的 Creator Hub 0.51.0 中曾两次出现这种情况,尽管 get_scene_settings 仍显示格式正确的值。点值和范围值都会受影响;早期版本的本技能中对仅范围值受影响的猜测是错误的。
因此:请用 set_component 在实体 0 上以组件自身的格式写入出生点——使用与 Gotchas 中缩略图相同的路径;从 entity_detail(0) 获取带版本号的组件名称,并只传入 spawnPoints 键:
{"spawnPoints": [{"name": "spawn", "default": true,
"position": {"x": {"$case": "single", "value": 8}, "y": {"$case": "single", "value": 0}, "z": {"$case": "single", "value": 8}},
"cameraTarget": {"x": 8, "y": 1, "z": 12}}]}
范围轴的格式为 {"$case": "range", "value": [4, 12]}。然后读取 scene.json(会在下一次自动保存时更新),并检查每个 spawnPoints[].position 中都保存了数字。如果结果是 {},请在 Hub 中关闭场景并手动修复 scene.json:下次打开时,数据层会从 scene.json 重新载入 SceneMetadata(overrideWithSceneJson,data-layer/host/composite-provider.ts),因此手动编辑会生效,并据此刷新组合文件中的副本——场景关闭时编辑的其他场景设置也同样如此。这种格式不匹配是 Hub 的一个 bug;如果当前运行版本仍存在此问题,请通过 report-sdk-issue 进行报告。
预览生命周期——stop_preview 不会关闭 Explorer
stop_preview 按设计不会关闭 Explorer,也没有任何工具可以做到这一点。 已在 main/src/modules/explorer-gateway.ts 中验证:它会关闭 MCP 客户端/传输层,并对 sdk-commands start --explorer-alpha --hub … --mcp --mcp-port <n> 子进程执行 treeKill(日志显示为 [UtilityProcess] Killing process "…"),然后返回 {ok: true}。Explorer 应用不在该进程树中——sdk-commands 通过 open decentraland://… 启动它,将操作交给操作系统后自身退出——Creator Hub 中也没有任何东西会终止它。
preview_status 也不会检测到这一点:running 是根据网关对象是否存在以及同一个 sdk-commands 句柄上的 child.alive() 计算的,而不是通过探测 Explorer 或其端口得出的。因此,“没有正在运行的预览”说的是开发服务器,而不是应用。
接下来启动为何会失败——先说已验证的部分:每次 launch_preview 都会获取一个新的临时 MCP 端口([Gateway] launching preview … with MCP on :53880),并将其作为 --mcp-port 传入;而桌面版 Explorer 只能运行一个实例,因此第二次启动的深层链接会交给已经打开的窗口。推测(并非从 Explorer 源码中直接读取)是,已打开的窗口会继续在旧端口上运行 MCP,且不会绑定新端口。无论实际情况如何,重试约 45 秒后,Hub 都会返回:
预览已启动,但其 MCP 服务始终未响应。Explorer 可能仍在启动,或者此构建不支持 MCP。(TypeError: fetch failed)
并且请注意,这条失败路径也会终止刚启动的开发服务器,使 Explorer 孤立在已关闭的 realm 上。观察记录:2026-10-08,连续启动两次复现了该问题。(相关说明:preview_status 可能会轮询已启动但尚未就绪的 Explorer,最长达 90 秒,因此长时间卡住并不代表崩溃。)
在 launch_preview / preview_status 上出现 Tool call interrupted: the session ended…,是创建者停止了这一轮,而不是预览失败。 这两个工具都会阻塞很久(启动过程会重试 Explorer 的 MCP 约 45 秒,状态轮询最长达 90 秒);在嵌入式助手中,聊天的停止控件会在此期间终止 CLI 子进程(aiStop → killTree,main/src/modules/ai.ts),工具调用随后会报告已中断。2026-10-08 的一次会话中,四次此类中断都分别发生在创建者发送下一条消息时,而 Agent 启动的预览始终在运行。下结论前,先用 pgrep 检查 Explorer 并读取日志——不要像那次会话一样,在项目笔记中写入“launch_preview 会结束会话”。
规则——调用 launch_preview 前,同时检查工具和操作系统:
pgrep -fl '[M]acOS/Explorer' # the Explorer app itself
pgrep -fl '[d]cl_watchdog' # its watchdog, from /Applications/Decentraland.app
在这些模式中保留方括号。pgrep -f / pkill -f 会匹配每个进程的完整命令行,而许多 Agent 的 shell 工具会以 bash -c "<command>" 的形式运行命令,因此普通模式也会匹配包装 shell:检查会报告一个实际上并不存在的 Explorer 正在运行,而 pkill 会杀掉运行该命令的 shell。[d]cl_watchdog 仍能匹配真实进程,但不会匹配命令文本本身。
反过来的情况也会发生:创建者关闭 Explorer 窗口后,preview_status 仍会报告 running: true。 sdk-commands 子进程仍在运行,因此句柄仍会报告运行中;与此同时,每次 explorer_* 调用都会失败并返回 fetch failed(观察记录:2026-10-12)。因此,一连串 fetch failed 结果表示“应用已关闭”,而不是“场景有问题”——使用 pgrep -fl '[M]acOS/Explorer' 确认,然后依次调用 stop_preview 和一次 launch_preview 以恢复。两个方向的规则都一样:要确认“Explorer 是否正在运行”,只有 pgrep 能给出可靠答案。
preview_status 显示“未运行”,并不能证明 Explorer 已关闭。如果任一进程仍在运行,而你需要干净的预览,请关闭残留实例,确认它已退出,然后只调用一次 launch_preview:
pkill -f '[d]cl_watchdog'; pkill -f '[D]ecentraland.app/Contents/MacOS/Explorer'
for i in $(seq 1 30); do pgrep -f '[M]acOS/Explorer' >/dev/null || break; sleep 1; done # wait up to 30 s
在 Windows 上,Explorer 进程名为 Decentraland.exe,看门狗进程名为 dcl_watchdog.exe。在 PowerShell 中运行以下命令(按进程名匹配,因此检查不会匹配运行该命令的 shell):
Get-Process Decentraland, dcl_watchdog -ErrorAction SilentlyContinue # is either alive?
Stop-Process -Name dcl_watchdog -Force -ErrorAction SilentlyContinue # watchdog first: it reacts to a non-zero Explorer exit
Stop-Process -Name Decentraland -Force -ErrorAction SilentlyContinue
Wait-Process -Name Decentraland -Timeout 30 -ErrorAction SilentlyContinue # confirm it exited
该 Explorer 窗口属于创作者,不是测试环境。 你通过 explorer_* 工具执行的所有操作——explorer_move_to、explorer_reload_scene、相机模式更改,以及触发热重载的任何资源文件变动——都会影响创作者正在体验的会话。接管控制前,请检查 explorer_get_player_state 和近期的 explorer_get_scene_logs,确认是否有活动;进行外观检查时,优先使用 explorer_set_camera_pose 而不是 explorer_move_to,并恢复你发现的相机模式。完整规则见 unity-explorer-mcp 技能中的迭代循环(观察于 2026-10-10)。
之后两次尝试都首次连接成功。优先复用健康运行的预览(热重载 + explorer_reload_scene),而不是重启——仅在预览过时或 MCP 始终无响应时才结束进程。如果该 Explorer 窗口属于用户,结束进程前请先征求同意。
重新烘焙的 GLB 在运行中的预览里可能仍显示旧内容。 这不是开发服务器导致的:@dcl/sdk-commands 7.30.1 会在每次内容请求时重新遍历项目,以 no-cache 提供当前字节,根据 mtime 为每个文件的 id 设置版本,并运行一个 Hub 永远不会禁用的 chokidar 监视器——因此,陈旧内容来自下游的 Explorer 自身资源缓存。观察于 2026-10-08:在 launch_preview 之后添加或重命名的 GLB 在游戏内不可见,直到执行 explorer_reload_scene(一个案例)或完整重启预览(另一个案例);而在原路径下覆盖同名 GLB 后,显示的网格仍是旧的。src/ 热重载不受影响。实用规则:重新烘焙模型后,使用新的文件名导出,并更新 GltfContainer.src 指向该文件——这是已确认能可靠重新加载的方式;否则,请执行 explorer_reload_scene,如果旧网格仍存在,则重启预览。(症状:刚导出的网格缺失或明显过时,而 explorer_get_scene_logs 中没有加载错误。另请检查 .dclignore——被忽略的路径根本不会被提供。)
技能的来源
这些技能如何到达 Agent,取决于你使用上述两种设置中的哪一种。
在 Creator Hub 的 AI 助手中,由应用安装这些技能——绝不要手动复制。 安装程序位于 packages/creator-hub/main/src/modules/skills.ts:
- 它会将
decentraland/sdk-skills的 main 下载到每位用户的缓存中(以上游提交 SHA 和应用版本为键,采用原子方式替换,并可在离线状态下运行)。 - 它会将该缓存符号链接到打开的场景中,路径为
.claude/skills和.agents/skills。应用创建的链接会添加到.gitignore。如果用户已有真实的skills目录,应用会逐个链接其中的技能,并跳过用户已有的名称。
在这种设置下,不要将技能目录复制到场景中,也不要让用户这样做:手动放置的副本会遮蔽受管理的符号链接,之后便会悄然过时;更新由应用负责。
在外部客户端(Claude Code CLI 或 VS Code 扩展、Cursor、Codex、Claude Desktop 等)中,技能由用户自行安装。 MCP 代码片段只能连接工具,不会一并安装技能。有两种情况:
-
如果 Creator Hub 当前打开了该场景,场景文件夹中已经存在应用管理的
.claude/skills/.agents/skills符号链接,因此在该文件夹中启动的 Claude Code 会话会自动加载这些技能。不要重复添加。 -
否则(工作目录不同、Creator Hub 未打开该场景,或客户端从其他位置读取技能),请从场景文件夹或用户的技能根目录按常规方式安装:
npx skills add decentraland/sdk-skills --all重新运行同一命令即可更新;
npx skills update只会刷新已存在的技能,无法获取新添加的技能。请参阅代码库的 README,了解各技能的安装方式。
应用链接的技能集合中包含拒绝名单上的技能。 因此,在已链接到 Hub 的文件夹中启动 Claude Code 会话时,没有 deploy-scene / deploy-worlds(一次 2026-10 会话通过网络搜索查找 Worlds 部署命令,并手动编写了 worldConfiguration)。应为用户安装这些技能,而不是装进符号链接文件夹——运行 npx skills add decentraland/sdk-skills --skill deploy-worlds -g(用户级)——或者走捷径:将 worldConfiguration.name 添加到 scene.json,然后运行 npx @dcl/sdk-commands deploy --target-content https://worlds-content-server.decentraland.org;缩略图、两组名称/描述/缩略图以及错误表均位于 deploy-worlds 中。
Creator Hub Agent 内会刻意将四项技能列入拒绝名单: create-scene、deploy-scene、deploy-worlds、migrate-sdk6-to-sdk7。Creator Hub 通过自己的界面负责搭建和发布,并且仅支持 SDK7。安装程序通过两种方式处理这些技能:
- 对于包含辅助文件的拒绝名单技能(
create-scene、migrate-sdk6-to-sdk7),安装时不包含其SKILL.md——其他技能仍可通过相对路径访问其references/,但该技能本身绝不会被触发。 - 对于目录中只有
SKILL.md的拒绝名单技能(deploy-scene、deploy-worlds),则会完全跳过。
如果用户在 Creator Hub 中要求搭建项目或发布,请引导他们使用应用自身的流程,而不要尝试加载或重建这些技能。通过外部客户端手动运行 npx skills add 安装时不会应用拒绝名单:这四项技能在外部客户端中均可用。
注意事项
-
Creator Hub 每次启动都会更换 URL 和令牌。 昨天还可用的配置今天会报
ECONNREFUSED或401;解决方法是从 Settings 重新复制代码片段,而不是反复重试。 -
一次只能打开一个项目。 服务针对单个编辑器窗口中打开的场景运行。用户位于场景列表时,变更工具会返回
No editor window is open.。 -
从外部客户端调用磁盘读取工具和
launch_preview时会返回No scene is open.,即使场景明明已打开: 只有在内嵌助手开始一轮对话时(从main/src/modules/ai.ts调用setSceneMcpProject),项目目录才会绑定到get_project_info/scene_state/entity_detail/launch_preview(从初始版本 creator-hub217e2f9f、PR #1499 到origin/maind25eff1b,2026-10-20,行为始终如此)。所有经由编辑器路由的操作(get_selection、get_scene_metrics、get_scene_settings、所有变更操作、place_smart_item)都不受影响。因此,从外部客户端验证访问时,请用get_selection/get_scene_settings,或执行一个无害的变更,再加上上文的复合文件 mtime 检查——不要用磁盘读取工具验证;只读地从磁盘读取scene.json和assets/scene/main.composite以获取实体列表;通过工具进行变更;若要在世界中检查,请从 Hub 的 Play 按钮启动预览,勾选 Enable MCP Server,并按照 unity-explorer-mcp 操作(其 Setup 部分适用于此路径——explorer_*工具不会出现,因为没有请求通过creator-hub服务到达)。 -
读取工具的数据会比引擎晚一个自动保存周期(约 100 ms)。变更工具已经会等待;只有在用户拖动对象的同时你进行读取时才需要注意。
-
Scene RPC "<tool>" timed out (no renderer response)是 Hub 的 5 秒编辑器 RPC 超时(renderer/src/modules/rpc/scene/client.ts中的REQUEST_TIMEOUT_MS),并非崩溃:检查器未能及时响应。2026-10-08 在 Bevy 编辑器处于 Play 状态时,create_entity曾出现两次此情况;停止 Play 后两次都成功了。请让创作者在批量变更前停止 Play,然后重试——不要改为直接编辑文件。 -
scene_state最多返回 200 个实体。 对于大型场景,可通过entity_detail按名称筛选,或从磁盘读取复合文件。 -
Creator Hub 内的技能拒绝列表。 应用会将
decentraland/sdk-skills链接到场景中的.claude/skills/.agents/skills,但会移除create-scene、deploy-scene、deploy-worlds和migrate-sdk6-to-sdk7的SKILL.md:在应用中,这些操作分别由自己的流程负责,包括脚手架搭建、发布和 SDK6 迁移。其参考文件仍可供交叉链接解析。 -
Explorer 的
--mcp预览复选框属于另一个服务。 Enable MCP Server 位于 Play Options 弹出菜单中(编辑器标题栏 Play 按钮上的下拉箭头),悬停在 Desktop Client 行时会打开其飞出菜单。它会启动带有独立 MCP 的 Explorer,端口为 8123(即 unity-explorer-mcp 技能),并且仅当项目使用@dcl/sdk7.25.0 或更高版本时才会显示——如果用户找不到此复选框,请先检查场景的 SDK 版本,再排查 Hub。此处介绍的 Creator Hub MCP 是编辑器的服务;在内嵌助手中,请使用它的launch_preview,而不是该复选框。从外部客户端调用launch_preview会失败(见上文No scene is open.的注意事项),因此在这种情况下,复选框才是正确的入口。 -
按一次 Ctrl+Z = 撤销你的一项操作,而不是一次组件写入。 自 creator-hub
fdc384b5起,一整批同步变更会作为一个撤销事务提交(旧版的 200 项操作批次上限曾导致大型变更被拆成多个条目,因此按一次 Ctrl+Z 后会留下孤立实体)。涉及多个实体的操作——例如放置复合 Smart Item,或带子级的脚本化物品——现在都只占一个条目;撤销添加操作也会从 Bevy 视口中移除该实体。仍然请按用户实际撤销时所用的单位描述你的变更。 -
可以在编辑器中静音场景音频,但仅限 Bevy。 视口工具栏上有一个扬声器切换按钮(Mute scene audio / Unmute scene audio),会将每个
AudioSource/AudioStream以音量 0 传给渲染器;重新加载后状态仍会保留。Babylon 渲染器下没有此按钮,因为它根本不会播放场景音频。因此,“我听不到你添加的声音”并不能证明组件有误——先检查渲染器和此切换按钮,并注意静音开启时,Bevy 视口不会按你设置的volume播放。 -
在 Bevy 渲染器下,
get_scene_metrics不会返回有用的信息。 已在packages/inspector/src/lib/renderer/bevy/BevyRenderer.ts中验证:getSceneMetrics()返回{triangles: 0, bodies: 0, materials: 0, textures: 0},getEntitiesOutsideLayout()返回[],两者均为硬编码值("No renderer to introspect yet — report zeros")。限制仍然有效;entities是从 Nodes 树而非渲染器得出的;但内容指标全为零且entitiesOutOfBoundaries为空,表示“Bevy”,而不是“场景为空”或“存在问题”——不要据此判断预算状态或实体是否越界。在 Babylon 下,这些数据是真实的:computeEntitiesOutsideLayout会检查每个实体的包围网格是否位于布局内,因此能够检测到尺寸过大的几何体。无论使用哪个渲染器,如需可靠的预算数据,请运行launch_preview,并使用explorer_get_scene_content_stats。 -
[已修复] 使用 Bevy 发布时,过去会丢弃地块布局变更。 由于 Bevy 下的数据层运行在 sdk-commands realm 中,
scene.json写入不会经过 Hub 的存储 RPC,因此 Hub 会保留项目加载时的布局,而发布时会将该旧布局写回——在 Scene settings 中调整大小的场景,发布后会恢复为原始布局(通常是 1x1)。此问题已在 creator-hubee43befd0(2026 年 10 月)中修复:检查器的notify_scene_metadata报告现在会携带parcels和base。get_project_info会从磁盘读取scene.json,从未受此问题影响,因此它不是变通方法,也从未出现过此症状。此处仅作说明,以便识别旧版 Hub 构建中的发布异常。 -
绝不要将自定义缩略图保存为
assets/Images/autogenerated-thumbnail.png。 Hub 每次自动生成缩略图时,都会将视口截图写入这个固定路径,覆盖其中已有的任何文件;发布开始时以及项目卡片刷新时都会触发(packages/creator-hub/preload/src/modules/workspace.ts中的getProjectThumbnailPath/saveThumbnail),所以在此处写入的封面会在上传前被替换。它只会在以下三种情况下重写scene.json的display.navmapThumbnail(workspace.ts中的saveThumbnail):该字段未设置、指向的文件不存在,或者其值指向大小写不同的自动生成路径。大小写不一致的自定义封面不会被修改——macOS 和 Windows 都能解析,因此只有部署时才会失败。这就是覆盖操作没有任何提示的原因。请将自定义封面保存为其他名称(例如assets/Images/cover.png),并将场景指向该文件。 -
图像资源位于
assets/Images/,I 必须大写;部署时大小写会影响结果。 部署文件列表会保留磁盘上的大小写,Catalyst 会区分大小写地将display.navmapThumbnail与文件列表匹配。因此,如果scene.json写的是assets/images/...,而磁盘上的文件夹是assets/Images/,发布时就会出现Scene thumbnail 'assets/images/autogenerated-thumbnail.png' must be a file included in the deployment。本地不会发现问题:macOS 和 Windows 对两种大小写都能正常解析,所以场景在上传前看起来一切正常。Hub 现在默认将自动生成的缩略图写入assets/Images/——resolveImagesFolderName会保留仅大小写不同的现有文件夹,因此已有assets/images/的项目仍会使用小写——并会在下次保存缩略图时重写大小写不一致的自动生成navmapThumbnail条目(creator-hub9d82aac07);但你手动写入的任何路径都必须与实际存在的文件夹大小写一致。设置路径前请用ls assets检查,且绝不要新建仅大小写不同的第二个文件夹。set_scene_settings无法完成此操作(其输入架构中没有thumbnail键;MCP SDK 会在编辑器收到数据前移除未知键),但可以用set_component:通过entity_detail(0)读取根实体的 scene-metadata 组件,然后执行set_component(0, "inspector::SceneMetadata-v5", {thumbnail: "assets/Images/cover.png"})——键会像任何更新一样进行合并,scene.json中的display.navmapThumbnail会在下次自动保存时同步更新(已实时验证;106 个地块和出生点均保留)。请使用读取结果中的确切版本名称,而不要硬编码-v5:编辑器会绑定到携带数据的版本(resolveActiveSceneComponent),因此使用较旧固定版本sdk-commands的场景仍使用-v4;写入错误版本只会添加一个无人读取的组件。编辑器中的 Scene settings → Thumbnail 字段提供了等效的 UI 操作方式。 -
大型场景中的
entity_detail(0)输出巨大——在包含 106 个地块的场景中有 3,335 行 / 79 KB,主要是inspector::Nodes和地块列表,大到足以导致工具结果溢出(2026-10-10 观察到)。请将输出重定向到文件,并用grep仅筛选所需组件。此外,由于set_component会合并顶层键,只写回你更改的键——绝不要将刚读取的整个组件写回。 -
你生成的缩略图(Blender 渲染、图像工具、截图)必须符合发布规格,之后才能将场景指向它。 发布到 World 时,缩略图超过 1,048,576 bytes 会被拒绝——曾使用普通的 1920x1080 PNG 遇到错误
Invalid thumbnail: size 1185064 bytes exceeds maximum of 1048576 bytes (1MB)。此检查不在 creator-hub 中(仓库中没有任何内容与此错误消息或常量匹配);Worlds 内容服务器会在部署时强制执行,因此编辑器和本地构建都不会提前警告。其余检查由编辑器执行:文件格式为.png/.jpg,且宽高比必须为 16:9,误差不超过 1 %;建议使用 1920x1080(packages/inspector/src/components/EntityInspector/SceneInspector/utils.ts中的getThumbnailWarnings/validateThumbnailFile;Hub 自己截取的图像会居中裁剪为 16:9,且宽度上限为 1920,见packages/creator-hub/renderer/src/modules/image.ts)。 -
因此:按 16:9(1920x1080,或文件较小的 1344x756)渲染,优先导出高质量 JPEG,而非 PNG——
ffmpeg -i cover.png -q:v 2 cover.jpg在 1344x756 下生成的文件约为 100 KB;只有 PNG 实际低于上限时才使用。将路径写入场景前,先检查字节大小(ls -l)和尺寸(sips -g pixelWidth -g pixelHeight),不要等发布失败后再检查。请使用不同名称保存,并按上文所述更新场景指向——绝不要使用assets/Images/autogenerated-thumbnail.png。 -
每张缩略图都必须适应正方形裁剪:将文字、徽标和主体放在中央正方形区域内。 有些平台只显示 1920x1080 图像的中央 1080x1080 区域,因此两侧各有
(1920 - 1080) / (2 * 1920) ≈ 0.219的宽度会被裁掉(THUMBNAIL_SAFE_AREA_INSET)。1920 宽的图像中,对应 x 坐标 420–1500;1280 宽的图像中,对应 x 坐标 280–1000。无论你是截取、渲染还是合成图像,都适用此规则。将场景指向该图像前,请先裁剪成正方形并检查效果。不要只看完整画面来判断:在完整画面中从一边延伸到另一边的标题看起来可能没问题(Locksmith,2026-10)。OUT="${TMPDIR:-/tmp}/cover-square.png" # macOS H=$(sips -g pixelHeight cover.png | awk '/pixelHeight/{print $2}'); sips -c $H $H cover.png --out "$OUT" # ImageMagick (any OS) H=$(magick identify -format %h cover.png); magick cover.png -gravity center -crop ${H}x${H}+0+0 +repage "$OUT"然后
Read这张方形图像。文本中的每个词都必须出现在图像中。 -
node/npx不在 PATH 中,并不意味着无计可施。 Creator Hub 自带完整的 Node(v22,包含npm和npx),并通过它运行每个sdk-commands子进程(main/src/modules/node-runtime.ts、scripts/download-node.js):macOS 路径为/Applications/Decentraland Creator Hub.app/Contents/Resources/node-bin/bin/{node,npm,npx},Windows 路径为 Creator Hub 可执行文件旁边的resources文件夹中的resources\node-bin\node.exe(以及npm.cmd/npx.cmd),Linux 路径为resources/node-bin/bin/。对于没有自带 Node 的创作者机器,可以使用绝对路径运行npx tsc --noEmit、npx skills add decentraland/sdk-skills --all、gltf-transform等命令。(开发版的 Hub 不包含捆绑的 Node,会使用开发者的 Node。) -
asset-packs::Placeholder的src需要解析后的文件路径,而不是模板变量。 目录中存储的路径使用{assetPath}/model.glb作为模板;通过set_component按原样设置该字符串,会生成不可见或损坏的操纵器,因为引擎无法解析该变量。place_smart_item会自动解析路径(例如解析为assets/asset-packs/spotlight/spotlight.glb)。如果必须手动设置Placeholder,请使用 GLB 文件在磁盘上的真实路径。