SAPIEN component lifecycle: enabled, attached and in a scene

SAPIEN calls a component’s scene-entry hook when three conditions become true together: the component is enabled, it is attached to an entity, and that entity belongs to a scene. Creating the component or attaching it to an off-scene entity establishes only part of that relationship.

The Component Lifecycle documentation defines the entry hook as on_add_to_scene() and the removal hook as on_remove_from_scene(). The first runs when the three conditions become true; the second runs when they cease to be true together. The component’s implementations should register and unregister it with the appropriate system.

This article follows the official lifecycle and architecture pages checked on October 16, 2026. No component was created or simulation stepped for the explanation.

An entity supplies a pose; components supply its functions

The Scene, Entity, Component, and System overview describes a scene as holding entities and systems. An entity has a position, orientation and attached components. Its components determine whether it participates in physics, has a rendered appearance or acts as a camera.

The overview’s concrete examples give those roles substance. A PhysxRigidDynamicComponent connects an entity to rigid-body simulation. A render-body component gives it an appearance, while a RenderCameraComponent makes an entity a camera. PhysxSystem updates physics-related components, and RenderSystem manages render bodies and cameras.

These responsibilities explain why an allocated component needs a system connection. A Python reference to an entity identifies an object in the application; registration makes the relevant system aware of the component it should process. The documentation uses Entity, Component and System terminology while explicitly distinguishing SAPIEN’s design from an ECS architecture.

The last missing condition triggers entry

The lifecycle page expresses the entry condition as this conjunction:

component.enabled
and component.entity is not None
and component.entity.scene is not None

The order in which those conditions are established can vary. The page describes three ways to complete them:

Final change Conditions already established Entry event
Add an entity to a scene Its component is attached and enabled on_add_to_scene() runs
Attach a component to an entity already in a scene The component is enabled on_add_to_scene() runs
Enable a component It is already attached to an entity in a scene on_add_to_scene() runs

In each case, the final change completes the same relationship. That is more precise than associating registration only with an add_entity call. An entity can already be in the scene when a newly attached or newly enabled component becomes eligible to enter its system.

Disabling and re-enabling changes participation

Consider an illustrative sequence in which a component starts enabled. It is first unattached, then attached to an entity outside the scene, and finally brought into the scene with that entity.

Step Enabled? Attached to an entity? Entity in scene? Lifecycle effect
Create the example component Yes, by assumption No No Entry condition incomplete
Attach it to an off-scene entity Yes Yes No Entry condition still incomplete
Add the entity to the scene Yes Yes Yes Entry hook runs; its implementation registers with the system
Disable the component No Yes Yes Removal hook runs; its implementation unregisters it
Enable it again Yes Yes Yes Entry hook runs again to register it

The table explicitly assumes the initial enabled value; it does not infer a constructor default. More importantly, it shows that membership can change while the entity remains in the scene. Disabling the component breaks the conjunction even though the entity attachment and scene membership still exist.

Removing the parent entity from the scene is another documented removal event. In that case, the scene condition becomes false. The hook is tied to losing the complete relationship, not only to deleting the component object from application code.

Registration determines which system processes the component

For the dynamic rigid-body example, the architecture overview describes querying the scene for its PhysxSystem and registering a PhysX rigid dynamic actor in that system’s simulation scene. When the physics system steps, it synchronizes updated poses to the component, which updates the SAPIEN entity’s pose.

This gives the entry hook a concrete purpose: it establishes the connection through which a system processes the component. The removal hook performs the corresponding unregistration. For custom behavior, the lifecycle page assigns those responsibilities to the hook implementations; having the entry condition become true is the occasion to perform that work.

The two official pages use slightly different names in their descriptions. The architecture overview says add_to_scene and remove_from_scene, while the dedicated lifecycle page names on_add_to_scene() and on_remove_from_scene(). This explanation uses the latter hook names from the lifecycle specification and does not turn the overview’s shortened names into a runnable custom-component implementation.

When an object exists in application code but its expected physics or rendering behavior is absent, the three conditions localize the question. Is the component enabled, is it attached, and is its entity in the scene? Once all three hold, the relevant hook and system registration explain how the component becomes part of simulation or rendering.

For a related testing question, the Gazebo TestFixture explanation describes observing a named component condition at a chosen update phase. SAPIEN’s lifecycle supplies its own concrete condition to examine: whether the three membership requirements hold and the corresponding system registration has occurred.