Skip to content

Gameplay & Controls

Sektor's gameplay layer is built from three pieces: Input Actions (the durable binding contract), the Character Controller (a production third-person mover), and the gameplay Camera. All three are ordinary components on the same deterministic fixed tick as everything else.

Input Actions

Projects store named actions instead of hard-coded keys. Gameplay reads actions, never raw keys, so rebinding never touches logic. Each action is a Button, 1D axis, or 2D axis with any number of bindings across Keyboard/, Mouse/, and Gamepad/ control paths, plus per-binding scale, dead zone, and response curve.

Field Notes
name / displayName Stable identifier and creator-facing label
valueType button, axis_1d, or axis_2d
bindings[].control For example Keyboard/W, Mouse/DeltaX, Gamepad/LeftStickX
bindings[].component Which axis component the binding feeds (0 or 1)
bindings[].scale Signed multiplier, so A and D become -1 and +1 on one axis

A classic WASD + jump + sprint + crouch setup, exactly as the engine accepts it:

{"op":"project.input_actions.set","actions":[
  {"name":"Move","valueType":"axis_2d","bindings":[
    {"control":"Keyboard/A","component":0,"scale":-1},
    {"control":"Keyboard/D","component":0,"scale":1},
    {"control":"Keyboard/S","component":1,"scale":-1},
    {"control":"Keyboard/W","component":1,"scale":1}]},
  {"name":"Jump","valueType":"button","bindings":[{"control":"Keyboard/SPACE","component":0,"scale":1}]},
  {"name":"Sprint","valueType":"button","bindings":[{"control":"Keyboard/SHIFT","component":0,"scale":1}]},
  {"name":"Crouch","valueType":"button","bindings":[
    {"control":"Keyboard/CTRL","component":0,"scale":1},
    {"control":"Gamepad/B","component":0,"scale":1}]}]}

Event Sheets consume input.action_down, input.action_pressed, and input.action_released; runtime snapshots expose each action's value plus down / pressed / released at fixed-tick boundaries. Keyboard, raw relative mouse, and XInput-compatible gamepads all flow through the same queue in Studio Play and the standalone Player.

Pointer policy

Every genre needs different mouse ownership. Projects choose a default policy, and gameplay can switch it live with the input.pointer_mode.set Event action:

  • free keeps the cursor visible (strategy, point-and-click). Normalized Mouse/PositionX/Y controls stay published.
  • capture_on_click grabs the mouse when the player clicks the world (shooters, third person).
  • capture_on_focus grabs it as soon as the window is active.

Escape always releases capture, and focus loss cleans up stuck inputs automatically.

Character Controller

A capsule character driven by Jolt's character system: real collision, grounding, slopes, stairs, moving-ground velocity, air control, and pushing dynamic bodies. It consumes named actions from the table above.

Field Meaning
moveAction, jumpAction, sprintAction, crouchAction, lookAction Names of the Input Actions to consume
walkSpeed, sprintSpeed Ground speeds in units per second
acceleration How quickly velocity approaches the target
airControl 0 to 1 steering authority while airborne
jumpSpeed Initial vertical velocity
maximumSlopeDegrees, stepHeight What counts as walkable and climbable
crouchMode hold or toggle
crouchedHeight Capsule height while crouched
crouchSpeedMultiplier Speed scale while crouched
cameraRelativeMovement Move relative to the camera instead of world axes
orientToMovement Rotate the character to face travel direction
characterMassKilograms Mass used when pushing dynamic bodies

Crouch is obstruction safe. If the player releases crouch under a low ceiling, the controller keeps the smaller collision shape until there is clearance to stand, and telemetry exposes both the requested and the actual stance. No half-standing clipping, ever.

The gameplay Camera

The third-person camera orbits with the lookAction, follows at the authored distance and height, and is obstruction safe: a mask-aware sphere sweep pulls the camera in front of walls immediately and returns it smoothly along the authored path.

Field Notes
driveGameplayCamera Make this character own the Play camera
cameraDistance, cameraHeight Authored orbit position
crouchedCameraHeight, crouchCameraTransitionSpeed Camera drop while crouched, and how fast it blends
cameraCollisionEnabled, cameraCollisionRadius, cameraCollisionClearance The obstruction sweep
cameraReturnSpeed How quickly the camera relaxes back after an obstruction
lookSensitivityDegreesPerSecond, maximumPitchDegrees Orbit feel and limits

Recipe: a playable character in five minutes

  1. Import or place a character model (a capsule works for greyboxing).
  2. Add Component → Character Controller. Point it at your Move, Jump, Sprint, and Crouch actions.
  3. Enable driveGameplayCamera so Play mode uses its third-person camera.
  4. Press Play. Walk, sprint, jump, then crouch under something low and release crouch: you stay small until there is room to stand.
  5. Open Event Sheets and add: trigger input.action_pressed "Jump", action audio.play on an effort grunt. Playtest again.

Automate it

{"op":"component.add","id":12,"type":"character_controller"}
{"op":"component.character_controller.set","id":12,"moveAction":"Move","jumpAction":"Jump",
 "sprintAction":"Sprint","crouchAction":"Crouch","crouchMode":"hold","walkSpeed":5,"sprintSpeed":8,
 "crouchedHeight":1.1,"crouchSpeedMultiplier":0.5,"acceleration":30,"airControl":0.35,"jumpSpeed":6,
 "maximumSlopeDegrees":50,"stepHeight":0.4,"orientToMovement":true,
 "crouchedCameraHeight":1.45,"crouchCameraTransitionSpeed":8}
{"op":"runtime.play"}
{"op":"runtime.input.key.set","key":"W","down":true}

runtime.physics.characters telemetry reports grounding, velocity, the object being stood on, and requested versus actual crouch, so an AI playtester verifies feel from engine state rather than eyeballing pixels.