Physics Event Relays¶
Broadcasts Unity physics callbacks as subscribable C# events. Pick the subclass that matches the callback family you need — each only registers its own Unity messages with the physics engine.
Namespace: Jungle.Physics
Base type: PhysicsEventRelayBase (abstract MonoBehaviour)
Why split relays¶
Defining a Unity physics message (OnTriggerEnter, OnCollisionEnter, …) on a MonoBehaviour registers that GameObject with the physics engine for that message path whether or not anyone listens. A single relay that defines all 8 enter/exit messages pays the engine-side cost for four families even when only one is used. Each specific relay defines only its two Unity messages — Unity skips the others entirely.
Available subclasses¶
| Component | Listens for | Use when |
|---|---|---|
Trigger3DRelay |
OnTriggerEnter / OnTriggerExit |
The collider is a 3D trigger. |
Collision3DRelay |
OnCollisionEnter / OnCollisionExit |
The collider is a solid 3D collider. |
Trigger2DRelay |
OnTriggerEnter2D / OnTriggerExit2D |
The collider is a 2D trigger. |
Collision2DRelay |
OnCollisionEnter2D / OnCollisionExit2D |
The collider is a solid 2D collider. |
Each relay also shows its own Enter and Exit events in the Inspector, so you can wire a method there without code. Both receive the other GameObject.
If a GameObject genuinely needs more than one family, add multiple relays — each subscribes only to its own Unity messages, so the total cost is exactly the families you opt into.
All subclasses share the same subscription API (see below), so consumers like PhysicsEvent and PhysicsOverlapDetectionStrategy only know about PhysicsEventRelayBase.
Shared events¶
Every relay exposes the same 8 Action<GameObject> events on PhysicsEventRelayBase; an individual subclass only ever raises the ones it actually monitors. The SupportedEvents property lists which PhysicsEventType values that relay emits.
| Event | Fires from |
|---|---|
CollisionEntered / CollisionExited |
OnCollisionEnter / OnCollisionExit |
TriggerEntered / TriggerExited |
OnTriggerEnter / OnTriggerExit |
CollisionEntered2D / CollisionExited2D |
OnCollisionEnter2D / OnCollisionExit2D |
TriggerEntered2D / TriggerExited2D |
OnTriggerEnter2D / OnTriggerExit2D |
Methods¶
| Method | Description |
|---|---|
Register(PhysicsEventType, Action<GameObject>) |
Subscribe to a specific physics event type. No-ops silently if the relay subclass doesn't emit that type — call Supports first to validate. |
Unregister(PhysicsEventType, Action<GameObject>) |
Unsubscribe from a physics event type. |
Supports(PhysicsEventType) |
True if this relay actually emits the given event. Use to fail loudly on misconfiguration before wiring listeners. |
SupportedEvents |
Read-only list of the PhysicsEventType values this relay emits. |
FlushExits() |
Fires synthetic Exit events for every collider currently tracked as overlapping, then clears tracking. Reentrant. Called automatically from OnDisable. |
Stranded-exit protection¶
Unity does not fire OnTriggerExit / OnCollisionExit when one of this GameObject's own colliders is disabled, has isTrigger flipped, or is destroyed while still overlapping — listeners would be stuck thinking the other object is still inside.
Every relay tracks its overlapping colliders on enter/exit and exposes FlushExits() to synthesize the missing exits. It's called automatically from OnDisable (covers GameObject deactivation and destruction).
For programmatic collider mutation, the SetEnabled and SetTrigger collider operations call FlushExits() before applying their change, so the bug never surfaces through Jungle commands. If you toggle collider.enabled or collider.isTrigger from your own code on a GameObject that has a relay, call FlushExits() manually first.