SpatialFeatures - ECS modules
Updated: Mar 4, 2026
A SpatialFeature bundles components, systems, and lifecycle events into a reusable module. Add a feature to your app with a few lines of code, and the SDK runs it at the right time.
For example, the VRFeature provides:
- Components: Hand tracking components, controller input components
- Systems: Input processing systems, interaction systems
- Lifecycle events: VR session management and device initialization
Similarly, the PhysicsFeature includes:
- Components:
Physics for defining physical properties (shape, density, restitution, friction, state) - Systems: Physics simulation system that handles collision detection and response
- Lifecycle events: Physics world initialization and cleanup
The registerFeatures function defines the features you want to include in your app. It is only called and used at startup. Any modifications to the list after the initial startup will not change the registered features.
Here is an example of registering multiple features in an app:
import com.meta.spatial.core.SpatialFeature
import com.meta.spatial.physics.PhysicsFeature
import com.meta.spatial.vr.VRFeature
class MyActivity : AppSystemActivity() {
override fun registerFeatures(): List<SpatialFeature> {
return listOf(
PhysicsFeature(spatial),
VRFeature(this))
}
...
}
Using this code, the example Spatial SDK app will have Physics capabilities and default VR capabilities.
When to make a SpatialFeature
You should create a SpatialFeature if you plan to use a specific feature in multiple apps or want to use it as a code organization method. Features are ideal for:
- Building complete functional modules (like physics, networking, or input handling)
- You want to share functionality across multiple projects
- You need bundled components, systems, and lifecycle management
- Working with complex feature sets that require coordinated initialization
SpatialFeature capabilities
Using a SpatialFeature allows you to:
- Bundle related components and systems together
- Execute code at different lifecycle points of a Spatial SDK app
- Organize complex functionality into reusable modules
- Manage initialization and cleanup for your features
Register your feature’s components
Override the componentsToRegister function to register components required for your feature. componentsToRegister returns a list of ComponentRegistration objects.
override fun componentsToRegister(): List<ComponentRegistration> {
return listOf(
ComponentRegistration.createConfig(MyComponent1.Companion, MyComponent1.id, { MyComponent1() }),
ComponentRegistration.createConfig(MyComponent2.Companion, MyComponent2.id, { MyComponent2() }, sendRate = SendRate.LOW))
}
Define your component’s send rate
ComponentRegistration objects let you define your component’s SendRate. Use SendRate.DEFAULT for components that need updates every frame. Use SendRate.LOW for components that do not.
Use different functions to register the systems required for your feature depending on when you want your system to run.
You have three options:
earlySystemsToRegister: All systems in the list returned by this function will run first.systemsToRegister: All systems in the list returned by this function will run next.lateSystemsToRegister: All systems in the list returned by this function will run last.
If you do not know which bucket to put your system in, or if it doesn’t matter, use systemsToRegister.
override fun systemsToRegister(): List<SystemBase> {
return listOf(MySystem())
}
override fun earlySystemsToRegister(): List<SystemBase> {
return listOf(MyEarlySystem())
}
override fun lateSystemsToRegister(): List<SystemBase> {
return listOf(MyLateSystem())
}
Android and Spatial SDK lifecycle events
A SpatialFeature lets you override most Android lifecycle event functions and some Spatial SDK lifecycle events. These functions run when the matching lifecycle event occurs.
You can override these functions by using a SpatialFeature:
onCreateonSceneReadyonStartonResumeonPauseActivity- This is only called when extending
VrActivity, not VrService, as services do not utilize OnPause().
onStopActivity- This is only called when extending
VrActivity, not VrService, as services do not utilize OnStop().
onDestroyonVRReadyonVRPause
Here is an example:
// Example init code
override fun onSceneReady() {
Entity.create(listOf(MyComponent()))
// Other initialization code here
...
}