Camera

The engine provides a camera system with two modes: third-person orbit (default) and first-person. Toggle between them with TAB.

Setup

Attach a Camera component to any entity with a Transform:

world.AddComponent(player, new Camera {
    Offset = new Vec3(0f, 0f, 3f),
    Yaw = 0f, Pitch = 0f,
    Fov = 45f,
    LookSpeed = 90f,
    MouseSensitivity = 0.15f
});

The CameraFollowSystem handles all camera logic automatically.

Player Movement Coupling

When an entity has both Camera and Movable, the InputMovementSystem uses the camera yaw to drive camera-relative movement:

  • W / S move forward/back along camera-facing ground direction
  • A / D strafe left/right relative to camera
  • The player visual Transform.Rotation.Y is updated to face the movement direction

This gives third-person style controls where movement direction follows camera orientation.

Camera Modes

Third-Person (CameraMode.ThirdPerson, default)

The camera orbits around the entity at a configurable distance. Scroll wheel zooms in and out, clamped between MinDistance and MaxDistance.

First-Person (CameraMode.FirstPerson)

The camera is placed at the entity's position plus EyeHeight on the Y axis. It looks in the direction defined by Yaw and Pitch. Scroll wheel zoom is not used in this mode.

Switching Modes

Press TAB to toggle between modes. The toggle is edge-detected (fires once per press).

Controls

InputAction
Q / EOrbit camera left / right (yaw)
R / FOrbit camera up / down (pitch)
Mouse movement (when locked)Free-look orbit
Scroll wheelZoom in / out (third-person only)
TABToggle first-person / third-person
ESCToggle cursor lock on/off

How It Works

  1. Orbit distance is calculated from the length of the Offset vector
  2. Yaw and Pitch define the spherical coordinates around the entity
  3. In third-person mode, the camera position is computed as: entity position + spherical offset
  4. In first-person mode, the camera is at entity position + EyeHeight, looking along the yaw/pitch direction
  5. Pitch is clamped to [-89, 89] degrees to prevent gimbal lock
  6. The view matrix is set via NativeBridge.SetCamera()

Mouse Look

When the cursor is locked (press ESC to toggle):

  • Mouse movement updates Yaw and Pitch based on MouseSensitivity
  • The cursor is hidden and captured for raw input
  • Press ESC again to release the cursor

When the cursor is free, only keyboard orbit (Q/E/R/F) works.

Default Camera

If no Camera component is attached to any entity, the renderer uses its built-in default:

  • Eye position: (0, 0, 3)
  • Look-at target: (0, 0, 0)
  • Up vector: (0, 1, 0)
  • FOV: 45 degrees

Free Camera (Debug)

The engine includes a debug fly camera for inspecting the scene freely. It is only available when GameConstants.Debug is true.

Activating

InputAction
0Activate free camera
1Deactivate and return to player camera

When the free camera is active, player input (InputMovementSystem) is disabled — WASD controls only the free camera.

Note

FreeCameraSystem is optional. Register world.AddSystem(Systems.FreeCameraSystem); before CameraFollowSystem to enable it.

Controls

InputAction
WASDFly forward / back / strafe left / right
Q / EFly down / up
Mouse (when locked)Look around (yaw/pitch)
ESCToggle cursor lock

Configuration

Sensitivity and speed are configured in GameConstants:

GameConstants.FreeCamSensitivity = 0.15f;  // degrees per pixel
GameConstants.FreeCamSpeed = 5f;           // units per second

FOV is set in FreeCameraState.Fov (default 45).

How It Works

  1. FreeCameraSystem runs before CameraFollowSystem
  2. When active, it overrides the camera via NativeBridge.SetCamera() directly
  3. CameraFollowSystem returns early when the free camera is active
  4. InputMovementSystem returns early when the free camera is active
  5. Pressing 1 deactivates the free camera and resets entity camera mouse state to avoid delta jumps

State

Free camera state is stored in FreeCameraState (static class, not an ECS component):

FieldTypeDefaultDescription
IsActiveboolfalseWhether the free camera is currently active
PositionVec3(0, 2, 5)World-space position
Yawfloat0Horizontal look angle (degrees); 0 = facing -Z
Pitchfloat0Vertical look angle (degrees), clamped [-89, 89]
Fovfloat45Vertical field of view (degrees)

Camera Properties

FieldTypeDefaultDescription
OffsetVec3(0, 0, 3)Offset vector; length = orbit distance
Yawfloat0Horizontal orbit angle (degrees)
Pitchfloat0Vertical orbit angle (degrees), clamped [-89, 89]
Fovfloat45Vertical field of view (degrees)
LookSpeedfloat90Degrees/second for keyboard orbit
MouseSensitivityfloat0.15Degrees/pixel for mouse look
ModeCameraModeThirdPersonThirdPerson (orbit) or FirstPerson
EyeHeightfloat0.8Eye height offset for first-person mode
MinDistancefloat1Minimum zoom distance (third-person)
MaxDistancefloat20Maximum zoom distance (third-person)
ZoomSpeedfloat2Scroll wheel zoom sensitivity