Skip to content

GameComponents in action

tutorial lesson Beginner ⏱ 12 min vgai 0.1.0

Prerequisites: Get Started (install + first look)

What you'll learn

  • Understand that the Three.js Object3D IS the entity
  • Write a GameComponent with init / update / dispose
  • Know which phase a component's update() runs in
  • Register a component and see it tick in play mode

What you'll build: A mental model of the GameComponent lifecycle, seen running in a component-rich scene.

Walkthrough — GameComponents in action · generated by site/media/lessons/foundations-components.lesson.ts (5 steps)

The whole engine rests on one idea: the Three.js Object3D is the entity, and behavior is attached to it with a GameComponent. This lesson makes that concrete — first the shape of a component, then seeing components tick live.

A GameComponent (packages/engine/src/ecs/game-component.ts) is a small class with a lifecycle:

// A minimal component: spin an object every frame.
import { GameComponent } from '@engine/ecs/game-component';
import { z } from 'zod';
export class Spin extends GameComponent {
static phase = 'gameLogic' as const; // when update() runs
static schema = z.object({ speed: z.number().default(1) }); // authored field
speed = 1;
init(ctx) { /* runs once, after the entity + physics exist */ }
update(dt, ctx) { this.object3D.rotation.y += this.speed * dt; }
dispose(ctx) { /* clean up anything you created */ }
}
  • this.object3D is the entity — there is no separate handle.
  • static phase picks which phase update() runs in (default gameLogic).
  • static schema (Zod) declares fields an author can set in the scene; they’re validated and assigned on load.
  • init / update / dispose are the lifecycle; sensor overlaps also call onTriggerEnter / onTriggerExit.

Register the class by name in the component registry, then reference it from a scene’s components — the loader validates the data through schema.parse() and attaches an instance (the ComponentManager ticks it each frame in its phase).

  1. Open a scene whose entities have GameComponents. Load examples/scenes/editor-tutorial.vscn.json.

    A component-rich scene loaded
    A scene whose entities carry components.
  2. Enter play mode — each component’s update() runs every tick. Press Play; the ComponentManager begins ticking every attached component in its phase.

    The scene running in play mode
    Components tick once play starts.
  3. Watch component-driven animation and physics. The motion you see is components mutating their object3D each frame.

    Component-driven motion in play mode
    Per-frame update() in action.
  4. Components keep ticking in their phase. Each runs in the fixed phase order — input → … → gameLogic → … → render.

  5. Stop play mode. Press Stop (or Escape) — dispose() runs and the runtime tears down.

Recap

New functionality

  • Saw a component-rich scene run
  • Read the GameComponent lifecycle

New concepts & skills

  • The Object3D IS the entity (no separate ECS)
  • update() runs each fixed tick in the component's phase
  • Static schema authors fields; the registry + ComponentManager wire and tick instances
  • State on the instance survives hot reload

Next lesson → Manual: Entities & GameComponents