Log inGet started
World

Builtin Library

Branchmain
Branchesmainpublish
Commitdd348ac6c3

README.md

machine

State machine helper for the builtin character controller. Owns the state table shape (grounded / falling / sliding / wall contact / blocked / jump counts / moving-platform tracking) and the timing rules (coyote time, jump buffering, multi-jump cap) that the controller consumes each tick. Pure logic — no engine globals beyond entity() for platform position lookups.

Exports

  • M.new() -> State — allocate a fresh state with default values.
  • M.update(state: State, groundHit, wallHit, ceilHit, vel, config, dt, now) — run ground/wall sensors and update grounding, timing, and moving-platform fields.
  • M.shouldJump(state: State, config: Config, now: number) -> boolean — decide whether a queued jump should fire this tick.
  • M.executeJump(state: State, config: Config) -> number — mutate state for a jump and return the Y velocity to apply.
  • M.requestJump(state: State, now: number) — register a jump press (may be deferred via jump buffer).
  • M.clearJumpRequest(state: State) — drop any pending jump request.

Types:

  • Vec3 = { x: number, y: number, z: number }
  • RaycastHit = { point?, normal: Vec3, entityId?, _sliding?, _blocked? } — shape of Physics.raycast-style hits the controller produces.
  • State = { grounded, falling, sliding, wallContact, blocked, wallNormal, velocity, groundNormal, slopeAngle, jumpCount, timeSinceGrounded, timeSinceWallContact, onMovingPlatform, platformEntity, ...internal timing fields }
  • Config = { maxJumps?, coyoteTime?, jumpBuffer?, jumpForce? } — character tuning fields read each tick.

Usage

local State = require("@builtin::systems.characterController.characterController.state.machine")

local s = State.new()
State.update(s, groundHit, wallHit, ceilHit, vel, config, dt, now)

if State.shouldJump(s, config, now) then
    local jumpY = State.executeJump(s, config)
end

Notes

  • update is destructive — it mutates state in place. The state table is the single source of truth; callers should not rebuild it each tick.
  • The jump-buffer window persists across frames; shouldJump consumes it via the _jumpBufferTime/_jumpRequested pair.
  • Moving-platform detection relies on the platform entity's localPosition — non-entity hits leave onMovingPlatform = false.
  • blocked is true on a frame the wall pass left the character with none of the horizontal movement it asked for — wallHit._blocked, which Velocity.resolve marks. It is what tells a character standing still apart from one whose walk is being refused.
  • ceilHit is accepted for API symmetry but currently unused; future ceiling-bump handling will read it without changing the signature.