Skip to content

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

PropertyTypeDescription
pathstringSource URL or localasset:// path of the GLTF/GLB asset.
objectTHREE.Object3D | nullLoaded model object, populated asynchronously by the model loader. null until loaded.

API reference

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:

typescript
// 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.

typescript
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.

typescript
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.