Skip to content

World code 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 React component whose useFrame callback drives motion
  • Know when per-frame code runs in the loop's phase order
  • See per-frame world code tick in play mode

What you'll build: A mental model of world code, seen running in a live scene.

Walkthrough — World code 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 ordinary React — a component in your world’s TSX calling useFrame. This lesson makes that concrete — first the shape of a behaving component, then seeing it tick live.

A three world is authored as TSX (src/world.tsx — the source is the document). Anything that behaves is a component with a useFrame callback:

// A minimal behavior: spin an object every frame.
import { useRef } from 'react';
import { useFrame } from '@react-three/fiber';
import type { Mesh } from 'three';
function Spinner({ speed = 1 }: { speed?: number }) {
const ref = useRef<Mesh>(null);
useFrame((_, dt) => {
if (ref.current) ref.current.rotation.y += speed * dt;
});
return (
<mesh ref={ref}>
<boxGeometry />
<meshStandardMaterial color="tomato" />
</mesh>
);
}
  • The ref’s target is the entity — there is no separate handle. It is a THREE.Object3D, and every call on it is Three’s own API.
  • Props are the configuration — the editor’s inspector types them straight from the JSX literal; there is no schema to declare separately.
  • useFrame runs in the loop — per-frame work happens inside the engine’s fixed phase order, so physics, input, and rendering see a consistent world every tick.
  • Engine services come from the world context — input, physics, audio, deterministic RNG (packages/engine/src/world3d-react/world-context.ts). A subsystem the world did not declare is a compile error, not a runtime surprise.
  1. Open a scene whose entities carry per-frame code. Run VGAI_PROJECT=examples/first-person npm run dev — the project’s world loads by default.

    A scene with behaving entities loaded
    A world whose entities carry per-frame code.
  2. Enter play mode — every useFrame callback runs each tick. Press Play; the loop begins ticking and every mounted component’s callback fires in order.

    The scene running in play mode
    World code ticks once play starts.
  3. Watch world code drive animation and physics. The motion you see is components mutating their own objects each frame.

    Code-driven motion in play mode
    Per-frame callbacks in action.
  4. Per-frame code runs in the loop’s fixed phase order — input → … → gameLogic → … → render.

  5. Stop play mode. Press Stop (or Escape) — components unmount, cleanups run, and the runtime tears down.

Recap

New functionality

  • Watched per-frame useFrame callbacks drive motion in play mode
  • Stopped play mode and saw component cleanups tear the runtime down

New concepts & skills

  • A thing that behaves is a component calling useFrame — per-frame work runs in the fixed phase order
  • Props are configuration and hooks are state, so the world's source is the only authority

Next lesson → Worlds and roots (manual)