Decentraland SDK 6.0 Beta Migration Guide
Everything you need to know to migrate your scenes to the latest version of the SDK
The 6.0 Beta release of the Decentraland SDK includes some changes that may break your scenes’ existing code. These changes are not as drastic as the changes introduced in version 5.0, but they do still affect all scenes built using previous versions of the SDK.
So, we’ve written a migration guide to help you transition to the new SDK as quickly and smoothly as possible. If you continue to have problems with your migration after working through this guide, please reach out for help in Decentraland’s Developers channel.
Creating a scene in the SDK 6.0 beta
To create a new scene that uses the SDK 6.0 beta, make sure you have the latest version of the CLI installed, and create a new project, with dcl init
.
To make sure you have the latest version of the CLI, run:
npm install -g decentraland
Migrate an existing project to the SDK 6.0 beta
To migrate an existing project, follow these steps:
- Delete the
bin
and thenode_modules
folders of the project you want to migrate. - Delete the
package-lock.json
file. - Make sure that in the
package.json
file, thedecentraland-ecs
field is set tolatest
. - Run
npm install
on your project’s folder. - Make the syntax changes in your code according to the rest of this migration guide.
General syntax changes
The following commands for handling components have been renamed for better clarity and to make it more obvious just what they do. Your scene probably uses at least a couple of these, so it’s worth double checking your code and making sure that you update any obsolete commands.
Old Command | New Command |
---|---|
add | addComponent |
set | addComponentOrReplace |
get | getComponent |
getOrNull | getComponentOrNull |
getOrCreate | getComponentOrCreate |
remove | removeComponent |
has | hasComponent |
Old code:
const ent = new Entity()
ent.add(new GLTFShape('models/Environment.glb'))
ent.add(new Transform({
position: new Vector3(5, 0, 5)
}))
engine.addEntity(ent)
New code:
const ent = new Entity()
ent.addComponent(new GLTFShape('models/Environment.glb'))
ent.addComponent(new Transform({
position: new Vector3(5, 0, 5)
}))
engine.addEntity(ent)
Tip: We recommend running a “find and replace” command over your entire project to make sure you’re using the most recent commands and terms. If you do, remember that the
set
command could also refer to the command used to set a specific position, rotation, or scale, which hasn’t changed. So be careful not to replace any commands that have not changed. For example:myTransformComponent.position.set(5, 0, 5)
.
Larger parcels
Each parcel in Decentraland now measures 16 meters x 16 meters (as opposed to the previous 10 x 10 format). As a result, you now have far more space to host content in your scene! Please note that the limits of polygons in your scene are based on the number of parcels that make up your scene, not the surface area, so these limits haven’t changed.
Since single parcel scenes now measure 16 x 16, the center of each scene has moved to (8, 0, 8)
. Depending on the content of your scene, you might want to scale all of your entities up by a factor of 1.6
to fill the entire space. Otherwise, you may need to add new content to fill in the gaps.
3D model rotation
We changed how the SDK internally sets the rotation of all 3D models in a scene so that it follows standards that are consistent with most other platforms. This means that any 3D models in your scene will now be rendered facing backwards, rotated 180 degrees along the Y axis. You may have to reposition or rotate your entities to compensate for this new rotation.
If you used the lookAt
function to set the rotation of an entity, keep in mind that what used to be the front of the entity is now its back. In these cases, our recommendation is that you edit the 3D model in an external tool like Blender so that it faces the opposite direction on the Y axis.
Animations
3D model animations are now handled by a separate Animator
component, instead of the GLTFModel
component.
Also, we’ve renamed the AnimationClip
object to AnimationState
to help avoid any confusion with the actual animation clip in the glTF file.
Old code:
let shark = new Entity()
shark.add(new GLTFShape("models/shark.gltf"))
let clipSwim = shark.get(GLTFShape).getClip("swim")
clipSwim.play()
engine.addEntity(shark)
New code:
let shark = new Entity()
shark.addComponent(new GLTFShape("models/shark.gltf"))
const animator = new Animator()
shark.addComponent(animator)
let clipSwim = new AnimationState("swim")
animator.addClip(clipSwim)
clipSwim.play()
engine.addEntity(shark)
Read more about this in the documentation or look at an example scene that uses this feature.
Audio
Audio is now handled by a SoundSource
component that must be added to an entity. You don’t need to use the executeTask
function anymore.
Old code:
executeTask(async () => {
try {
await playSound("sounds/Vexento.ogg", {
loop: true,
volume: 75,
})
} catch {
log('failed to play sound')
}
})
New code:
const ent = new Entity()
const audioClip = new AudioClip("sounds/Vexento.ogg")
const audioSource = new AudioSource(audioClip)
ent.addComponent(audioSource)
audioSource.playing = true
engine.addEntity(ent)
Read more about this in the documentation or look at an example scene that uses this feature.
Billboard mode
Billboard
is now a separate component, instead of a setting applied to shape components.
Old code:
let ent = new Entity()
ent.add(new BoxShape())
ent.get(BoxShape).billboard = BillboardMode.BILLBOARDMODE_ALL
engine.addEntity(ent)
New code:
let ent = new Entity()
ent.addComponent(new BoxShape())
ent.addComponent(new Billboard())
engine.addEntity(ent)
Read more about this in the documentation.
Textures
To add a texture, you now have to create a Texture
component, and add this component to a Material
or BasicMaterial
component. The Texture
component exposes a few new parameters you can set for evern greater control over how things look.
The Material
and BasicMaterial
components no longer support paths to image files on any of their fields, instead these must point to Texture
components.
Old code:
const woodMaterial = new Material()
woodMaterial.albedoTexture = "materials/wood.png"
let ent = new Entity()
ent.add(new PlaneShape())
ent.add(woodMaterial)
engine.addEntity(ent)
New code:
const woodTexture = new Texture("materials/wood.png")
const woodMaterial = new Material()
woodMaterial.albedoTexture = woodTexture
let ent = new Entity()
ent.addComponent(new PlaneShape())
ent.addComponent(woodMaterial)
engine.addEntity(ent)
Read more about this in the documentation.
Click events
We’ve renamed the BUTTON_A_DOWN
and BUTTON_A_UP
events to simply BUTTON_DOWN
and BUTTON_UP
. Information about which button was pressed will now be passed as one of the fields inside the event.
Old code:
input.subscribe("BUTTON_A_DOWN", e => {
log("button Down", e)
})
New code:
input.subscribe("BUTTON_DOWN", e => {
log("button Down", e)
})
Optional click enhancement
Version 6.0 includes a new OnPointerDown
component, which is often a better option than OnClick
. OnClick
is only triggered when both the pressing and releasing of the button occurs while pointing at the same entity. OnPointerDown
is triggered with just the pressing of the button.
The OnClick
component will remain supported, but it’s the least versatile option. The event handled by the OnPointerDown
component exposes more data, including ray distance, position of the player, and the id of the specific mesh in the 3D model that was clicked.
Old code:
ent.add(
new OnClick(e => {
log("event data: " + e)
})
)
New recommended code:
ent.addComponent(
new OnPointerDown(e => {
log("event data: " + e)
})
)
Other
Removing entities
The engine.removeEntity()
used to have a second optional argument, a boolean that determined if child entities should also be removed.
On 6.0 we determined that the default behavior should be to remove all child entities every time.
Old code:
engine.removeEntity(cube, true)
New recommended code:
engine.removeEntity(cube)
Tip: If you don’t want to remove children, you can make them children of another entity before you remove the parent.
Text component alignment
The TextShape
component used to have two properties named hAlign
and vAlign
. These have been renamed to hTextAlign
and vTextAlign
.
Old code:
let text = new TextShape("Hello world!")
text.hAlign = 'center'
New recommended code:
let text = new TextShape("Hello world!")
text.hTextAlign = 'center'
Entity type renamed
If your scene has function definitions that take entities as inputs, the Entity
type now needs to be renamed to IEntity
.
Old code:
export function myFunction(
myNumber: number,
myEntity: Entity
) {
log("Entity: " , myEntity)
}
New recommended code:
export function myFunction(
myNumber: number,
myEntity: IEntity
) {
log("Entity: " , myEntity)
}