Develop

SpatialFeatures - ECS modules

Updated: Mar 4, 2026

Overview

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

Add features to your app

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.

Register systems

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:
  • onCreate
  • onSceneReady
  • onStart
  • onResume
  • onPauseActivity
    • 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().
  • onDestroy
  • onVRReady
  • onVRPause
Here is an example:
// Example init code
override fun onSceneReady() {
  Entity.create(listOf(MyComponent()))
  // Other initialization code here
  ...
}