Movement
Move step
Following equation is used to calculate desired position delta for single move step:
Position Delta = (Dynamic Velocity + Kinematic Velocity) * Delta Time + External Delta
Dynamic Velocity
- Velocity that accumulates external forces
- Gravity, impulse from explosion, force field, jump pad
- Can push the KCC upwards on slopes
KCCData.DynamicVelocity
,KCC.SetDynamicVelocity()
Kinematic Velocity
- Unconstrained velocity calculated from user input actions
- Usually based on
KCCData.InputDirection
(entry point) - Only walkable surfaces push the KCC upwards to prevent artifacts on steep slopes
KCCData.KinematicVelocity
,KCC.SetKinematicVelocity()
External Delta
- Absolute position offset
- Used for shifts and corrections after depenetration
KCCData.ExternalDelta
,KCC.SetExternalDelta()
The KCC always moves and then depenetrates from overlapping colliders.
- ✅ This approach gives natural sliding against geometry.
- ✅ Most of the time single capsule overlap is needed which makes KCC very performant.
- ❌ Sometimes it results in jitter when moving against multiple colliders (usually some corners), this is compensated by Anti-Jitter feature.
If the character moves too fast (position delta for single step is bigger than 85% or radius), the movement is divided into sub-steps to not pass through geometry.
This is called continuous collision detection (CCD) and is described in Features section.
Collision filtering
- Primary filter is collision layer mask - controlled by
KCCSettings.CollisionLayerMask
property. The Layer Collision Matrix from Physics Settings is not used by KCC. - Child colliders are cached upon spawning and ignored. If a new collider is added to the child hierarchy,
KCC.RefreshChildColliders()
needs to be called manually. - Register a delegate to
KCC.ResolveCollision
for application of additional filtering rules. - Use
KCC.IsValidHitCollider()
to validate if the KCC can possibly collide with a collider with current settings. - It is possible to explicitly ignore a specific collider with
KCC.SetIgnoreCollider()
- the collider must have aNetworkObject
component.