World
World is a level/scene container inside a Game. It groups Actors, sets up a default camera, and optionally enables physics. Toggle worlds on/off with the active prop.
A Game can have multiple Worlds — only the active one is visible and receives rendering.
import { World } from "@carverjs/core/components";Quick Start #
import { Game, World, Actor } from "@carverjs/core/components";
function App() {
return (
<Game>
<World>
<Actor type="primitive" shape="box" color="red" position={[0, 1, 0]} />
</World>
</Game>
);
}Props Reference #
| Prop | Type | Default | Description |
|---|---|---|---|
active | boolean | true | Whether this world is visible. Set to false to hide it. |
physics | WorldPhysicsConfig | — | Enable Rapier physics. Requires @react-three/rapier. |
cameraProps2D | CameraProps2D | — | Overrides for the default OrthographicCamera (2D mode) |
cameraProps3D | CameraProps3D | — | Overrides for the default PerspectiveCamera (3D mode) |
orbitControlsProps | OrbitControlsProps | — | Overrides for the default OrbitControls (3D mode) |
children | ReactNode | — | Scene content (Actors, Camera, etc.) |
Physics #
Pass a physics prop to enable Rapier-based physics for all Actors in the World.
Install #
pnpm add @react-three/rapier@react-three/rapier is an optional peer dependency — Rapier is lazy-loaded at runtime. If it's not installed and you pass a physics prop, a console warning is logged and children render without physics.
WorldPhysicsConfig #
| Field | Type | Default | Description |
|---|---|---|---|
gravity | [number, number, number] | [0, -9.81, 0] | Gravity vector |
timestep | number | "vary" | 1/60 | Physics timestep. "vary" uses variable timestep. |
interpolation | boolean | true | Smooth rendering between physics steps |
debug | boolean | false | Show wireframe collider outlines |
Basic physics #
<Game>
<World physics={{ gravity: [0, -9.81, 0] }}>
<Actor type="primitive" shape="box" color="red" position={[0, 5, 0]}
physics={{ bodyType: "dynamic" }}
/>
<Actor type="primitive" shape="plane" color="#eee" size={20}
rotation={[-Math.PI / 2, 0, 0]}
physics={{ bodyType: "fixed" }}
/>
</World>
</Game>2D physics #
In 2D mode, Z translation and X/Y rotation are auto-locked per Actor.
<Game mode="2d">
<World physics={{ gravity: [0, -9.81, 0] }}>
<Actor type="sprite" src="/player.png" position={[0, 5, 0]}
physics={{ bodyType: "dynamic" }}
/>
</World>
</Game>Debug mode #
<World physics={{ gravity: [0, -9.81, 0], debug: true }}>
{/* wireframe colliders visible */}
</World>Default Camera #
World provides a default camera based on the mode set on the parent Game:
| Property | 3D Mode | 2D Mode |
|---|---|---|
| Type | PerspectiveCamera | OrthographicCamera |
| Position | [0, 5, 10] | [0, 0, 100] |
| FOV / Zoom | 75 | 50 |
| Near / Far | 0.1 / 1000 | 0.1 / 1000 |
| Orbit Controls | Enabled | Disabled |
Override defaults #
<World cameraProps3D={{ position: [0, 10, 20], fov: 60 }}>
{/* scene */}
</World>Custom Camera #
Drop a <Camera> inside World to replace the default camera and controls:
<World>
<Camera type="perspective" controls="orbit" />
<Actor type="primitive" shape="box" color="red" />
</World>When a <Camera> is detected, the default camera and orbit controls are skipped.
Multiple Worlds #
Use the active prop to switch between worlds:
function App() {
const [level, setLevel] = useState("forest");
return (
<Game>
<World active={level === "forest"}>
<ForestScene onComplete={() => setLevel("dungeon")} />
</World>
<World active={level === "dungeon"}>
<DungeonScene />
</World>
</Game>
);
}Inactive worlds are hidden via visible={false} on the underlying Three.js group. The Canvas and WebGL context are not destroyed during world switches.
Type Definitions #
See Types for WorldPhysicsConfig, CameraProps2D, CameraProps3D, and OrbitControlsProps.