create-scene

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Create a New Decentraland SDK7 Scene

创建新的 Decentraland SDK7 场景

Runtime constraint: Decentraland runs in a QuickJS sandbox. No Node.js APIs (
fs
,
http
,
path
,
process
). Use the SDK's
executeTask()
+
fetch()
for async work. See the scene-runtime skill for details.
CRITICAL — read before generating any code: All initial scene entities (everything present at scene load) go in
assets/scene/main.composite
, NEVER in
src/index.ts
. See "Composite vs TypeScript — where entities go" (Step 4) for the rule, decision table, and rationale.
When the user wants to create a new scene, follow these steps:
运行时约束: Decentraland 运行在 QuickJS 沙箱中。无法使用 Node.js API(
fs
、
http
、
path
、
process
)。异步工作请使用 SDK 的
executeTask()
+
fetch()
。有关详细信息,请参阅 scene-runtime skill。
重要——生成任何代码前请先阅读: 加载场景时存在的所有初始场景实体都应放入
assets/scene/main.composite
,绝不能放入
src/index.ts
。有关规则、决策表和原因,请参阅“Composite 与 TypeScript——实体应放在哪里”(步骤 4)。
当用户想要创建新场景时,请遵循以下步骤:

1. Ask What They Want to Build

1. 了解用户想构建什么

If the user hasn't described their scene, ask them:
  • What kind of scene? (gallery, game, social space, interactive art, etc.)
  • How many parcels? (default: 1 parcel = 16x16m)
  • Any specific features? (3D models, interactivity, UI, multiplayer)
如果用户尚未描述其场景,请询问:
  • 场景类型是什么?(画廊、游戏、社交空间、互动艺术等)
  • 有多少个地块(parcel)?(默认:1 个地块 = 16x16m)
  • 有什么特定功能?(3D 模型、交互、UI、多人功能)

2. Scaffold the Project with
/init

2. 使用
/init
搭建项目

Always run
/init
first.
This uses the official
@dcl/sdk-commands init
to create scene.json, package.json, tsconfig.json, and src/index.ts with the correct, up-to-date configuration, and installs dependencies automatically.
Never manually create scene.json, package.json, or tsconfig.json — the SDK templates may change between versions and hand-written copies will diverge.
The
jsx
and
jsxImportSource
tsconfig settings are already included by
/init
— do not modify them.
始终先运行
/init
。
这会使用官方
@dcl/sdk-commands init
创建 scene.json、package.json、tsconfig.json 和 src/index.ts,并配置正确且最新的参数,同时自动安装依赖项。
绝不要手动创建 scene.json、package.json 或 tsconfig.json——SDK 模板可能会在不同版本之间发生变化,手动复制的配置会产生偏差。
jsx
和
jsxImportSource
tsconfig 设置已由
/init
包含——不要修改它们。

3. Find Matching 3D Assets

3. 查找匹配的 3D 资产

IMPORTANT: Only fetch models from the free catalogs below if the prompt explicitly asks to add new models. Confirm with the user always if they wish to add new models to their scene.
Before writing scene code, check the asset catalog for free models that match the user's theme:
  1. Search
    {baseDir}/../add-3d-models/references/model-catalog.md
    (8,800+ models with descriptions, dimensions, animations, and download URLs)
  2. Read
    {baseDir}/../audio-video/references/audio-catalog.md
    (50 free sounds — music, ambient, SFX, game mechanics, etc.)
  3. Suggest matching models and sounds to the user
  4. Download selected models into the scene's
    assets/Models/
    directory:
    bash
    mkdir -p assets/Models
    curl -o assets/Models/arcade_machine.glb "https://models.dclregenesislabs.xyz/blobs/bafybei..."
