Loading...
Loading...
Migrate a legacy Decentraland SDK6 scene to SDK7. Use when the user wants to port an SDK6 scene, upgrade the decentraland-ecs dependency to @dcl/sdk, or rewrite class-based scene code in the ECS style. Do NOT use for new scenes (see create-scene) or for SDK7-to-SDK7 refactors.
npx skill4agent add decentraland/sdk-skills migrate-sdk6-to-sdk7This is a porting skill, not a scaffolding skill. It assumes an existing SDK6 project on disk. For a brand-new SDK7 scene, use [[create-scene]].
| Check | SDK6 signal | SDK7 signal |
|---|---|---|
| | |
| | |
| No | |
| Source code imports | No explicit | Most things imported from |
| Source code patterns | | |
scene.jsonmainmain"bin/game.js"bin/index.jssdk-commands buildscene.jsonmainsdk-commandsbundle.tssceneJson.mainbin/game.jsbin/index.js"runtimeVersion": "7"scene.jsonassets/scene/main.compositeengine.addEntity()assets/scene/main.composite| Concept | SDK6 | SDK7 |
|---|---|---|
| Entity creation | | |
| Entity type | | |
| Adding a component | | |
| Defining a component | | |
Component methods ( | Allowed (class methods) | Forbidden — components are data only. Move methods into free functions or systems |
| Reading component data | | |
| Modifying component data | Mutate the returned reference | MUST use |
| Parenting | | Set |
| Defining a system | | |
| Querying entities | | |
| Removing an entity | | |
| Event callbacks on components | | |
| Static "scene-level" objects | | |
.get().getMutable().getMutable(){baseDir}/references/api-mapping.md| SDK6 | SDK7 |
|---|---|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
Custom per-frame | Delete it — use |
@Componentengine.defineComponent(...)reset()class X implements ISystem(dt: number) => voidOnPointerDownOnPointerUpInput.instance.subscribepointerEventsSysteminputSystem.isTriggered()GLTFShapeBoxShapeCamera.instanceInput.instancesetParentTransform.parentpackage.jsontsconfig.jsonscene.jsondecentraland-ecs@dcl/sdkbuild-ecsdcl startsdk-commands startsdk-commands buildtsconfig.jsontarget: ES2020module: ESNextjsx: react-jsxstrict: true"runtimeVersion": "7"scene.jsonmainassets/models/images/audio/sounds/textures/videos/assets/models/images/audio/sounds/textures/videos/assets/models/assets/Models/images/assets/Images/audio/sounds/assets/Audio/videos/assets/Videos/textures/assets/Images/GltfContainer.create(e, { src: 'models/chair.glb' })... { src: 'assets/Models/chair.glb' }AudioSource.create(e, { audioClipUrl: 'sounds/click.mp3' })... 'assets/Audio/click.mp3'Material.Texture.Common({ src: 'textures/logo.png' })... 'assets/Images/logo.png'<UiEntity uiBackground={{ texture: { src: 'images/icon.png' } }} />... 'assets/Images/icon.png'.compositeassets/assets/scene/Models/assets/asset-packs/assets/custom/assets/Models/src/index.tsmain()main()src/game.tsindex.tsimport { initializeGame } from "./game";
export function main() {
initializeGame();
}@Componentengine.defineComponent(name, schema, defaults)SchemasSchemas.Vector3Schemas.QuaternionSchemas.Map(...)Vector2posXposY{baseDir}/references/migration-example.mdgrep -rn "@Component(" src/engine.defineComponentclass X implements ISystem { update(dt) {...} }engine.getComponentGroup(A, B).entitiesfor (const [entity, a, b] of engine.getEntitiesWith(A, B)).getMutable(entity)grep -rnE "implements ISystem|getComponentGroup" src/engine.addSystemgame.tsnew Entity()engine.addEntity()Component.create(entity, ...)setParentparentassets/Models/...assets/Audio/...assets/Images/...srcaudioClipUrltexture.srcgrep -rnE "new Entity\(|\.addComponent\(|\.setParent\(" src/srcaudioClipUrlnew OnPointerDown(...)pointerEventsSystem.onPointerDown({ entity, opts }, handler)MeshCollider.setBox(entity)visibleMeshesCollisionMask: 1GltfContainerInput.instance.subscribeinputSystem.isTriggered(InputAction.IA_X, PointerEventType.PET_DOWN)grep -rnE "OnPointerDown|OnPointerUp|Input\.instance|ActionButton\." src/pointerEventsSysteminputSystemnew Animator()new AnimationState('clip')animator.addClip(...)Animator.create(entity, { states: [{ clip, playing, loop }] })Animator.playSingleAnimation(entity, 'clip')Animator.stopAllAnimations(entity)grep -rnE "new Animator|AnimationState|addClip|getClip" src/playAnimationgetClipstates[]states[]playSingleAnimationnew AudioClip(url)entity.addComponent(new AudioSource(clip))AudioSource.create(entity, { audioClipUrl: url, playing: false, ... })AudioSource.getMutable(entity).playing = truegrep -rnE "new AudioClip|new AudioSource\(" src/npm installsdk-commands startnpm startnpm run buildgrep -rnE "decentraland-ecs|@Component\(|implements ISystem|Input\.instance|Camera\.instance" src/.get()Transform.get(entity).position.x = 5Transform.getMutable(entity).position.x = 5rotation: undefinedscale: undefinedTransform.create"Cannot read properties of undefined (reading 'x')"@dcl/ecs/dist/components/manual/Transform.jsTransform.createTransformSchema.extend...valueundefinedundefinedserializevalue.rotation.xundefinedTransform.create(e, { position, rotation: maybeRot, scale: maybeScale })undefinedconst out: Partial<TransformType> = { position }
if (rotation) out.rotation = rotation
if (scale) out.scale = scale
if (parent !== undefined) out.parent = parent
Transform.create(entity, out)engine.defineComponentreset()SchemasSchemas.Vector2Schemas.NumberSchemas.Map({ x: Schemas.Number, y: Schemas.Number })setParentparentTransformColor4Color3.X()Color4.X()new Material()Material.setPbrMaterial(entity, props)BoxShapewithCollisions: trueGltfContainervisibleMeshesCollisionMaskCL_POINTERCL_PHYSICS3OnPointerDownforEachpointerEventsSystem.onPointerDown(...)Animator.playSingleAnimationAnimator.statesAnimatorAnimator.playSingleAnimation(entity, clipName)playSingleAnimationfalseclipNamestates@dcl/ecs/dist-cjs/components/extended/Animator.jsAnimator.getClip(name)playAnimation('Appear')'Appear'entity.getComponent(Animator).getClip(name).play()Animator.playSingleAnimation(entity, name)states[]playAnimationgetClipstatesAnimator.createstates.pushstates[]statesAnimatoranim.stop(); anim.play()anim.stop(); anim.play()Animator.statess.playings.shouldReset@dcl/ecsgetMutableOrNull()noLoop + revertToIdleonPointerDownAnimator.playSingleAnimationGltfContainerAnimatorAnimatorAnimatorplaySingleAnimationstates[]AnimatordieAnimator.create(entity, { states: [{ clip: '<intended-default>', playing: true, loop: true }] })playSingleAnimationstates[]Input.instance.subscribeBUTTON_DOWNBUTTON_UPinputSystem.isTriggered()@dcl/ecs-scene-utilsCamera.instance.positiononCameraEnteronCameraExitTriggerArea@dcl/sdk/ecsTriggerArea.setBox(entity).setSpheretriggerAreaEventsSystem.onTriggerEnter(entity, cb).onTriggerExit.onTriggerStayTransform.scaleTransform.positionTriggerAreaColliderLayer.CL_PLAYERif (result.trigger?.entity !== engine.PlayerEntity) returnresult.triggeredEntitytriggeredEntity{baseDir}/references/api-mapping.mdutils.Delayutils.ExpireIndecentraland-ecs-utils@dcl-sdk/utilsDelaysetSceneTimeouttimerSystemdttimers@dcl/sdk/ecsimport { timers } from '@dcl/sdk/ecs'setTimeoutclearTimeoutsetIntervalclearIntervalentity.addComponent(new utils.Delay(2000, cb))timers.setTimeout(cb, 2000)(callback, ms)(ms, callback)Delay(ms, cb)setTimeoutsetIntervaltimersInput.instance.subscribe('BUTTON_DOWN', ActionButton.POINTER, true, …)pointerEventsSystem.onPointerDownpointerEventsSystem.onPointerDown{baseDir}/references/api-mapping.md#click-interception-across-entities-keytool-acting-on-a-targetVector3.GetAngleBetweenVectorsVector3.Up()@dcl/sdk/mathVector3.LerpVector3.lerpVector3.log()console.log()Attachable.FIRST_PERSON_CAMERAAttachable.AVATARAttachable.FIRST_PERSON_CAMERAAttachable.AVATARAvatarAttachanchorPointIdAAPT_RIGHT_HANDAAPT_RIGHT_HANDTransform.parentAvatarAttachTransform.parent = engine.CameraEntityFIRST_PERSON_CAMERATransform.parent = engine.PlayerEntityPlayerEntityPlayerEntityAvatarAttachengine.CameraEntityengine.PlayerEntityAvatarAttach(boneId)new Billboard(false, true, false)Billboard.create(e, { billboardMode: BillboardMode.BM_Y })PBBillboardoppositeDirectionbillboardMode@dcl/ecsbillboard.gen.d.tsQuaternion.fromEulerDegrees(0, 180, 0)BillboardTransform.rotationUICanvasUIImageUITextwidth = 200positionX = -350ReactEcsRenderer.setUiRendererReactEcsRenderer.setUiRenderer(uiRoot, { virtualWidth: 1920, virtualHeight: 1080 })1920x10801280x720GemData.reset(val, x, y)(entity: Entity, val: number, ...)Component.getMutable(entity)engine.getEntitiesWith(...)entity.alivealiveComponent.has(entity)UICanvasUIImageUITextUIClickableReactEcsRenderer.setUiRenderer@Component('name')engine.defineComponent('name', ...).compositeGltfContainerpointerEventsSystemOnPointerDowninputSystemInput.instance.subscribetimers.setTimeouttimers.setInterval@dcl/sdk/ecsdecentraland-ecs-utilsDelayIntervalexecuteTaskfetchAnimatorTweenAnimatorAnimationStateAudioSourceVideoPlayerUICanvassyncEntityMessageBus{baseDir}/references/api-mapping.md{baseDir}/references/migration-example.md