
You are viewing a potentially older version of this package. View Latest Version
Optimized Kinematic Character Controller
Replaces games KinematicCharacterController assembly with a version modified by Claude AI to sacrifice quality for performance. Expect atleast 20% increase in performanceShort report from tester: "Seems like it works, with about a 3-5ms improvement across the board. Its easier to clip out of bounds though. Lowest values ended up going from ~14ms to ~10ms, actively sprinting/jumping into a corner went from ~20ms to ~16ms, very hectic gameplay with lots of enemies seemed to hover in the low ~20s instead of mid 20s"
Rundown on what Claude did for optimizing:
| Before | Now | |
|---|---|---|
| Decollision | up to 3 overlaps + penetration solves, in 2 phases | 1 overlap, run every tick for the player and every 4th tick for grounded NPCs |
| Ground probe | capsule cast, up to 3 retries, plus 2 ledge raycasts | 1 sphere cast; a ledge raycast only when the contact is far off-axis |
| Movement | up to 6 iterations, each with an overlap, a cast and crease logic | 3 iterations, one cast each |
| Steps | several sweeps and raycasts per hit | 2 queries, only when a low wall is hit |
| Idle grounded NPC | full cost | callbacks only, with a ground re-check every 8th tick |
Per-frame and FixedUpdate changes:
- No transform reads. The motor never reads the Transform back, so the Pre/Post passes are gone. It writes the pose once per tick, and only if it changed.
- Native interpolation. With Interpolate on, motors that have a kinematic Rigidbody use Unity’s native interpolation, so they have no managed per-frame cost. Motors without one fall back to a managed lerp in LateUpdate, skipped for idle characters.
- Movers. Movers use MovePosition/MoveRotation with native interpolation.
- No per-frame cost. With Interpolate off, nothing runs per frame.
- Lookups. GetComponent is gone from the hot path.
Quality you lose:
- No crease and corner solver, so tight corners can jitter.
- 3 slide iterations instead of 6.
- Ledge handling is a one-raycast approximation.
- Stepping is a simple step-up with a small forward probe.
- A character standing on steep ground only gets one probe.
- Dynamic rigidbody interaction is simplified.
- MaxVelocityForLedgeSnap, MaxStableDenivelationAngle, MinRequiredStepDepth and CheckMovementInitialOverlaps are now ignored.
API changes that could break your code:
- Teleporting. Use SetPosition/SetPositionAndRotation. Writing transform.position directly is ignored.
- Phases. UpdatePhase1/2 is replaced by Simulate(dt, full). The static pre/post interpolation methods are removed.
- Callback order. Each motor now runs its full tick before the next one starts, instead of all Phase1 callbacks and then all Phase2. If your characters read each other’s state inside callbacks, they’ll see different ordering.
- Time slicing. updateTimerMax <= 0 now means everyone updates every tick.
- Mover rotation. Angular velocity is now computed with a signed angle. The old eulerAngles form returned about 350° instead of -10° for negative rotations, so rotating platforms will behave differently.