Important:
GltfContainer
only works with local files. Never use external URLs for the model
src
field.
Important: Always download into
assets/Models/
. Never write to the scene root.
Existing folders take precedence. If the scene already has
assets/scene/Models/
(legacy layout) or assets under
assets/asset-packs/
(Creator Hub asset packs) /
assets/custom/
(Creator Hub custom items), reuse those paths instead of creating a parallel
assets/Models/
. Same rule applies for
assets/Audio/
,
assets/Images/
, and
assets/Videos/
.
Done when: every model the user approved exists in
assets/Models/
(or the pre-existing asset folder per the precedence rule above), each file is non-empty and begins with the
glTF
magic bytes (
head -c 4 file.glb
) — a curl that saved an HTML error page fails this check — and no downloaded file sits at the project root. If the user declined new models, this step is done with nothing downloaded.
重要:仅当提示明确要求添加新模型时,才从以下免费目录获取模型。务必始终向用户确认是否要在场景中添加新模型。
在编写场景代码之前,检查与用户主题匹配的资产目录:
  1. 搜索
    {baseDir}/../add-3d-models/references/model-catalog.md
    (包含 8,800+ 个模型及其描述、尺寸、动画和下载 URL)
  2. 阅读
    {baseDir}/../audio-video/references/audio-catalog.md
    (包含 50 种免费音效——音乐、环境声、音效、游戏机制等)
  3. 向用户建议匹配的模型和声音
  4. 将选定的模型下载到场景的
    assets/Models/
    目录:
    bash
    mkdir -p assets/Models
    curl -o assets/Models/arcade_machine.glb "https://models.dclregenesislabs.xyz/blobs/bafybei..."
重要:
GltfContainer
仅支持本地文件。模型的
src
字段绝不能使用外部 URL。
重要: 始终下载到
assets/Models/
。绝不能将文件写入场景根目录。
已有文件夹优先。 如果场景已经包含
assets/scene/Models/
(旧版布局),或
assets/asset-packs/
(Creator Hub 资产包)/
assets/custom/
(Creator Hub 自定义项目)下的资产,请复用这些路径,不要创建平行的
assets/Models/
。同样的规则也适用于
assets/Audio/
、
assets/Images/
和
assets/Videos/
。
完成标准: 用户批准的每个模型都存在于
assets/Models/
(或根据上述优先级规则使用已有资产文件夹)中,每个文件均非空且以
glTF
magic bytes 开头(
head -c 4 file.glb
)——保存了 HTML 错误页面的 curl 操作无法通过此检查——并且项目根目录中没有任何下载文件。如果用户拒绝添加新模型,则此步骤无需下载任何内容即可完成。

4. Customize the Generated Files

4. 自定义生成的文件

After
/init
completes, customize the generated files based on what the user wants:
/init
完成后,根据用户需求自定义生成的文件:

scene.json

scene.json

Update the
display
fields and parcels:
  • display.title
    — set to the scene name
  • display.description
    — set to a short description
  • scene.parcels
    — for multi-parcel scenes, list all parcels (e.g.,
    ["0,0", "0,1", "1,0", "1,1"]
    for 2x2)
  • scene.base
    — set to the southwest corner parcel
更新
display
字段和地块:
  • display.title
    ——设置为场景名称
  • display.description
    ——设置一段简短描述
  • scene.parcels
    ——对于多地块场景,列出所有地块(例如,2x2 场景为
    ["0,0", "0,1", "1,0", "1,1"]
    )
  • scene.base
    ——设置为西南角地块

Composite vs TypeScript — where entities go

Composite 与 TypeScript——实体应放在哪里

NEVER create initial scene entities in TypeScript. They MUST go in
assets/scene/main.composite
.
If you find yourself writing
engine.addEntity()
for a piece of scenery or a static prop, stop — put it in the composite instead.
Use
.composite
for
Use
.ts
(index.ts) for
All entities present at scene load (models, lights, primitives, text, audio)Entities spawned dynamically at runtime (e.g., projectiles, clones, NPCs that appear on demand)
Static and decorative objectsEntities whose count or existence depends on runtime state
Entities that need behavior added later (fetch by name/tag in code)Entities whose identity/structure cannot be known at author time
Anything the Creator Hub should be able to display and edit visually—
Rationale: Composite assets load faster, are visually editable in the Creator Hub, and keep TypeScript code focused on logic rather than scene construction.
绝不要在 TypeScript 中创建初始场景实体。它们必须放在
assets/scene/main.composite
中。
如果发现自己在为某个布景或静态道具编写
engine.addEntity()
,请立即停止——应将其放入 composite 中。
对
.composite
的使用场景
对
.ts
(index.ts)的使用场景
加载场景时存在的所有实体(模型、灯光、基础几何体、文本、音频)在运行时动态生成的实体(例如投射物、克隆体、按需出现的 NPC)
静态和装饰性对象数量或存在与否取决于运行时状态的实体
之后需要添加行为的实体(可通过名称或标签在代码中获取)创作时无法确定其身份或结构的实体
Creator Hub 应能以可视化方式显示和编辑的任何内容—
原因: Composite 资产加载速度更快,可在 Creator Hub 中进行可视化编辑,并使 TypeScript 代码专注于逻辑而非场景构建。

