mcpField
C
create-scene

create-scene

github.com/dcl-regenesislabs开发1738 次安装21 周前更新
代码仓库

关于 create-scene

指导创建 Decentraland SDK7 场景的技能,涵盖需求梳理、使用 `/init` 搭建项目、选择资源和配置文件,适用于场景开发者,并强调声明式实体与行为分离。

主要功能

  1. 01梳理场景需求
  2. 02使用 `/init` 搭建项目
  3. 03搜索 3D 模型与音频目录
  4. 04配置场景文件和地块
  5. 05分离声明式实体与行为

适用场景

  1. 01启动美术馆、游戏或社交场景
  2. 02按场景主题挑选模型和音效
  3. 03配置出生点与地块布局
  4. 04预览新建场景

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/dcl-regenesislabs/opendcl --skill create-scene

安装后在 Claude Code 中输入/create-scene确认已加载。

详细介绍

创建新的 Decentraland SDK7 场景

运行时限制: Decentraland 在 QuickJS 沙盒中运行。不支持 Node.js API(fs、http、path、process)。请使用 SDK 的 executeTask() + fetch() 执行异步工作。详情请参阅 scene-runtime 技能。

当用户想要创建新场景时,请按以下步骤操作:

1. 询问他们想要构建什么

如果用户尚未描述场景,请询问他们:

  • 场景类型是什么?(画廊、游戏、社交空间、交互艺术等)
  • 有多少块地块?(默认值:1 块地块 = 16x16m)
  • 有哪些特定功能?(3D 模型、交互功能、UI、多人游戏)

2. 使用 /init 搭建项目框架

始终先运行 /init。 它会使用官方的 @dcl/sdk-commands init 创建 scene.json、package.json、tsconfig.json 和 src/index.ts,并采用正确且最新的配置,同时自动安装依赖项。

切勿手动创建 scene.json、package.json 或 tsconfig.json——SDK 模板可能会随版本变化,手动编写的副本会逐渐偏离。

3. 查找匹配的 3D 资源

编写场景代码前,请在资源目录中搜索与用户主题匹配的免费模型:

  1. 搜索模型目录(包含 5,700 多个经过优化的 3D 模型——角色、建筑、道具、自然元素、载具等)
    grep -i "keyword" {baseDir}/../add-3d-models/references/model-catalog.md
    
  2. 阅读 {baseDir}/../../context/audio-catalog.md(包含 50 种免费音效——音乐、环境音、音效、游戏机制等)
  3. 获取预览缩略图(每行目录末尾的 preview: URL),以直观确认模型
  4. 向用户推荐匹配的模型和音效
  5. 将选定的模型下载到场景的 models/ 目录中:
    mkdir -p models
    curl -o models/zombie-purple.glb "https://models.dclregenesislabs.xyz/blobs/bafybeiffc..."
    

重要: GltfContainer 仅适用于本地文件。模型的 src 字段绝不可使用外部 URL。

4. 自定义生成的文件

/init 完成后,根据用户的需求自定义生成的文件:

scene.json

更新 display 字段和地块:

  • display.title — 设置场景名称
  • display.description — 设置简短描述
  • scene.parcels — 对于多地块场景,列出所有地块(例如,2x2 场景使用 ["0,0", "0,1", "1,0", "1,1"])
  • scene.base — 设置为西南角地块
main-entities.ts + src/index.ts

OpenDCL 场景采用双文件创作模式:

  • main-entities.ts(场景根目录)——使用类型化的声明式实体及其数据组件,并以 Name 为键。构建时会编译为 main.crdt,并由引擎在运行 main() 之前预加载。
  • src/index.ts ——仅包含行为。通过 engine.getEntityOrNullByName<EntityName>(name) 按 Name 引用实体,并附加系统、指针事件、补间等。

main-entities.ts 示例:

import type { Scene } from '@dcl/sdk/scene-types'

export const scene = {
  blue_cube: {
    components: {
      Transform: { position: { x: 8, y: 1, z: 8 }, rotation: { x: 0, y: 0, z: 0, w: 1 }, scale: { x: 1, y: 1, z: 1 } },
      MeshRenderer: { mesh: { $case: 'box', box: { uvs: [] } } },
      Material: {
        material: { $case: 'pbr', pbr: { albedoColor: { r: 0.2, g: 0.5, b: 1, a: 1 } } },
      },
    },
  },
} satisfies Scene

satisfies Scene 子句会保留字面量键的类型(因此 keyof typeof scene 会得到类型化的实体名称联合类型),同时仍会根据 Scene 架构验证对象的形状。

src/index.ts 示例:

import { engine, pointerEventsSystem, InputAction } from '@dcl/sdk/ecs'
import type { scene } from '../main-entities'

type EntityName = keyof typeof scene

