There are two ways to observe a controller after a tick:
Live getters (controller.isOnGround, controller.currPos, …) — return
the controller’s internal values with no allocation. Vectors and
quaternions are the actual three instances the controller reuses each tick.
snapshot() — returns a fresh, immutable
CharacterControllerSnapshot of plain data. update(dt) returns one
automatically.
// Zero-allocation reads (best for per-frame loops):
if (controller.isOnGround&& controller.moveSpeed>0.1) { /* footstep */ }
// Detached copy (safe to store, serialize, diff):
snapshot() (and the return of update(dt)) is a CharacterControllerSnapshot
with these read-only fields. Vectors are { x, y, z }, quaternions are
{ x, y, z, w }.
The platform’s per-tick yaw rotation (used for platform-follow turning).
input
MovementInput
The current movement intent.
These field names are intentionally Ecctrl-compatible (currPos,
currQuat, inputDir, movingDirection, relativeVel, floatingImpulse,
standCollider, isOnGround, runActive, lockForward, turnOnYQuat), so
code and debug overlays written against Ecctrl’s handle port with minimal
changes. standBody is a Jolt-flavored alias for standCollider.
The five booleans an animation state machine needs — isOnGround, isFalling,
isMoving, runActive, jumpActive — are all present as getters and snapshot
fields, which is exactly what
createCharacterAnimationStateController reads.