assets/scene/main.composite

assets/scene/main.composite

Create
assets/scene/main.composite
with the initial scene entities. See
{baseDir}/../composites/composite-reference.md
for the full format.
Editing an existing scene? Read the "Editing an existing composite (edit mode)" section of the composite reference FIRST. If the scene has been opened in the Creator Hub,
main.composite
already contains
inspector::*
components; adding new entities without registering them in
inspector::Nodes
leaves them rendering in-world but invisible and un-selectable in the Creator Hub entity tree. The reference spells out the exact procedure.
Minimal example — a single named box. Components share entity IDs across their
data
maps, so all of entity
512
's data lives under the
"512"
key:
json
{
	"version": 1,
	"components": [
		{
			"name": "core::Transform",
			"data": {
				"512": {
					"json": {
						"position": { "x": 8, "y": 1, "z": 8 },
						"scale": { "x": 1, "y": 1, "z": 1 },
						"rotation": { "x": 0, "y": 0, "z": 0, "w": 1 },
						"parent": 0
					}
				}
			}
		},
		{
			"name": "core::MeshRenderer",
			"data": { "512": { "json": { "mesh": { "$case": "box", "box": {} } } } }
		},
		{
			"name": "core-schema::Name",
			"data": { "512": { "json": { "value": "BlueCube" } } }
		}
	]
}
For multi-entity scenes, GLB models with collision masks, tags, and the full component-grouping pattern, see
{baseDir}/../composites/composite-reference.md
.
IMPORTANT: When placing a floor entity, always set the y position to 0.01 or higher so that it doesn't z-fight with the default ground.
  • Center of a single-parcel scene is (8, 0, 8) at ground level.
  • Y axis is up; ground level is Y=0. Floors and walkable surfaces belong at Y ≥ 0 because players cannot descend below ground, but entities can be placed at negative Y — positioning objects underground is a legitimate technique for hiding them.
创建
assets/scene/main.composite
并放入初始场景实体。完整格式参见
{baseDir}/../composites/composite-reference.md
。
正在编辑现有场景? 请先阅读 composite 参考文档中的“编辑现有 composite(编辑模式)”一节。如果场景已在 Creator Hub 中打开,
main.composite
会包含
inspector::*
组件;添加新实体时如果不将其注册到
inspector::Nodes
,这些实体虽然会在场景中正常渲染,但在 Creator Hub 实体树中不可见且无法选择。参考文档给出了确切的操作步骤。
最小示例——一个带名称的盒子。组件通过各自的
data
映射共享实体 ID,因此实体
512
的所有数据都位于
"512"
键下:
json
{
	"version": 1,
	"components": [
		{
			"name": "core::Transform",
			"data": {
				"512": {
					"json": {
						"position": { "x": 8, "y": 1, "z": 8 },
						"scale": { "x": 1, "y": 1, "z": 1 },
						"rotation": { "x": 0, "y": 0, "z": 0, "w": 1 },
						"parent": 0
					}
				}
			}
		},
		{
			"name": "core::MeshRenderer",
			"data": { "512": { "json": { "mesh": { "$case": "box", "box": {} } } } }
		},
		{
			"name": "core-schema::Name",
			"data": { "512": { "json": { "value": "BlueCube" } } }
		}
	]
}
对于多实体场景、带碰撞掩码的 GLB 模型、标签以及完整的组件分组模式,请参阅
{baseDir}/../composites/composite-reference.md
。
重要: 放置地板实体时,始终将 y 位置设为 0.01 或更高,以避免与默认地面发生 z-fighting。
  • 单一地块场景的中心位于地面高度 (8, 0, 8)。
  • Y 轴向上;地面高度为 Y=0。地板和可行走表面必须位于 Y ≥ 0,因为玩家无法下降到地面以下,但实体可以放在 Y 为负的位置——将物体置于地下是一种有效的隐藏方式。

src/index.ts

src/index.ts

Use
index.ts
only for:
  • Behavior and interactivity on composite entities (fetch them by name or tag)
  • Dynamically spawned entities (e.g., enemies, projectiles, clones)
  • Systems, game logic, UI
