Skip to content

CharacterController

A capsule-based character controller (Jolt CharacterVirtual) for player and NPC movement. Created via Scene.createCharacterController. The controller handles ground detection, stair-stepping, slope limits, and state tracking automatically.

scene.createCharacterController(height, radius, x, y, z)

Section titled “scene.createCharacterController(height, radius, x, y, z)”

Returns: CharacterController — A new controller placed at the given position.

Parameters:

  • height (Num) — Capsule standing height in metres.
  • radius (Num) — Capsule radius in metres.
  • x, y, z (Num) — Initial world position.
_controller = _scene.createCharacterController(1.8, 0.3, 0, 2, 0)

Set the velocity the controller should try to reach this frame. Call every frame from update(dt). The physics system handles ground detection and slope response; do not set a Y velocity for jumps — use jump() instead.

var speed = 5
var vx = 0
var vz = 0
if (Input.key("a")) vx = -speed
if (Input.key("d")) vx = speed
if (Input.key("w")) vz = -speed
if (Input.key("s")) vz = speed
_controller.setDesiredVelocity(vx, 0, vz)

Apply an upward impulse. Only effective when the controller is grounded (isGrounded is true).

if (Input.keyJustPressed("space") && _controller.isGrounded) {
_controller.jump()
}

running=(value) / crouching=(value) / swimming=(value)

Section titled “running=(value) / crouching=(value) / swimming=(value)”

Set locomotion flags. These switch the controller into the corresponding state for speed selection and animation.

Get or set the yaw angle (radians) the controller is facing. Used for directional movement and animation.

Returns: Num — Current CharacterState constant.

Returns: Num — Ground contact state:

ValueMeaning
0On ground (flat/walkable)
1On steep ground (too steep to walk)
2Not supported (hanging, ledge)
3In air

Returns: Booltrue when the controller is on walkable ground (groundState == 0).

Returns: Booltrue when the controller has any ground contact (including steep slopes).

Returns: List[nx, ny, nz] ground surface normal.

Returns: List[vx, vy, vz] velocity of the surface the controller is standing on (for moving platforms).

Returns: List[vx, vy, vz] current controller velocity.

if (_controller.state == CharacterState.JUMPING) {
// play jump animation
}
if (_controller.groundState == 1) {
// on steep slope — slide down
_controller.setDesiredVelocity(0, -5, 0)
}

Get or set the controller world position. Returns [x, y, z].

Get or set the rotation (Euler radians). Returns [rx, ry, rz].

Get or bind the controller to a Node. When bound, the node’s world position is updated each frame to follow the controller. Bind after creating the controller to drive a scene node.

_controllerNode = _scene.addNode("Player")
_controller.node = _controllerNode

Returns: Booltrue if the shape change succeeded (i.e. the new capsule fits in the current position without overlap).

Change the capsule dimensions at runtime (e.g. stand up from crouch). Returns false if the new shape would overlap existing geometry.

Read-only current capsule dimensions.

PropertyDefaultDescription
walkSpeed / walkSpeed=(value)Walk speed in m/s
runSpeed / runSpeed=(value)Run speed in m/s
crouchSpeed / crouchSpeed=(value)Crouch speed in m/s
swimSpeed / swimSpeed=(value)Swim speed in m/s
jumpVelocity / jumpVelocity=(value)Upward velocity applied on jump()
_controller.walkSpeed = 3
_controller.runSpeed = 7
_controller.jumpVelocity = 6

Constant class for state values returned by controller.state:

ConstantValueDescription
CharacterState.IDLE0Standing still
CharacterState.WALKING1Moving at walk speed
CharacterState.RUNNING2Moving at run speed
CharacterState.JUMPING3In a jump (rising)
CharacterState.FALLING4Falling (no ground contact)
CharacterState.SWIMMING5Swimming
CharacterState.CROUCHING6Crouching, stationary
CharacterState.CROUCH_WALKING7Moving while crouching
CharacterState.INTERACTING8Custom interaction state
CharacterState.CUSTOM_TOGGLE_ON9Custom toggle on
CharacterState.CUSTOM_TOGGLE_OFF10Custom toggle off
if (_controller.state == CharacterState.RUNNING) {
// Play run animation
}

See Physics for rigid body operations and contact events. See Scene for createCharacterController.