Repository navigation
NavTurning
NavTurning converts a desired direction into deterministic fixed-step
rotation. It buffers one requested target, interpolates toward it, detects
arrival, and can optionally create a turn after a collision.
Most applications should let Navigator drive turning. Use NavTurning
directly only when the host needs facing control without the full Navigator
lifecycle.
Turning works from snapshots rather than an engine interface. Each update uses:
- current world position;
- previous world position;
- current forward direction;
- current rotation.
If TrySimulateTurn(...) returns true, apply the returned quaternion. A
false result means no rotation should be applied for that frame.
A turn request is buffered. It does not rotate the body immediately.
var turning = new NavTurning(context, bodyRadius);
turning.RequestTurnDirection(currentForward, desiredForward);
if (turning.TrySimulateTurn(
position,
lastPosition,
currentForward,
currentRotation,
out FixedQuaternion appliedRotation))
{
currentRotation = appliedRotation;
}The example variables are host snapshots. In a real integration, call
TrySimulateTurn(...) once per fixed step and apply the returned rotation to
the authoritative body.
RequestTurnDirection(...) accepts an optional interpolation override. When no
positive override is supplied, turning uses TurnRate * context.DeltaTime.
Interpolation is clamped to the closed range [0, 1].
NeedsTurn(...) compares current and requested facing and ignores differences
within the minimum angle. This prevents tiny steering changes from producing
visible jitter or endless turn requests.
You can call the static helper before coordinating your own facing logic:
if (NavTurning.NeedsTurn(currentForward, desiredForward))
turning.RequestTurnDirection(currentForward, desiredForward);RequestTurnDirection(...) already performs the same check, so the extra call
is needed only when the host wants to make another decision from the result.
TargetReached means no interpolation is currently active. It does not promise
that no buffered request is waiting to start.
When an idle update finds a buffered target, that same update promotes it and
begins interpolation. TargetRotation then exposes the active target.
StopTurn() marks the active interpolation complete. It does not clear a
buffered request that has not started yet, so a later update may still consume
that request.
Only one target is buffered. NavTurning is not a queue.
NotifyCollision() records that an automatic turn should be considered. It
does not rotate immediately.
On a later idle update, turning compares the frame's actual movement with a radius- and frame-rate-derived threshold. When the movement is large enough, it buffers a turn toward that movement direction. The following update may then begin rotation.
turning.NotifyCollision();
// The first update may only buffer the collision turn.
turning.TrySimulateTurn(
position,
lastPosition,
forward,
rotation,
out _);Set CanTurnOnCollision when host state needs to veto automatic collision
turning. Returning false defers the pending collision turn; a later idle
update evaluates it again without introducing an engine dependency into
Trailblazer.
When driving a full controller, call navigator.NotifyCollision() instead so
the notification remains at the host-facing orchestration boundary.
Navigator owns the normal order:
- steering produces a desired movement direction;
- Navigator buffers that direction on
Turning; - Navigator advances turning once;
-
CommitFrameMotion()applies the frame's rotation state.
Do not independently simulate navigator.Turning in the same frame. Use
navigator.Simulate() and navigator.CommitFrameMotion() so steering, motor,
and turning remain coordinated.
Navigator persistence records public turning configuration and state through Chronicler. The owning context is restored separately and must already be available when the existing Navigator shell is populated.
RequestTurnDirection(...) buffers a target. Rotation happens during
TrySimulateTurn(...) or the owning Navigator's simulation.
It describes active interpolation only. One buffered target may still exist.
Collision turning is staged: notify, evaluate and buffer, then simulate the turn.
Navigator already advances its turning controller. Calling the lower-level method again can make frame behavior diverge from the intended lifecycle.