Cameras and follow modes
Follow a character or a vehicle with first-person and third-person modes, set eye height, and switch the active camera at runtime.
Third-person cameras
A camera behind the character uses a negative local Z offset, for example {x=0, y=0.4, z=-1.5}, and looks back toward the character. Built-in follow camera modes expose their live smoothed transform through the normal game object API.
Built-in camera control modes
A camera object's controlMode is free (default, no automatic following), first_person, or third_person. Set it from the camera's inspector, or through the MCP scene-object tools, instead of hand-rolling the offset every frame.
Both following modes aim at the camera's targetCharacterId. If that does not resolve to an object in the scene, the camera silently falls back to free-camera behaviour parked at its authored position — which is the first thing to check if a follow camera seems inert.
The target does not have to be a character. The field name is historical: it accepts any object with a transform, including wheeledVehicle and trackedVehicle objects. A chase camera for a car or a tank needs no hand-written script — set controlMode to third_person and point targetCharacterId at the vehicle. The camera's inspector lists characters and vehicles together in its Follow Target dropdown.
first_person
The camera snaps to the target character's position every frame, with no smoothing. followDistance and followHeight are ignored in this mode; they apply only to third_person.
Eye height. Set eyeHeight — the camera's own field, default 1.6 — to the eye height you want. It is measured from the follow target's origin, which for a character is its feet, so it is the eye height directly: eyeHeight = 1.65 puts the eye at 1.65m on a 2m character. There is no arithmetic to do. The editor exposes it as Eye Height on a first-person camera's inspector.
followOffset still applies, and it is added on top of eyeHeight rather than used in place of it — so leave followOffset.y at 0 unless you want a further nudge. Before eyeHeight existed the 1.6 was hardcoded and invisible, and the way to get a 1.65m eye was followOffset.y = 0.05; that still works and still means the same thing, but eyeHeight is what someone reading the scene later will understand. The offset is also rotated by the character's rotation before being added, so a non-zero x or z orbits with the character rather than staying world-fixed.
Because a character's origin is at its feet, eyeHeight is measured from the floor the character is standing on, not from its waist. See Characters.
Which way it looks. With no look input applied, the camera renders along its target's forward axis — local +Z, the direction a character or a vehicle faces. The facing you authored on the character is therefore what the player sees at spawn, and turning the character turns the view with it. getForward() on the camera reports that same rendered direction, so it agrees with what is on screen and can be used directly as a movement or aiming basis.
This changed on 9 September 2026
Three.js cameras render down their local -Z while everything else in Airogel faces +Z, and first_person used to inherit the character's rotation without reconciling the two — so the view started out facing behind the character. If you compensated for that by rotating the character or the camera 180° in an existing scene, remove the compensation: the view now agrees with the character's facing on its own.
Look. The mode consumes input.lookDeltaX and input.lookDeltaY automatically — you do not need to write look handling in Lua. But it can only turn the camera if something is producing those deltas, and what produces them depends on the device: arrow keys always, the mouse only when the scene enables desktop mouse look, and touch only when mobile controls are enabled. That is the single most common reason a first-person camera positions correctly but never rotates. Player input and touch controls has the full list.
Desktop mouse look
Enable it per scene: Scene Settings > Player input controls > Desktop mouse look, or pointer_lock on the player-controls MCP payload. The player clicks the canvas to capture the mouse and presses Escape to release it. The canvas click that captures the mouse does not trigger primary_fire; subsequent left clicks do.
It is off by default, and deliberately so. Pointer lock hides the cursor and stops DOM events reaching guiButton elements, so a scene whose UI is GUI buttons would lose every click. Enable it for a game the player aims with; leave it off for anything menu-driven.
This is settable headlessly. pointer_lock is a field on scenes_update's player_controls object, so an agent building a scene entirely through MCP can turn mouse look on without anyone opening the editor. desktop_mouse_look is accepted as an alias for the same field, since that is the name the editor and these docs use for it. See MCP tool guide.
third_person
In third_person mode the camera booms behind its target automatically using four properties:
followDistance(default 5) andfollowHeight(default 2) set the boom's base offset behind and above the target.followOffsetadds a local{x, y, z}nudge on top of that, for example to shift the camera to one side.followSmoothingis a lerp time constant in seconds, not a 0-1 intensity:0tracks instantly, larger values lag more. Values much past 2s read as a stuck camera rather than a smooth one, so keep it small.
The defaults are sized for a roughly human-scale target. A car or tank is wider and faster than a character, so a vehicle chase camera usually wants a larger followDistance than 5 and a little followSmoothing so the boom does not snap on every steering input.
Attaching a script disables the control mode
The engine runs its built-in camera controller only for cameras that have no script attached. Giving a camera object a scriptId hands full control to that script and silently stops first_person and third_person from doing anything — the camera will sit wherever the script leaves it. This is deliberate, so a script can take over completely, but it is all-or-nothing: you cannot keep the built-in follow behaviour and add a little scripting on top. Put the script on another object if you only need to read or nudge the camera.
Switching the active camera at runtime
A camera authored with isActive becomes the camera the scene renders through when it runs — in preview, in a published game, and when you press Play in the editor. Stopping the run in the editor hands the viewport back to the editor camera. If you were already previewing a specific camera from the outliner, running the scene leaves you on that one.
scene.setActiveCamera(id) changes which camera the running scene renders through, and scene.getActiveCamera() returns the live one's object API. Both are available to every object script, not just scene scripts. See Scene scripts and storage.
setVisible() on a camera does not affect which camera renders — it is a rendering-visibility toggle and is not tied to a camera's active state.