| name | sdk-component-implementation |
| description | End-to-end SDK7 component implementation from protocol to C# systems. Use when implementing new SDK components (PB* types, protobuf, CRDT), modifying SDK component systems, or registering in ComponentsContainer. |
| user-invocable | false |
SDK Component Implementation
Sources
docs/how-to-implement-new-sdk-components.md -- Step-by-step implementation guide
docs/scene-runtime.md -- SDK7 scene execution and CRDT bridge
End-to-End Workflow
Step 1: Protocol Definition
Create protobuf definition in the protocol repository with a unique component ID:
12xx -- Main components
14xx -- Experimental components
16xx -- Protocol Squad components
Step 2: TypeScript Code Generation
In js-sdk-toolchain, generate serialization code and optional helper functions.
Step 3: C# Code Generation + Unity Implementation
In unity-explorer:
- Run protocol update:
npm install @dcl/protocol@experimental && npm run build-protocol
- Node/npm only —
build-protocol runs the protoc-gen-bitwise plugin, a dependency-free Node script bundled in @dcl/protocol (no Python or extra packages required).
- Add partial class to
IDirtyMarker.cs
- Register in
ComponentsContainer.cs using SDKComponentBuilder<T>
- Create feature folder under
Explorer/Assets/DCL/SDKComponents/<Feature>/
- Create plugin at
Explorer/Assets/DCL/SDKComponents/<Feature>/Systems/<Feature>Plugin.cs
- Instantiate plugin in
StaticContainer.cs (in the ECSWorldPlugins array)
- Implement systems (lifecycle, properties, cleanup)
Step 4: Test Scene
Create example test scene in sdk7-test-scenes.
SDK getOrNull vs getMutableOrNull (CRITICAL): In scene-side TypeScript, getMutableOrNull marks the component dirty in the CRDT system, which triggers IsDirty = true on the Explorer side and causes a full property re-apply. Only use getMutableOrNull when you are about to write to the component. For read-only access (e.g., reading values to display in a UI panel), always use getOrNull. Calling getMutableOrNull every frame in a UI render function will make the component permanently dirty, causing unintended side effects like re-triggering emission bursts, restarting animations, or redundant material/texture reloads.
PR Merge Order
Protocol first -> update both js-sdk-toolchain and unity-explorer -> merge in any order.
Registration Steps
1. IDirtyMarker Partial Class
File: Explorer/Assets/DCL/Infrastructure/ProtobufPartialClasses/IDirtyMarker.cs
public partial class PBMyComponent : IDirtyMarker
{
public bool IsDirty { get; set; }
}
2. ComponentsContainer Registration
File: Explorer/Assets/DCL/Infrastructure/Global/ComponentsContainer.cs
.Add(SDKComponentBuilder<PBMyComponent>.Create(ComponentID.MY_COMPONENT).AsProtobufComponent())
.Add(SDKComponentBuilder<PBMyResult>.Create(ComponentID.MY_RESULT).AsProtobufResult())
3. StaticContainer Plugin Instantiation
File: Explorer/Assets/DCL/Infrastructure/Global/StaticContainer.cs
Add the plugin to the ECSWorldPlugins array (~line 274):
new MyFeaturePlugin(poolsRegistry, assetsProvisioner),
Feature Folder Structure
Real example from Explorer/Assets/DCL/SDKComponents/LightSource/:
Assets/DCL/SDKComponents/<Feature>/
+-- Components/
| +-- <Feature>Component.cs // Internal ECS struct component
+-- Prefab/ // Optional: Unity prefabs for pooled objects
+-- Systems/
| +-- DCL.<Feature>.Systems.asmref // { "reference": "DCL.Plugins" }
| +-- <Feature>Plugin.cs // Plugin lives WITH the systems it injects
| +-- <Feature>LifecycleSystem.cs // Create/destroy internal components
| +-- <Feature>ApplyPropertiesSystem.cs // Apply SDK data to Unity objects
| +-- CleanUp<Feature>System.cs // Cleanup on removal/destruction
| +-- <Feature>Group.cs // Custom SystemGroup for execution ordering
+-- Tests/
| +-- EditMode/
| | +-- <Feature>SystemShould.cs
| | +-- EditMode.asmref // { "reference": "DCL.EditMode.Tests" }
Assembly notes: .asmref for DCL.Plugins goes inside Systems/. Tests use DCL.EditMode.Tests. Do not create standalone .asmdef for ECS systems. See plugin-architecture skill for full rules.
Detailed Reference
For plugin code examples, system patterns (lifecycle, apply-properties, cleanup, groups), CRDT bridge usage (IECSToCRDTWriter, LWW vs GOVS), and test patterns, see reference.md.
Implementation Checklist