Skip to content

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.

Inspector
Pressure Plate
Trigger 3D Relay? ⇅ ⋮
On Trigger Enter (GameObject)
Runtime OnlyDoor.Open
Door
+−
On Trigger Exit (GameObject)
List is Empty
+−
A Trigger 3D Relay that opens the door when something steps onto the plate.

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.

See Also