Skip to content

How to implement new SDK Components

Pravus edited this page Dec 5, 2025 · 8 revisions

How to implement new SDK7 components

This is the high-level steps that must be followed:

  1. Create the protobuf definition in Decentraland's SDK protocol
  2. Generate the new protobuf TypeScript code in the js-sdk-toolchain (serialization test + (optional) sdk helpers)
  3. Generate the new protobuf C# code in unity-explorer + implement the systems that handle the functionalities, cleanup, etc. for the component
  4. (Ideally) Create an example test-scene to show how the component is used from the SDK side

IMPORTANT This is the order in which PRs must be merged:

  1. Merge Protocol repo PR (if the change was on main, then experimental must sync the new changes before step 2)
  2. Update both js-sdk-toolchain repo PR and unity-explorer repo PR to use the updated @dcl/protocol@experimental package
  3. Merge js-sdk-toolchain and unity-explorer in any order

1. Create the protobuf definition in Decentraland's SDK protocol

  1. Create the protobuf definition inside https://github.com/decentraland/protocol/tree/main/proto/decentraland/sdk/components
  2. Create a PR with the new changes

NOTE: After creating the PR, a GitHub Bot will comment with the package link to test the PR. You can use that link for testing in the following steps

Things to take into account

  • We are using proto 3, so all the definition of the proto must compile with their syntax
  • Be VERY mindful of the fields and types you create in the Protobuf Message, due to retro-compatibility standards we can never rename or modify any field of an already released Protobuf message (AKA if you are still working on your PRs then you can keep changing stuff, although you will be forced to change the other 2 repo PRs as well fo course), as that will break scenes that are already deployed and create conflicts in the SDK and Explorer... if at some point we really need to "update" an already released component field, we should create a new field and somehow flag the old one as deprecated...
  • We have some common types that cannot be recreated
  • The proto should have the basic definition
  • You must add the following code to enumerate the component with a unique ID
import "common/id.proto";
option (ecs_component_id) = 1100;

NOTE: With the repo cloned locally you can run make list-components-ids and make check-component-id ID=xxx to make sure your component is using a unique id.

Example of .proto:

syntax = "proto3";

import "common/id.proto";
option (ecs_component_id) = 1020;

message PBAudioSource {  
  optional bool playing = 1;
  optional float volume = 2; // default=1.0f
  optional bool loop = 3;
  optional float pitch = 4; // default=1.0f
  string audio_clip_url = 5;
}

2. Generate the new protobuf TypeScript code in the js-sdk-toolchain

Clone the sdk repo: https://github.com/decentraland/js-sdk-toolchain

Run the following command at the root of the js-sdk-toolchain project (use @experimental instead if you are working on an experimental feature):

npm install @dcl/protocol@next

Or the command generated by the GitHub Bot in your @dcl/protocol PR (this must be temporal for testing the PRs).

Then run the following commands at the root of the js-sdk-toolchain project:

make install
make build

And push the generated code to your branch.

For the branch PR to be approved and functional you will also need to:

After that is done, the GitHub Bot comment in the PR will expose a test package so that you install that in your test scene and be able to use the new component from the SDK in the scene (see this wiki page on setting up a local scene and running it)

3. Generate the new protobuf C# code in unity-explorer

To generate the C# code from the protobuf files that come from the protocol, go to the scripts path in the root of the unity-explorer repository. And execute the following commands:

npm install
npm run build-protocol

To upgrade to the latest version of the @dcl/protocol, we should update using

npm install @dcl/protocol@experimental
npm run build-protocol

NOTE: unity-explorer needs to always use the @experimental protocol package to support all the experimental features, otherwise the Unity project won't even compile due to missing component files, etc.

To test a PR, we can use a URL generated by the GitHub Bot in the @dcl/protocol PR: Example:

npm install "https://sdk-team-cdn.decentraland.org/@dcl/protocol/branch//dcl-protocol-1.0.0-3143233696.commit-45f1290.tgz"
npm run build-protocol

IMPORTANT: After merging a @dcl/protocol PR, we must make unity-explorer point to the updated @dcl/protocol@experimental package (and NOT the PR test package) before merging the unity-explorer PR.

  • If the protocol update happened at main then the experimental branch must sync those new changes first, and then update the unity-explorer PR with the latest @experimental package.
  • If the protocol update happened at experimental then the unity-explorer PR can just use the updated @experimental package.

Implement the new Component functionalities

After the C# code for the protobuf component was generated, one or more systems have to be implemented to handle its functionality, following the Arch ECS architecture.

  • Add the partial class corresponding to the new PB component at IDirtyMarker
  • Register the component at the ComponentsContainer, otherwise no system will recognize the component on the ECS entities

NOTE: You'll see that some special components registered as "result components". Those are some components designed mainly to be PUT by the Explorer and only READ by the scene (e.g. input result component, raycast result component).

As a general guideline this must be implemented:

  • Relevant functionalities for the new component
    • Custom non-sdk struct components (can be empty) are normally used to change the state of the entity
    • If IsDirty needs to be relied upon, for the case of the scene modifying the component values in runtime and reacting to that: then the IsDirty reset handling can either be manual in your systems OR by injecting ResetDirtyFlagSystem<PBYourComponent>.InjectToWorld(ref builder) in your Plugin.
  • Cleanup of the component
    • SDK component removal
    • Scene unloading (IFinalizeWorldSystem implementation)

4. Create SDK example test-scene

This step is important because it allows creators (like the Content Team itself) to easily test the new component and know how it should be used, when the official documentation may still be pending.

  1. Clone the sdk7-test-scenes repo
  2. Create your test scene base
    • Duplicate one of the existent test scenes that exist in /scenes
    • Change the new folder name to your new test scene coordinates AND name (same format as the rest)
    • Update the README.md file
    • Update the package.json file -> "name" property
    • Update the scene.json file -> "name" property + "title" property + "base" and "parcels" coordinate properties
  3. Go to the root of the repo and run npm i and then npm run check-parcels to confirm there is no coordinates conflict between your new test scene and a previously existent one (that also updates the dcl-workspace.json file)
  4. Return to the root of your test scene and install an SDK version that contains the new component, for example if you are still working on an SDK branch with the component, the package is the one exposed in the js-sdl-toolchain PR, like npm install "https://sdk-team-cdn.decentraland.org/@dcl/js-sdk-toolchain/branch/feat/trigger-area-components/dcl-sdk-7.10.1-17412673762.commit-72cc7b1.tgz"
    • After that, your IDE should recognize the new component when imported from '@dcl/sdk/ecs' and you should be able to use it in your code without compilation errors
  5. run your scene to confirm there are no compilation errors (npm run start -- --explorer-alpha)
  6. Code your test scene making use of the new component (index.ts and whatever extra scripts you need)
  7. Make sure to remove unneeded files like /models, etc. if your scene doesn't use them (/images/scene-thumbnail.png must be kept)
  8. create a branch in the test scenes repo and push your new scene to create the corresponding PR in that repo, you are responsible for merging it

Clone this wiki locally