Summary
The OnEnter event always fires correctly, but OnExit fires inconsistently (Sometimes it does, Sometimes it doesn't) when the NetworkTrigger2D/NetworkCollider2D component is placed on a GameObject whose Transform is driven by a Unity Animator (e.g. a weapon attached to a hand bone that is animated for a swing/attack).
Root cause (as far as I can tell)
NetworkCollider2D.CheckColliders() maintains a tick-indexed history (Dictionary<uint, HashSet<Collider2D>> _enteredColliders) and relies on this history being consistent across repeated calls for the same localTick during client reconciliation (PredictionManager.OnPostPhysicsTransformSync → replay).
When the collider's Transform is animated by Unity's Animator rather than driven by tick-deterministic/networked logic, its world position at replay time does not match its position during the original tick. This means:
- On the original pass for tick N, an overlap may be detected and written to
_enteredColliders[N].
- On a later reconcile replay of tick N, the Animator has moved on in real time, so the same overlap check now returns different (often empty) results.
- Since
CheckColliders overwrites _enteredColliders[localTick] on each call (see the "tick is being run again... store the prior collection" branch), the replay silently replaces the original correct entry with a stale/incorrect one.
- This corrupts the
lastTick lookup on subsequent ticks, causing OnExit to fail to fire, fire late, or fire inconsistently.
Summary
The
OnEnterevent always fires correctly, butOnExitfires inconsistently (Sometimes it does, Sometimes it doesn't) when theNetworkTrigger2D/NetworkCollider2Dcomponent is placed on a GameObject whose Transform is driven by a UnityAnimator(e.g. a weapon attached to a hand bone that is animated for a swing/attack).Root cause (as far as I can tell)
NetworkCollider2D.CheckColliders()maintains a tick-indexed history (Dictionary<uint, HashSet<Collider2D>> _enteredColliders) and relies on this history being consistent across repeated calls for the samelocalTickduring client reconciliation (PredictionManager.OnPostPhysicsTransformSync→ replay).When the collider's Transform is animated by Unity's
Animatorrather than driven by tick-deterministic/networked logic, its world position at replay time does not match its position during the original tick. This means:_enteredColliders[N].CheckCollidersoverwrites_enteredColliders[localTick]on each call (see the "tick is being run again... store the prior collection" branch), the replay silently replaces the original correct entry with a stale/incorrect one.lastTicklookup on subsequent ticks, causingOnExitto fail to fire, fire late, or fire inconsistently.