To add interactivity to a composite entity, look it up by name or tag — do NOT re-create it in code:
typescript
import { engine, pointerEventsSystem, InputAction } from '@dcl/sdk/ecs'
import { EntityNames } from '../assets/scene/entity-names'

export function main() {
	// Fetch an entity defined in the composite — never re-create it here
	const cube = engine.getEntityOrNullByName(EntityNames.BlueCube)
	if (cube) {
		pointerEventsSystem.onPointerDown(
			{
				entity: cube,
				opts: { button: InputAction.IA_PRIMARY, hoverText: 'Click me' },
			},
			() => {
				console.log('Cube clicked!')
			}
		)
	}
}
To fetch groups of entities by tag (
engine.getEntitiesByTag
) or add/remove tags at runtime, see the "Referencing Composite Entities from Code" section of
{baseDir}/../composites/composite-reference.md
.
仅将
index.ts
用于:
  • 为 composite 实体提供行为和交互(按名称或标签获取)
  • 运行时动态生成的实体(例如敌人、投射物、克隆体)
  • 系统、游戏逻辑、UI
要为 composite 实体添加交互性,请按名称或标签查找它——不要在代码中重新创建:
typescript
import { engine, pointerEventsSystem, InputAction } from '@dcl/sdk/ecs'
import { EntityNames } from '../assets/scene/entity-names'

export function main() {
	// Fetch an entity defined in the composite — never re-create it here
	const cube = engine.getEntityOrNullByName(EntityNames.BlueCube)
	if (cube) {
		pointerEventsSystem.onPointerDown(
			{
				entity: cube,
				opts: { button: InputAction.IA_PRIMARY, hoverText: 'Click me' },
			},
			() => {
				console.log('Cube clicked!')
			}
		)
	}
}
要按标签获取实体组(
engine.getEntitiesByTag
)或在运行时添加/移除标签,请参阅
{baseDir}/../composites/composite-reference.md
中的“在代码中引用 Composite 实体”一节。

scene.json Reference

scene.json 参考

All valid
scene.json
fields:
FieldRequiredDescription
ecs7
Conventional
true
in SDK7 scenes. Written by
init
; the build only validates
runtimeVersion
, but keep it for tooling compatibility
runtimeVersion
YesMust be
"7"
main
YesMust be
"bin/index.js"
— the compiled output path
display.title
RecommendedScene name shown in the map and Places
display.description
RecommendedShort description for discovery
display.navmapThumbnail
OptionalImage path for the Genesis City minimap
scene.parcels
YesArray of
"x,y"
coordinate strings
scene.base
YesThe origin parcel (usually southwest corner)
spawnPoints
OptionalWhere players appear when entering (see below)
requiredPermissions
OptionalArray of permissions (e.g.,
"ALLOW_MEDIA_HOSTNAMES"
)
allowedMediaHostnames
OptionalWhitelisted domains for external media
featureToggles
OptionalEnable/disable SDK features
worldConfiguration
OptionalFor Worlds deployment (see deploy-worlds skill)
landscapeTerrain
OptionalBoolean, default
true
. Root-level field. Worlds only (single-scene Worlds; ignored in Genesis City). Set
false
to disable the auto-generated grassland/trees/sea landscape around the scene — for open-water/space settings and to free rendering budget. Also applies in local preview. In the Creator Hub, it is a toggle in the Scene Inspector settings (and a preview menu option); a scene-level
false
overrides the preview preference.
scene.json
的所有有效字段:
字段必需性描述
ecs7
惯例上SDK7 场景中为
true
。由
init
写入;构建仅验证
runtimeVersion
,但应保留此项以兼容工具链
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 skill)
landscapeTerrain
可选布尔值,默认
true
。根级字段。仅适用于 Worlds(单场景 Worlds;在 Genesis City 中忽略)。设为
false
可禁用场景周围自动生成的草地/树木/海洋景观——适用于开放水域/太空场景,也可释放渲染预算。本地预览中同样有效。在 Creator Hub 中,它是 Scene Inspector 设置里的开关(预览菜单中也有该选项);场景级
false
的优先级高于预览偏好。

Tags

标签

Valid values for the
tags
array:
"art"
,
"game"
,
"casino"
,
"social"
,
"music"
,
"fashion"
,
"crypto"
,
"education"
,
"shop"
,
"business"
,
"sports"
,
"parkour"
tags
数组的有效值:
"art"
、
"game"
、
"casino"
、
"social"
、
"music"
、
"fashion"
、
"crypto"
、
"education"
、
"shop"
、
"business"
、
"sports"
、
"parkour"

