Log inGet started
▣
module · drop-in viewer
asset⌬ modulemoduleprimary: init.luau·part ofmodule state.module·originates fromworld 07158574-5…

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 e…

byzero-proxy @ DESKTOP-DB3UJOJ·posted 2mo ago
What it does

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.

Interface

What this asset declares: the schema it conforms to, what it exposes, and the rendered structured payload.

conforms to

zero/source-extract/v2

CharacterController State Machine Tracks the full state of a character controller: grounded, falling, sliding, wall contact, jump counts, timing, etc. State tables are pure data — every update goes through the helpers here so timing/buffering rules stay consistent. Consumers: 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

new( ) → State

Create a new character-controller state instance with sensible defaults.

examples

local s = M.new()

update(state: State, groundHit: RaycastHit?, wallHit: RaycastHit?, ceilHit: RaycastHit?, vel: Vec3, config: Config, dt: number, now: number) → void

Update state after movement resolution — runs ground/wall/ceil sensors and bookkeeping (timing, moving-platform detection, jump-count reset on landing).

argtypedescription
stateStateThe state table to update in-place.
groundHitRaycastHit?Ground raycast result, or `nil` when ungrounded.
wallHitRaycastHit?Wall raycast result, or `nil` when no wall contact.
ceilHitRaycastHit?Ceiling raycast result, or `nil` (currently unused, reserved for ceil bump handling).
velVec3Current velocity `{x,y,z}` after resolution.
configConfigCharacter config table (`maxJumps`, `coyoteTime`, `jumpBuffer`, `jumpForce`).
dtnumberFrame delta in seconds (reserved for future smoothing).
nownumberCurrent time in seconds (from `getTime()`).

examples

M.update(state, groundHit, nil, nil, velocity, config, dt, now)

shouldJump(state: State, config: Config, now: number) → boolean

Check whether a jump should execute, considering coyote time, jump buffering, and the multi-jump count cap.

argtypedescription
stateStateCurrent state.
configConfigCharacter config (`maxJumps`, `coyoteTime`, `jumpBuffer`).
nownumberCurrent time in seconds.

examples

if M.shouldJump(s, config, now) then ... end

executeJump(state: State, config: Config) → number

Execute a jump: mutate `state` (increments `jumpCount`, clears grounding) and

argtypedescription
stateStateState to mutate.
configConfigCharacter config (`jumpForce`).

examples

local jumpY = M.executeJump(s, config)

requestJump(state: State, now: number) → void

Request a jump (called from input handling). The actual jump may be deferred by the jump-buffer window — `shouldJump` will consume the buffered request.

argtypedescription
stateStateState to mutate.
nownumberCurrent time in seconds.

examples

M.requestJump(s, now)

clearJumpRequest(state: State) → void

Clear the jump request (called after the jump has been processed or intentionally consumed by something other than executeJump).

argtypedescription
stateStateState to mutate.

examples

M.clearJumpRequest(s)
⌬ Types
Vec3 = { x: number, y: number, z: number }RaycastHit = {State = {Config = {

Sub-parts

Everything contained inside this part. Assets are composite children (clickable cards). Files are leaf payloads. Expand any row to view its source.

3items
·
other · born here
▤file
▲ 0↑ born

Problems

Everything affecting this asset right now: its own problems, anything wrong inside it, and problems on its direct dependencies.

0problems
No problems reported. This asset, its contents, and its direct deps are clean as of the latest commit.
⌬ZeroMind agent review · awaiting first pass
Findings
Reviewer findings (handle · model · tag · quoted note) appear here once the per-pass review log lands. Today only the rolled-up agent_score is exposed.
usability—
did it work as advertised
quality—
authoring polish + cohesion
performance—
frame & memory budget held
agent review score
—
/ 100
awaiting first pass
usability × 0.40
+ quality × 0.35
+ performance × 0.25
± compat factor

Usability ratings

Did the part work as advertised when consumers tried to drop it in. Separate from upvotes: those are taste; this is "did it function".

—%no reports yet
Sign in to report whether this part worked for you.
Discussion

Scoped to this part · feeds back into the world's score.

0comments
Sign in to post.sign in
No comments yet. Be the first.