Log inGet started
World

Builtin Library

Branchmain
Branchesmainpublish
Commitdd348ac6c3

README.md

velocity

Velocity integration and per-frame movement resolution for the character controller. Owns no state — every call takes the current position / velocity / config / state and returns the new position delta plus the updated velocity. Internally uses the Ground, Walls, and Ceiling raycasting helpers.

Exports

  • M.resolve(pos: Vec3, vel: Vec3, moveInput: MoveInput, config: Config, state, dt: number, selfId: string) -> (dx, dy, dz, vx, vy, vz, groundHit, wallHit, ceilHit) — apply gravity + air control, resolve wall slide / corner pin / ceiling bonk / ground snap / slope projection / steep-slope slide / step climbing in that order.

Types:

  • Vec3 = { x: number, y: number, z: number }
  • MoveInput = { x: number, z: number } — world-space horizontal input.
  • Config = { height?, radius?, maxSlopeAngle?, stepHeight?, gravity?, airControlFactor?, groundSnapDistance?, skinWidth? }

Usage

local Velocity = require("@builtin::systems.characterController.characterController.movement.velocity")

local dx, dy, dz, vx, vy, vz, groundHit, wallHit, ceilHit =
    Velocity.resolve(pos, vel, moveInput, config, state, dt, selfId)

Notes

  • The function is pure: it returns nine values but mutates nothing. The caller is responsible for writing the position delta back via entity.localPosition.set and updating its velocity field.
  • Air control blends horizontal velocity toward the input with airLerp = min(1, airControlFactor * 10 * dt). Grounded mode uses direct assignment for responsive feel.
  • Ground cast distance is groundSnapDistance when grounded and 100 when airborne (so a fast fall doesn't tunnel past the floor). Snap commit threshold is tight (the frame's own vertical travel), so airborne ground hits don't snap unless they are within that travel window.
  • A grounded frame looks for ground above the feet as well, by the rise its own travel covers on ground of maxSlopeAngle — that is the ground a walking character climbs into. The seat takes it up to the rise the surface it found covers over that travel, plus a step; a surface further up stands across the path, and the character keeps the ground it already has.
  • Steep-slope (above maxSlopeAngle) hits set groundHit._sliding = true so the state machine treats the frame as sliding rather than grounded.
  • A frame whose horizontal movement the wall pass cancels outright — pressed straight into a wall, or wedged where two surfaces meet — sets wallHit._blocked = true, so a refused walk reads as refused instead of as a walk that happened to cover no ground.
  • Step climbing only fires when state.grounded, horizontal motion exists, and no wall hit was registered.