Required Permissions

必需权限

Add to
requiredPermissions
when your scene uses these features:
These are the exact 7 permission strings the runtime recognizes (the protocol enum names drop the
PI_
prefix):
PermissionWhen needed
ALLOW_TO_MOVE_PLAYER_INSIDE_SCENE
movePlayerTo
(move player within the scene)
ALLOW_TO_TRIGGER_AVATAR_EMOTE
triggerEmote
and
triggerSceneEmote
ALLOW_MEDIA_HOSTNAMES
[LEGACY]
External video/audio streams — not required (see below)
USE_WEB3_API
Blockchain interactions
USE_FETCH
HTTP requests (
fetch
/
signedFetch
)
USE_WEBSOCKET
WebSocket connections
OPEN_EXTERNAL_LINK
openExternalUrl
(open URLs in the browser)
Grounded caveat (from the engine test scenes): enforcement is uneven, so declare the correct permission for intent rather than relying on it being blocked. The
80,-4-restricted-actions
scene declares only
ALLOW_TO_MOVE_PLAYER_INSIDE_SCENE
+
ALLOW_TO_TRIGGER_AVATAR_EMOTE
, yet successfully runs
openExternalUrl
,
openNftDialog
,
teleportTo
, and
changeRealm
without
OPEN_EXTERNAL_LINK
. The
66,6-signed-fetch
scene calls
signedFetch
with an empty
requiredPermissions
.
movePlayerTo
and emotes are the two whose permissions the engine team consistently declares.
teleportTo
(jump to other Genesis City coords) needs no permission.
[LEGACY]
ALLOW_MEDIA_HOSTNAMES
and
allowedMediaHostnames
are not required — do not add them for new scenes. The permission string still exists in
@dcl/schemas
, but no current client enforces it: unity-explorer gates the hostname check behind the
CHECK_ALLOWED_MEDIA_HOSTNAMES
compile define, which is set in no build config (
SceneData.TryGetMediaUrl
falls through to a plain URL syntax check), and bevy-explorer has no enforcement at all. Only the retired web client enforced it. Current clients play external media without it. If a legacy scene still declares it, whitelist the domains as follows:
json
"requiredPermissions": ["ALLOW_MEDIA_HOSTNAMES"],
"allowedMediaHostnames": ["youtube.com", "www.youtube.com", "player.vimeo.com", "twitch.tv"]
当场景使用以下功能时,将其添加到
requiredPermissions
:
以下是 runtime 识别的确切 7 个权限字符串(协议枚举名称会去掉
PI_
前缀):
权限何时需要
ALLOW_TO_MOVE_PLAYER_INSIDE_SCENE
movePlayerTo
(在场景内移动玩家)
ALLOW_TO_TRIGGER_AVATAR_EMOTE
triggerEmote
和
triggerSceneEmote
ALLOW_MEDIA_HOSTNAMES
[LEGACY]
外部视频/音频流——不需要(见下文)
USE_WEB3_API
区块链交互
USE_FETCH
HTTP 请求(
fetch
/
signedFetch
)
USE_WEBSOCKET
WebSocket 连接
OPEN_EXTERNAL_LINK
openExternalUrl
(在浏览器中打开 URL)
实际情况说明(来自引擎测试场景): 权限执行并不一致,因此应根据使用意图声明正确权限,不要依赖权限一定会阻止操作。
80,-4-restricted-actions
场景只声明了
ALLOW_TO_MOVE_PLAYER_INSIDE_SCENE
和
ALLOW_TO_TRIGGER_AVATAR_EMOTE
,却成功执行了
openExternalUrl
、
openNftDialog
、
teleportTo
和
changeRealm
,且未使用
OPEN_EXTERNAL_LINK
。
66,6-signed-fetch
场景以空的
requiredPermissions
调用
signedFetch
。
movePlayerTo
和 emote 是引擎团队始终会声明权限的两项功能。
teleportTo
(跳转到其他 Genesis City 坐标)不需要权限。
[LEGACY]
ALLOW_MEDIA_HOSTNAMES
和
allowedMediaHostnames
不是必需项——不要为新场景添加它们。该权限字符串仍存在于
@dcl/schemas
中,但当前没有任何客户端执行它:unity-explorer 将 hostname 检查置于编译常量
CHECK_ALLOWED_MEDIA_HOSTNAMES
之后,而所有构建配置均未设置该常量(
SceneData.TryGetMediaUrl
最终只进行普通 URL 语法检查);bevy-explorer 则完全不执行检查。只有已停用的 web 客户端会执行该限制。当前客户端无需它即可播放外部媒体。如果旧版场景仍声明了此项,请按如下方式将域名加入白名单:
json
"requiredPermissions": ["ALLOW_MEDIA_HOSTNAMES"],
"allowedMediaHostnames": ["youtube.com", "www.youtube.com", "player.vimeo.com", "twitch.tv"]

