Builtin Library
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.setand 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
groundSnapDistancewhen grounded and100when 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 setgroundHit._sliding = trueso the state machine treats the frame asslidingrather thangrounded. - 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.