Script
Component holding the list of scripts attached to an entity. Loaded from the saved project; the runtime-side fields (scriptInstance, scriptInstances) are non-enumerable so they never leak into save data or undo history. Authored scripts subclass Behaviour.
Managed by:
ScriptBehaviourSystem
Editor inspector

Properties
| Property | Type | Description |
|---|---|---|
entries | ScriptEntry[] | Authored script entries attached to the entity. Each entry references a class by name plus its inspector field overrides. Saved with the project. |
scriptInstance | unknown | null | First live behaviour instance after compile/load. Non-enumerable, so it does not appear in save data. null when no script is loaded. |
scriptInstances | Map<number, unknown> | Map of entityId to its compiled behaviour instance (one entry per script bound to the entity). Non-enumerable, so it does not appear in save data. |
API reference
- Class:
ScriptComponent - Source:
core/components/ScriptComponent.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 scriptComp = this.getComponent(ScriptComponent);
// Component on another entity, found by its scene name
const other = this.world.getEntityByName("Manager");
if (other) {
const scriptComp = this.world.getComponent(other.entityId, ScriptComponent);
}Call a method on another script attached to the same entity
ScriptComponent.scriptInstances maps entity IDs to their compiled behaviour instances. You can cast an instance to a known shape and call public methods on it, enabling script-to-script communication.
import { Behaviour, ScriptComponent } from "@relu-interactives/spatial-ecs";
// Assumes another script on this entity exposes a `reset()` method.
export default class ScriptBridge extends Behaviour {
protected init() {
const scriptComp = this.getComponent(ScriptComponent);
if (!scriptComp) return;
// scriptInstance is the first compiled behaviour on this entity
const other = scriptComp.scriptInstance as { reset?(): void } | null;
if (other?.reset) {
other.reset();
}
}
}Inspect script entries
Read the authored entries array to find which scripts are attached and inspect their saved field overrides.
import { Behaviour, ScriptComponent } from "@relu-interactives/spatial-ecs";
export default class ScriptInspector extends Behaviour {
protected init() {
const scriptComp = this.getComponent(ScriptComponent);
if (!scriptComp) return;
for (const entry of scriptComp.entries) {
console.log(`Script: ${entry.className}`, entry.data);
}
}
}Via ComponentInput in the inspector
You can also pick this component from the inspector using a ComponentInput field. Assign any entity in the inspector and the field resolves to the live ScriptComponent instance at runtime.
import {
Behaviour,
ScriptComponent,
type ComponentInput,
} from "@relu-interactives/spatial-ecs";
export default class Example extends Behaviour {
data = {
targetScript: {
type: "component",
value: null,
} as unknown as ComponentInput,
};
protected onUpdate() {
const scriptComp = this.data.targetScript.value as ScriptComponent | null;
if (!scriptComp) return;
// Use the live component instance.
}
}Via EntityInput in the inspector
Alternatively, pick an entity from the inspector using an EntityInput field and then read the component off that entity via world.getComponent:
import {
Behaviour,
ScriptComponent,
type EntityInput,
type WorldEntityView,
} from "@relu-interactives/spatial-ecs";
export default class Example extends Behaviour {
data = {
targetEntity: { type: "entity", value: null } as unknown as EntityInput,
};
protected onUpdate() {
const entity = this.data.targetEntity.value as WorldEntityView | null;
if (!entity) return;
const scriptComp = this.world.getComponent(
entity.entityId,
ScriptComponent,
) as ScriptComponent | null;
if (!scriptComp) return;
// Use the component on the picked entity.
}
}Runtime vs. authored data
entries is the persisted array of script definitions (class name + inspector overrides). scriptInstance and scriptInstances are non-enumerable runtime references that are never saved to snapshots. Do not store references to scriptInstance across frames — re-read from ScriptComponent each time if needed.