Feature Toggles

功能开关

json
"featureToggles": {
  "voiceChat": "enabled",
  "portableExperiences": "enabled"
}
Valid values:
"enabled"
,
"disabled"
. For
portableExperiences
also:
"hideUi"
.
json
"featureToggles": {
  "voiceChat": "enabled",
  "portableExperiences": "enabled"
}
有效值为
"enabled"
、
"disabled"
。对于
portableExperiences
,还可以使用
"hideUi"
。

Spawn Points

出生点

Configure where and how players enter the scene:
json
{
	"spawnPoints": [
		{
			"name": "spawn1",
			"default": true,
			"position": { "x": [1, 5], "y": [0, 0], "z": [2, 4] },
			"cameraTarget": { "x": 8, "y": 1, "z": 8 }
		}
	]
}
  • Position ranges (e.g.,
    [1, 5]
    ) spawn players randomly within the range
  • cameraTarget
    orients the player's camera on spawn — point it at the scene's focal area
  • Fixed spawn: use single values instead of ranges (e.g.,
    "x": 8
    )
配置玩家进入场景的位置和方式:
json
{
	"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
    )

Multi-Parcel Layouts

多地块布局

LayoutParcels ArrayUse Case
Single
["0,0"]
Small games, galleries, single-room experiences
Strip
["0,0", "1,0", "2,0"]
Hallways, racing tracks, linear journeys
L-Shape
["0,0", "1,0", "0,1"]
Corner buildings, split experiences
2x2 Square
["0,0", "1,0", "0,1", "1,1"]
Open plazas, arenas, medium games
3x3 Square9 parcels from
"0,0"
to
"2,2"
Large games, multi-room buildings
Base parcel: Always set
scene.base
to the southwest (lowest x,y) corner parcel.
Boundaries: each parcel is 16m x 16m; a 2x2 scene spans 32m x 32m. The height limit applies to the whole scene and grows with parcel count:
log2(n+1) × 20
meters (1 parcel = 20m, 2x2 = ~46m, 3x3 = ~66m).
  • Always validate entity positions against parcel bounds. With the default base parcel at the lower-left corner, valid range is
    0 ≤ x ≤ 16*parcelsWide
    and
    0 ≤ z ≤ 16*parcelsDeep
    . Any negative X or Z coordinate is outside the scene. An entity entirely outside the bounds is not rendered and no error is shown; a model that straddles the boundary still renders the part that is inside. The bound check uses world positions, so a child whose parent is moved out of bounds disappears with it, and exceeding the height limit hides the entity too. Multi-parcel scenes are only rectangular if you list every parcel; an L-shaped parcel set has "holes" that are out of bounds. (See the
    5,90-scene-bounds-check
    example scene.)