export function main() {
  const cube = engine.getEntityOrNullByName<EntityName>('blue_cube')
  if (cube === null) return

  pointerEventsSystem.onPointerDown(
    { entity: cube, opts: { button: InputAction.IA_POINTER, hoverText: 'Click me' } },
    () => console.log('clicked'),
  )
}

tsconfig.json 应包含 main-entities.ts,以便对其进行类型检查:

{
  "extends": "@dcl/sdk/types/tsconfig.ecs7.json",
  "include": ["src/**/*.ts", "src/**/*.tsx", "main-entities.ts"]
}

规则:

  • 每个可编辑/已声明的实体都必须在 main-entities.ts 中拥有唯一的 Name。
  • 运行时创建的动态实体(特效、弹射物、动态 UI 标记)直接使用 engine.addEntity()。不要为动态实体设置 Name——它们不属于 main-entities.ts。
  • 纯数据内容(Transform、GltfContainer、MeshRenderer、MeshCollider、Material、AudioSource、VideoPlayer、TextShape、Animator 配置、NftShape、Billboard、VisibilityComponent)放在 main-entities.ts 中。
  • 行为内容(指针回调、系统、补间触发器、条件逻辑)放在 src/ 中。
  • scene 字面量必须兼容 JSON——对象中不能有函数调用、展开语法或注释。
scene.json 参考

所有有效的 scene.json 字段:

字段必填说明
ecs7是SDK7 必须设为 true
runtimeVersion是必须为 "7"
main是必须为 "bin/index.js" — 编译后的输出路径
display.title建议显示在地图和 Places 中的场景名称
display.description建议用于发现的简短说明
display.navmapThumbnail可选Genesis City 小地图的图片路径
scene.parcels是"x,y" 坐标字符串数组
scene.base是原点地块(通常为西南角)
spawnPoints可选玩家进入时出现的位置(见下文)
requiredPermissions可选权限数组(例如,"ALLOW_MEDIA_HOSTNAMES")
allowedMediaHostnames可选外部媒体的白名单域名
featureToggles可选启用/禁用 SDK 功能
worldConfiguration可选用于 Worlds 部署(参见 deploy-worlds 技能)
authoritativeMultiplayer可选启用权威服务器模式(参见 authoritative-server 技能)
出生点

配置玩家进入场景的位置和方式:

{
  "spawnPoints": [
    {
      "name": "spawn1",
      "default": true,
      "position": { "x": [1, 5], "y": [0, 0], "z": [2, 4] },
      "cameraTarget": { "x": 8, "y": 1, "z": 8 }
    }
  ]
}
  • 位置范围(例如,[1, 5])会让玩家在该范围内随机出生
  • cameraTarget 用于确定玩家出生时的镜头朝向 — 将其指向场景的焦点区域
  • 固定出生点:使用单个值而非范围(例如,"x": 8)
多地块布局
布局地块数组使用场景
单地块["0,0"]小型游戏、画廊、单房间体验
条带["0,0", "1,0", "2,0"]走廊、赛车道、线性旅程
L 形["0,0", "1,0", "0,1"]转角建筑、分区体验
2x2 方形["0,0", "1,0", "0,1", "1,1"]开放广场、竞技场、中型游戏
3x3 方形从 "0,0" 到 "2,2" 的 9 个地块大型游戏、多房间建筑

基础地块: 始终将 scene.base 设置为西南角(x、y 最小)的地块。

每个地块的边界: 16m x 16m,高 20m。2x2 场景占地 32m x 32m。

5. 创建后的步骤

自定义文件后:

  1. 使用 preview 工具启动预览服务器(或手动运行 npx @dcl/sdk-commands start --bevy-web)
  2. 场景将在浏览器中打开,地址为 http://localhost:8000

交叉引用

  • 准备部署?请参阅 deploy-scene 技能(Genesis City)或 deploy-worlds 技能(个人 Worlds)
  • 需要针对地块限制进行优化?请参阅 optimize-scene 技能
  • 正在规划游戏?请参阅 game-design 技能,了解设计模式和性能预算

重要说明

  • 始终将物体放置在场景边界内(X 轴为 0 到 16parcelsX,Z 轴为 0 到 16parcelsZ)
  • 单地块场景的中心位于地面高度的 (8, 0, 8)
  • Y 轴朝上,最小 Y=0(地面)
  • scene.json 中的 main 字段必须为 "bin/index.js" — 这是编译后的输出路径
  • jsx 和 jsxImportSource tsconfig 设置已由 /init 包含 — 请勿修改
  • 切勿在 Transform 字段(position、rotation、scale)中传入 undefined 值 — SDK 序列化器会崩溃。如果字段是可选的,请完全省略该键,而不要将其设为 undefined。

评论

支持 Markdown