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.
Creating a controller
Section titled “Creating a controller”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)Movement input
Section titled “Movement input”setDesiredVelocity(vx, vy, vz)
Section titled “setDesiredVelocity(vx, vy, vz)”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 = 5var vx = 0var vz = 0if (Input.key("a")) vx = -speedif (Input.key("d")) vx = speedif (Input.key("w")) vz = -speedif (Input.key("s")) vz = speed_controller.setDesiredVelocity(vx, 0, vz)jump()
Section titled “jump()”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.
facingYaw / facingYaw=(value)
Section titled “facingYaw / facingYaw=(value)”Get or set the yaw angle (radians) the controller is facing. Used for directional movement and animation.
State queries
Section titled “State queries”Returns: Num — Current CharacterState constant.
groundState
Section titled “groundState”Returns: Num — Ground contact state:
| Value | Meaning |
|---|---|
0 | On ground (flat/walkable) |
1 | On steep ground (too steep to walk) |
2 | Not supported (hanging, ledge) |
3 | In air |
isGrounded
Section titled “isGrounded”Returns: Bool — true when the controller is on walkable ground (groundState == 0).
isSupported
Section titled “isSupported”Returns: Bool — true when the controller has any ground contact (including steep slopes).
getGroundNormal()
Section titled “getGroundNormal()”Returns: List — [nx, ny, nz] ground surface normal.
getGroundVelocity()
Section titled “getGroundVelocity()”Returns: List — [vx, vy, vz] velocity of the surface the controller is standing on (for moving platforms).
getLinearVelocity()
Section titled “getLinearVelocity()”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)}Position & transform
Section titled “Position & transform”getPosition() / setPosition(x, y, z)
Section titled “getPosition() / setPosition(x, y, z)”Get or set the controller world position. Returns [x, y, z].
getRotation() / setRotation(rx, ry, rz)
Section titled “getRotation() / setRotation(rx, ry, rz)”Get or set the rotation (Euler radians). Returns [rx, ry, rz].
node / node=(value)
Section titled “node / node=(value)”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 = _controllerNodesetShape(height, radius)
Section titled “setShape(height, radius)”Returns: Bool — true 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.
height / radius
Section titled “height / radius”Read-only current capsule dimensions.
Speed settings
Section titled “Speed settings”| Property | Default | Description |
|---|---|---|
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 = 6CharacterState
Section titled “CharacterState”Constant class for state values returned by controller.state:
| Constant | Value | Description |
|---|---|---|
CharacterState.IDLE | 0 | Standing still |
CharacterState.WALKING | 1 | Moving at walk speed |
CharacterState.RUNNING | 2 | Moving at run speed |
CharacterState.JUMPING | 3 | In a jump (rising) |
CharacterState.FALLING | 4 | Falling (no ground contact) |
CharacterState.SWIMMING | 5 | Swimming |
CharacterState.CROUCHING | 6 | Crouching, stationary |
CharacterState.CROUCH_WALKING | 7 | Moving while crouching |
CharacterState.INTERACTING | 8 | Custom interaction state |
CharacterState.CUSTOM_TOGGLE_ON | 9 | Custom toggle on |
CharacterState.CUSTOM_TOGGLE_OFF | 10 | Custom toggle off |
if (_controller.state == CharacterState.RUNNING) { // Play run animation}See Physics for rigid body operations and contact events. See Scene for createCharacterController.