Changing parcels in an existing scene: Modifying
scene.parcels
shifts the coordinate bounds for the entire scene — entities near the current boundary may end up outside (invisible) after the change. Before editing this field, describe the proposed change and confirm with the user first. See the "Agent Behavioral Guidelines" section in the
sdk-scenes
skill (
{baseDir}/../sdk-scenes/SKILL.md
).
Done when: (1)
main.composite
parses as JSON and every entity ID that appears in any component's
data
map has a
core::Transform
and a
core-schema::Name
entry; (2) every composite position lies within parcel bounds (
0 ≤ x ≤ 16·width
,
0 ≤ z ≤ 16·depth
) — an entity placed entirely outside is silently hidden, and a model straddling the boundary renders only the part inside; (3)
src/index.ts
contains no
engine.addEntity()
for load-time scenery — grep for
engine.addEntity
and confirm every hit is a runtime spawn; (4)
scene.json
has
"runtimeVersion": "7"
and
scene.base
is a member of
scene.parcels
; (5)
npm run build
exits 0.
布局地块数组使用场景
单地块
["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;2x2 场景占地 32m x 32m。高度限制适用于整个场景,并随地块数量增加:
log2(n+1) × 20
米(1 个地块 = 20m,2x2 ≈ 46m,3x3 ≈ 66m)。
  • 务必根据地块边界验证实体位置。 当基础地块默认位于左下角时,有效范围为
    0 ≤ x ≤ 16*parcelsWide
    和
    0 ≤ z ≤ 16*parcelsDeep
    。任何负的 X 或 Z 坐标都位于场景之外。 完全位于边界之外的实体不会渲染,也不会显示错误;跨越边界的模型只会渲染其位于边界内的部分。边界检查使用世界坐标,因此如果父实体的位置被移到边界外,其子实体也会随之消失;超过高度限制同样会隐藏实体。只有列出每个地块时,多地块场景才是矩形;L 形地块集合会存在超出边界的“空洞”。(参见
    5,90-scene-bounds-check
    示例场景。)
  • 修改现有场景的地块: 修改
    scene.parcels
    会改变整个场景的坐标边界——修改后,靠近原边界的位置可能落到场景之外(不可见)。编辑此字段前,请先说明拟议的更改并向用户确认。请参阅
    sdk-scenes
    skill(
    {baseDir}/../sdk-scenes/SKILL.md
    )中的“Agent 行为准则”一节。
完成标准: (1)
main.composite
可解析为 JSON,且任何组件
data
映射中出现的每个实体 ID 都有
core::Transform
和
core-schema::Name
条目;(2) 每个 composite 位置都位于地块边界内(
0 ≤ x ≤ 16·width
、
0 ≤ z ≤ 16·depth
)——完全位于边界之外的实体会被静默隐藏,跨越边界的模型只会渲染其位于边界内的部分;(3)
src/index.ts
中不包含用于加载时布景的
engine.addEntity()
——搜索
engine.addEntity
,并确认每个命中项都是运行时生成;(4)
scene.json
包含
"runtimeVersion": "7"
,且
scene.base
是
scene.parcels
的成员;(5)
npm run build
的退出码为 0。

5. Post-Creation Steps

5. 创建完成后的步骤

After customizing the files:
  1. Use the
    preview
    tool to start the preview server (or run
    npx @dcl/sdk-commands start --bevy-web
    manually)
  2. The scene will open in a browser at http://localhost:8000
自定义文件后:
  1. 使用
    preview
    工具启动预览服务器(或手动运行
    npx @dcl/sdk-commands start --bevy-web
    )
  2. 场景将在浏览器中的 http://localhost:8000 打开

Preview CLI flags

预览 CLI 参数

FlagTypeDescription
--web
(alias
--bevy-web
)
booleanOpen the preview in the Bevy Web browser client at
decentraland.org/bevy-web/
instead of the Desktop Explorer. Chromium 142+ requires Local Network Access permission for the page to reach the localhost preview server -- when the browser asks to access apps on your device, click "Allow".
--mcp
booleanEnable the MCP server in the Explorer (forwarded as a deep-link parameter)
--mcp-port
numberPort for the MCP server in the Explorer
--multi-instance
booleanAllow running multiple Explorer instances simultaneously
--no-client
booleanSuppress auto-launch (desktop deeplink, browser, mobile QR); the file watcher still notifies a desktop Explorer if it connects on its own
-- <args>
passthroughArguments after a standalone
--
are forwarded verbatim into the Explorer deep link as query params (
--key=value
,
--key value
, bare
--key
= true)
--web-explorer
has been removed.
--web3
and
--no-debug
(alias
-d
) are deprecated no-ops kept for backwards compatibility only -- do not use them in new scenes.
Bevy renderer in Creator Hub: Settings > Editor > "Scene renderer" dropdown (Babylon default / Bevy preview). Gated behind the Experimental features toggle. The Bevy editor supports gizmos, multi-select, free-fly camera, spawn point visualization, drag-drop assets, animation clip dropdown, lock/hide entities, screenshots, and hot-reload.
Keep
.dclignore
(project root) up to date.
It lists files and extensions that are NOT uploaded on deploy. Whenever the project contains working files — Blender/FBX sources, draft models, concept art, spreadsheets, markdown notes — add them (or their extensions) to
.dclignore
proactively so the deployed scene stays light. See the
.dclignore
section in the deploy-scene skill.
Done when: the preview server responds at
http://localhost:8000
and the scene renders with no errors in the console.
参数类型描述
--web
(别名
--bevy-web
)
boolean在 decentraland.org/bevy-web/ 的 Bevy Web 浏览器客户端中打开预览,而不是 Desktop Explorer。Chromium 142+ 需要 Local Network Access 权限,页面才能访问 localhost 预览服务器——当浏览器询问是否允许访问设备上的应用时,点击“允许”。
--mcp
boolean启用 Explorer 中的 MCP 服务器(作为 deep-link 参数转发)
--mcp-port
numberExplorer 中 MCP 服务器的端口
--multi-instance
boolean允许同时运行多个 Explorer 实例
--no-client
boolean禁止自动启动(桌面端 deep link、浏览器、移动端二维码);如果 Desktop Explorer 自行连接,文件监视器仍会向其发送通知。
-- <args>
透传独立
--
后的参数会原样作为查询参数转发到 Explorer deep link(
--key=value
、
--key value
、裸
--key
= true)
--web-explorer
已被移除。
--web3
和
--no-debug
(别名
-d
)是已弃用的空操作项,仅为向后兼容而保留——不要在新场景中使用它们。
Creator Hub 中的 Bevy renderer: Settings > Editor > “Scene renderer”下拉框(默认 Babylon / Bevy 预览)。此功能受 Experimental features 开关控制。Bevy editor 支持 gizmos、多选、自由飞行摄像机、出生点可视化、拖放资产、动画片段下拉框、锁定/隐藏实体、截图和热重载。
保持项目根目录中的
.dclignore
为最新状态。
它会列出部署时不会上传的文件和扩展名。每当项目包含工作文件——Blender/FBX 源文件、模型草稿、概念图、电子表格、Markdown 笔记——都应主动将它们(或其扩展名)添加到
.dclignore
,以确保部署的场景保持轻量。参见 deploy-scene skill 中的
.dclignore
一节。
完成标准: 预览服务器能够在 http://localhost:8000 响应请求,且场景渲染时控制台中没有错误。

Vibe Coding with AI

使用 AI 进行 Vibe Coding

AI assistants (Cursor, Claude Code, etc.) can build entire scenes from plain-language prompts. Install Decentraland SDK skills first so the AI knows SDK patterns:
bash
npx skills add decentraland/sdk-skills
The official quickstart teaches a Script-component-first workflow: attach a Script component to an entity in the Creator Hub, write a class with
constructor(src, entity)
,
start()
, and
update(dt)
, and use
this.entity
to reference the holder entity. This keeps behavior self-contained and reusable across entities. See the script-components skill for full details.
AI 助手(Cursor、Claude Code 等)可以根据自然语言提示构建完整场景。请先安装 Decentraland SDK skills,让 AI 掌握 SDK 模式:
bash
npx skills add decentraland/sdk-skills
官方 quickstart 讲解了以 Script 组件优先的工作流:将 Script 组件附加到 Creator Hub 中的实体,编写包含
constructor(src, entity)
、
start()
和
update(dt)
的类,并使用
this.entity
引用承载该组件的实体。这样可以使行为自包含,并可在多个实体之间复用。完整详情请参阅 script-components skill。

Cross-References

交叉引用

  • Ready to deploy? See the deploy-scene skill (Genesis City) or deploy-worlds skill (personal Worlds)
  • Need to optimize for parcel limits? See the optimize-scene skill
  • Planning a game? See the game-design skill for design patterns and performance budgets
  • Validate entity component combinations: see
    {baseDir}/references/entity-validation-rules.md
    for rules on which components require each other, mutual exclusions, and common misconfigurations
  • 准备部署?请参阅 deploy-scene skill(Genesis City)或 deploy-worlds skill(个人 Worlds)
  • 需要针对地块上限进行优化?请参阅 optimize-scene skill
  • 正在规划游戏?请参阅 game-design skill,了解设计模式和性能预算
  • 验证实体组件组合:参阅
    {baseDir}/references/entity-validation-rules.md
    ,了解组件依赖关系、互斥关系和常见配置错误

Example scenes

示例场景

Engine-team test scenes illustrating
scene.json
configuration: