@modoki/engine / index / zone3DSystem
Function: zone3DSystem()
zone3DSystem(
world):void
Deactivated zones/occupants are DROPPED from this frame's lists, which makes the existing membership diff synthesize their exit events for free — the same path a DESPAWNED zone already takes ("removing a zone fires exit for all its occupants", docs/zones.md). That is the deliberate semantic: switching a trigger volume off means it is GONE while off, not paused, so the enter/exit ledger stays BALANCED — code that counted an enter always gets its exit. (Matches Unity, where disabling a trigger collider fires OnTriggerExit.) Re-activating fires a fresh enter for whoever is still inside, so a one-shot "first time here" handler needs its own guard. Contrast Director, which FREEZES on deactivation — a playhead has no ledger to keep balanced, so resuming where it stopped is the useful behaviour there.
Uses isEntityActiveInHierarchy (runtime/core/ecs/entityIndex.ts) rather than the renderers' deactivatedEntities: although these systems run at TRANSFORM+2 (so that set would be current, unlike timelineSystem's case), it is produced by a THREE module the headless harness never registers — the guard would be permanently inert in headless games and untestable.
Parameters
world
World
Returns
void