Motor Ownership & Handover
The Single-Writer Invariant for Flawless Motion Continuity
One of the most persistent bugs in character AI is transform fighting: an AI steering script and a landing script simultaneously trying to write to the character’s transform.position. The result is violent visual jitter, erratic physics collisions, and broken navigation.
PERCH enforces a strict Single-Writer Transform Invariant governed by the MotionOwner state.
The MotionOwner Enum
At any given microsecond, exactly one system possesses the authority to displace the creature’s root:
public enum MotionOwner
{
ExternalProvider, // Wandering/Navigation AI owns movement
PerchMotor, // PERCH owns approach, touchdown, anchoring, takeoff
InterventionHold // Safety freeze during entrapment
}
[Free Roaming] [Landing Approach & Dwell]
External Flight AI ──(Handover)──> PERCH Motor (Trajectory & IK)
(MotionOwner.ExternalProvider) (MotionOwner.PerchMotor)
^ |
+───────────(Takeoff Handover)─────────+
The Handover Contract (IPerchFlightProvider)
When PERCH transitions between free flight and landing approaches, it executes a formal handover handshake with the creature’s flight provider:
1. Acquiring Control (Flight $\rightarrow$ Approach)
- PERCH queries
provider.CanYield(agent). If the creature is in an unyielding state (e.g. playing a death animation or stunned), handover is declined withProviderRejected. - PERCH calls
provider.CaptureMotion(agent)to record the creature’s entry position, velocity vector, and forward heading. - PERCH calls
provider.OnPerchControlAcquired(agent). The provider suspends its internal steering updates. MotionOwnerswitches toMotionOwner.PerchMotor.
2. Releasing Control (Takeoff $\rightarrow$ Flight)
- As the creature completes its departure curve and clears the perch footprint:
- PERCH computes the final exit position $\mathbf{P}{\text{exit}}$ and departure velocity vector $\mathbf{V}{\text{exit}}$ (including platform momentum).
- PERCH calls
provider.OnPerchControlReleased(agent, exitPosition, exitVelocity). - The external provider initializes its steering vectors from the supplied exit velocity, eliminating any sudden direction snaps.
MotionOwnerreverts toMotionOwner.ExternalProvider.
Shipped Motor Implementations
PERCH provides two optimized motor components out of the box:
1. TransformMotor
- Target: Creatures that do not use physical Rigidbody dynamics.
- Mechanism: Writes directly to
transform.positionandtransform.rotationduringUpdate(). - Performance: Sub-microsecond execution; ideal for large background flocks of songbirds.
2. KinematicRigidbodyMotor
- Target: Characters interacting with complex physics colliders or moving physics triggers.
- Mechanism: Displaces the root using
Rigidbody.MovePosition()andRigidbody.MoveRotation()duringFixedUpdate(). - Stability: Eliminates physics penetration tunneling against moving environment colliders.