Model
References a GLTF/GLB asset loaded from path. The model loading system resolves the asset asynchronously and populates ModelComponent.object once available; loading is deferred-tolerant so the entity exists before the model finishes loading.
Properties
| Property | Type | Description |
|---|---|---|
path | string | Source URL or localasset:// path of the GLTF/GLB asset. |
object | THREE.Object3D | null | Loaded model object, populated asynchronously by the model loader. null until loaded. |
API reference
- Class:
ModelComponent - Source:
core/components/Model.ts
Scripting examples
Component access patterns
Use this.getComponent(X) to access a component on the entity this script is attached to. Use this.world.getEntityByName to find another entity by name, then this.world.getComponent to read its component:
// Component on the entity this script is on
const model = this.getComponent(ModelComponent);
// Component on another entity, found by its scene name
const other = this.world.getEntityByName("Robot");
if (other) {
const model = this.world.getComponent(other.entityId, ModelComponent);
}Fade the model in after it loads
Wait for the async model load to complete, then animate opacity to 1 over one second.
import { Behaviour, ModelComponent } from "@relu-interactives/spatial-ecs";
export default class ModelFadeIn extends Behaviour {
private fadeProgress = 0;
private started = false;
protected onUpdate() {
const model = this.getComponent(ModelComponent);
if (!model?.object) return; // wait for async load to complete
if (!this.started) {
this.started = true;
// Initialise all sub-mesh materials to transparent before fading in
model.object.traverse((child: any) => {
if (child.isMesh && child.material) {
child.material.transparent = true;
child.material.opacity = 0;
}
});
}
this.fadeProgress = Math.min(1, this.fadeProgress + this.deltaTime);
model.object.traverse((child: any) => {
if (child.isMesh && child.material) {
child.material.opacity = this.fadeProgress;
}
});
}
}Toggle model visibility
Show or hide the loaded model at runtime using the Object3DRef visibility flag.
import { Behaviour, ModelComponent, Object3DRef } from "@relu-interactives/spatial-ecs";
import type { BooleanInput } from "@relu-interactives/spatial-ecs";
export default class ModelVisibility extends Behaviour {
data = {
visible: true as BooleanInput,
};
protected onUpdate() {
const model = this.getComponent(ModelComponent);
if (!model?.object) return; // still loading
const ref = this.getComponent(Object3DRef);
if (ref) ref.visibility = this.data.visible;
}
}Async loading
Always guard with model?.object before traversing or mutating sub-meshes. The object property is null until the GLTF/GLB asset finishes loading.

