Game.Simulation.WaitingPassengersSystem
Assembly:
Namespace: Game.Simulation
Type: class
Base: GameSystemBase
Summary:
WaitingPassengersSystem collects and updates waiting passenger statistics for transport stops and queue areas. It performs three main tasks each update: clear per-stop counters, count waiting humans and groups at transport stops and queues (accumulating counts and ongoing wait estimates into WaitingPassengers components), and tick/update those WaitingPassengers values (decaying/consuming accumulations, adjusting averaged waiting time, and marking stops for pathfinding updates when averages change). The system uses Burst-compiled IJobChunk jobs and an EndFrameBarrier command buffer to safely add components from jobs.
Fields
-
private EndFrameBarrier m_EndFrameBarrier
Reference to the EndFrameBarrier system used to create an EntityCommandBuffer for marking entities (PathfindUpdated) from a job. The system adds the produced job handle to this barrier so the barrier can wait for completion and flush commands at end of frame. -
private EntityQuery m_StopQuery
EntityQuery that matches entities with the WaitingPassengers component and excludes Temp and Deleted. This query is used to schedule jobs operating on transport stops (clear + tick jobs). -
private EntityQuery m_ResidentQuery
EntityQuery that matches resident/creature entities with HumanCurrentLane (and excludes Temp, Deleted, and GroupMember). This query is used by the counting job to iterate residents and inspect their path/queue data. -
private TypeHandle __TypeHandle
Internal struct instance that caches ComponentTypeHandle, BufferTypeHandle, EntityTypeHandle and ComponentLookup instances used by the jobs. Populated in OnCreateForCompiler / __AssignHandles to avoid recreating handles every frame.
Properties
- (none)
Constructors
public WaitingPassengersSystem()
Default constructor. The system initialization of handles/queries happens in OnCreate/OnCreateForCompiler rather than the constructor.
Methods
-
public override int GetUpdateInterval(SystemUpdatePhase phase)
Returns 256. The system requests to update at this interval (i.e., it is intended to run less frequently than every frame — the update scheduler will use this value to throttle updates). -
protected override void OnCreate()
Initializes system state: - Resolves the EndFrameBarrier system from World and stores it in m_EndFrameBarrier.
- Creates m_StopQuery to select WaitingPassengers entities (excluding Temp/Deleted).
- Creates m_ResidentQuery to select resident/creature entities with HumanCurrentLane (excluding Temp/Deleted/GroupMember).
-
Calls RequireForUpdate(m_StopQuery) so the system only runs when there are stops present.
-
protected override void OnUpdate()
Primary scheduling method. It: - Builds job data for ClearWaitingPassengersJob (resets WaitingPassengers counters).
- Builds job data for CountWaitingPassengersJob (iterates resident entities, determines stops or queue targets and accumulates counts into per-stop WaitingPassengers via a ComponentLookup with Interlocked.Add).
- Schedules TickWaitingPassengersJob, CountWaitingPassengersJob, and ClearWaitingPassengersJob with appropriate dependencies:
- ClearWaitingPassengersJob runs on m_StopQuery.
- CountWaitingPassengersJob runs on m_ResidentQuery and writes into WaitingPassengers via ComponentLookup; it is scheduled to run after Clear.
- TickWaitingPassengersJob runs on m_StopQuery and depends on the counting job; it uses a RandomSeed and an EndFrameBarrier command buffer (AsParallelWriter) to add PathfindUpdated to a stop when the average waiting time changes.
-
Adds the resulting job handle to the EndFrameBarrier via AddJobHandleForProducer, and stores the dependency.
-
private void __AssignQueries(ref SystemState state)
Compiler helper used by OnCreateForCompiler; here it creates a temporary EntityQueryBuilder (empty) and disposes it. In generated code this method can set up query caching; in the decompiled snippet it's effectively a placeholder. -
protected override void OnCreateForCompiler()
Compiler/authoring-time method that assigns query handles and component type handles by calling __AssignQueries and TypeHandle.__AssignHandles. This ensures the cached handles are initialized for the Burst jobs. -
private struct TypeHandle.__AssignHandles(ref SystemState state)
Initializes and caches all ComponentTypeHandle/BufferTypeHandle/EntityTypeHandle/ComponentLookup used by the jobs: - WaitingPassengers (read-write)
- HumanCurrentLane (read-only)
- Resident (read-only)
- PathOwner (read-only)
- PathElement buffer (read-only)
- GroupCreature buffer (read-only)
- Queue buffer (read-only)
- ComponentLookup
(for atomic updates from counting job) -
EntityTypeHandle
-
private struct ClearWaitingPassengersJob : IJobChunk
Burst job that iterates chunks matched by m_StopQuery and resets WaitingPassengers.m_Count and WaitingPassengers.m_OngoingAccumulation to zero for every matched entity. This ensures counting starts from zero each update. -
private struct CountWaitingPassengersJob : IJobChunk
Burst job (ReadOnly for many inputs) that iterates resident/creature entities and: - Checks if the creature has reached a transport stop (CreatureUtils.TransportStopReached) and if so inspects its path buffer to find the target stop entity.
- Otherwise iterates Queue buffer entries for the creature and inspects queue.m_TargetEntity.
- Accumulates counts per stop in a streaming-fashion: it compares the target to the lastStop, and when changing stop it uses ComponentLookup
with Interlocked.Add to apply the previously accumulated counts to the WaitingPassengers component of the lastStop. - For each resident it computes an int2: x = number of people (1 + group size), y = ongoing accumulation estimated as resident.m_Timer * x * (2/15). These are added to the running accumulation.
-
The method is careful to skip null target entities and handles group creatures and residents that may not exist on every chunk.
-
private struct TickWaitingPassengersJob : IJobChunk
Burst job that updates WaitingPassengers values per stop: - Uses a RandomSeed to produce per-chunk randomness.
- For each WaitingPassengers instance:
- Randomly increments SuccessAccumulation occasionally (1/64 chance) up to ushort.MaxValue.
- Computes an average waiting time estimate based on ongoing and concluded accumulation vs. counts and success accumulation. It uses integer math with math.max and math.cmax, clamps the result to a maximum of 65535 and normalizes it to the nearest multiple of 5 (num - num % 5).
- If the newly computed average differs from stored m_AverageWaitingTime, the job adds a PathfindUpdated component to the entity using the EndFrameBarrier command buffer (so pathfinding can react to changed stop wait times).
- Applies a stochastic decay/consumption of success accumulation and concluded accumulation (random factor using NextInt and bit-shifts).
- Writes back updated fields (ConcludedAccumulation, SuccessAccumulation, AverageWaitingTime).
Notes about thread-safety and atomics:
- CountWaitingPassengersJob uses ComponentLookup
Usage Example
[Preserve]
protected override void OnCreate()
{
base.OnCreate();
m_EndFrameBarrier = base.World.GetExistingSystemManaged<EndFrameBarrier>();
m_StopQuery = GetEntityQuery(ComponentType.ReadWrite<WaitingPassengers>(),
ComponentType.Exclude<Temp>(),
ComponentType.Exclude<Deleted>());
m_ResidentQuery = GetEntityQuery(ComponentType.ReadOnly<HumanCurrentLane>(),
ComponentType.Exclude<Temp>(),
ComponentType.Exclude<Deleted>(),
ComponentType.Exclude<GroupMember>());
RequireForUpdate(m_StopQuery);
}
This example shows how the system initializes its EndFrameBarrier reference and entity queries in OnCreate so the jobs scheduled in OnUpdate have the proper queries and command buffers available.