Game.Simulation.CitizenEvacuateSystem
Assembly: Game
Namespace: Game.Simulation
Type: class
Base: GameSystemBase
Summary:
Handles citizen evacuation behavior during emergency events. The system runs at a reduced frequency (once every 16 simulation frames) and schedules a parallel IJobChunk (CitizenEvacuateJob) to process citizens whose CurrentBuilding is marked InDanger with evacuation flags. Depending on the InDanger flags it will either send citizens to the nearest shelter (by setting TripNeeded with Purpose.EmergencyShelter) or attempt to board dispatched public transport vehicles (if a handler is boarding and matches the evacuation request). The system uses an EndFrameBarrier command buffer to modify components (remove ResourceBuyer / TravelPurpose / AttendingMeeting and update TripNeeded) and relies on UpdateFrame shared component to stagger work across chunks.
Fields
-
private SimulationSystem m_SimulationSystem
References the SimulationSystem instance used to read the global frameIndex. The frameIndex is used to compute the UpdateFrame index which staggers chunk updates. -
private EndFrameBarrier m_EndFrameBarrier
Used to create an EntityCommandBuffer (AsParallelWriter) to safely enqueue structural/component changes from the job and ensure they run at the end of the frame. -
private EntityQuery m_InDangerQuery
Query selecting InDanger entities (used to require the system update only when there are in-danger entities present). -
private EntityQuery m_CitizenQuery
Query selecting citizens that should be processed (reads Citizen and CurrentBuilding, excludes HealthProblem/Deleted/Temp). The system requires this query to run. -
private TypeHandle __TypeHandle
Internal struct containing cached Entity/Component/Buffer type handles and ComponentLookups used to build the job's handles. Assigned in OnCreateForCompiler.
Properties
- (No public properties exposed by this system.)
Constructors
public CitizenEvacuateSystem()
Default constructor (annotated with [Preserve] in source). Actual initialization of queries and type handles happens in OnCreate / OnCreateForCompiler.
Methods
-
public override int GetUpdateInterval(SystemUpdatePhase phase)
Returns the system's update interval in frames. This system returns 16, meaning it runs at 1/16th of the simulation frame rate (staggered behavior in-game to reduce per-frame cost). -
protected override void OnCreate()
Sets up required systems and entity queries: - Acquires SimulationSystem and EndFrameBarrier via World.GetOrCreateSystemManaged.
- Creates m_InDangerQuery and m_CitizenQuery with required component filters.
-
Calls RequireForUpdate for both queries so the system only runs when relevant entities exist.
-
protected override void OnUpdate()
Builds and schedules the CitizenEvacuateJob in parallel: - Computes a per-update UpdateFrame index from SimulationSystem.frameIndex: (frameIndex >> 4) & 0xF. This is used to only process chunks whose UpdateFrame matches, staggering work across frames.
- Fills job fields (type handles, lookups, command buffer writer).
- Schedules the job with JobChunkExtensions.ScheduleParallel using m_CitizenQuery.
- Adds the job handle to m_EndFrameBarrier (so the barrier knows about the producer).
-
Sets base.Dependency to the scheduled job handle.
-
private void __AssignQueries(ref SystemState state)
Compiler helper; current implementation creates/disposes a temporary EntityQueryBuilder. Present for compiler-generated wiring; not used directly by modders. -
protected override void OnCreateForCompiler()
Compiler helper that calls __AssignQueries and assigns cached type handles (__TypeHandle.__AssignHandles) using the system state. Ensures type handles are prepared for job scheduling. -
Inner type: CitizenEvacuateJob (IJobChunk)
Summary of job behavior: - Fields: m_UpdateFrameIndex, m_CommandBuffer (ParallelWriter), EntityTypeHandle, SharedComponentTypeHandle
, ComponentTypeHandle , BufferTypeHandle , ComponentLookup , ComponentLookup , BufferLookup , ComponentLookup (rw). - Execute: For each chunk, checks the chunk's UpdateFrame shared component and returns early if it does not match m_UpdateFrameIndex. Iterates citizens in the chunk:
- Gets currentBuilding from CurrentBuilding component.
- Skips if current building has no InDanger component.
- Reads InDanger flags:
- If DangerFlags.Evacuate is not set: skip.
- If DangerFlags.UseTransport is set:
- Calls GetBoardingVehicle to check if there is a dispatched public transport handler currently in Boarding state and that the first ServiceDispatch buffer entry matches the evacuation request. If a vehicle is found, calls GoToVehicle to set TripNeeded to Purpose.EmergencyShelter with m_TargetAgent = vehicle and removes ResourceBuyer / TravelPurpose / AttendingMeeting components from the citizen using the command buffer.
- If no vehicle is boarding, sets the WaitingCitizens flag on the InDanger record (if not already set).
- If UseTransport is not set: calls GoToShelter to set TripNeeded to Purpose.EmergencyShelter and remove ResourceBuyer / TravelPurpose / AttendingMeeting.
- GetBoardingVehicle logic: verifies that the evacuation request entity has a Dispatched component and that the dispatched handler has a PublicTransport component with the Boarding bit set and a ServiceDispatch buffer whose first entry matches the request. Returns the handler entity as vehicle if successful.
- GoToShelter / GoToVehicle: clear TripNeeded buffer and add a single TripNeeded with Purpose.EmergencyShelter (GoToVehicle also sets m_TargetAgent to the found vehicle). Use the command buffer to remove ResourceBuyer, TravelPurpose and AttendingMeeting from the citizen.
Notes: - The job uses m_InDangerData with NativeDisableParallelForRestriction to allow safe concurrent reads/writes to InDanger entries; when flags are updated (WaitingCitizens cleared/set), it writes back the updated InDanger component. - Structural/component removals are done via the EndFrameBarrier's parallel command buffer to avoid structural changes inside the job.
Usage Example
[Preserve]
protected override void OnCreate()
{
base.OnCreate();
// Acquire required systems and build queries (source does this automatically)
m_SimulationSystem = World.GetOrCreateSystemManaged<SimulationSystem>();
m_EndFrameBarrier = World.GetOrCreateSystemManaged<EndFrameBarrier>();
m_InDangerQuery = GetEntityQuery(ComponentType.ReadWrite<InDanger>(), ComponentType.Exclude<Deleted>(), ComponentType.Exclude<Temp>());
m_CitizenQuery = GetEntityQuery(ComponentType.ReadOnly<Citizen>(), ComponentType.ReadOnly<CurrentBuilding>(), ComponentType.Exclude<HealthProblem>(), ComponentType.Exclude<Deleted>(), ComponentType.Exclude<Temp>());
RequireForUpdate(m_InDangerQuery);
RequireForUpdate(m_CitizenQuery);
}
Additional notes for modders: - The system expects and manipulates these components: InDanger, CurrentBuilding, TripNeeded (buffer), ResourceBuyer, TravelPurpose, AttendingMeeting, Dispatched, PublicTransport, ServiceDispatch, UpdateFrame, Citizen. Modifications to those component definitions or lifecycle may affect evacuation behavior. - The UpdateFrame shared component is used to distribute chunk work across multiple frames; do not assume all citizens are processed every time the system runs. - If you need to hook or extend evacuation behavior, consider: - Adding/observing InDanger flags to control building evacuation state. - Intercepting or augmenting TripNeeded buffer content for custom destinations. - Using EndFrameBarrier to schedule structural changes from jobs in a compatible way.