Game.Simulation.AmbulanceAISystem
Assembly: Assembly-CSharp
Namespace: Game.Simulation
Type: public class AmbulanceAISystem
Base: GameSystemBase
Summary:
AmbulanceAISystem is the Entity Component System (ECS) system that manages ambulance vehicles' AI and behaviour. It schedules a Burst-compiled parallel IJobChunk (AmbulanceTickJob) to process all ambulance entities: handling dispatches, pathfinding setup, loading/unloading patients, parking, returning to depot, emergency flags, and interacting with healthcare requests. The system integrates with PathfindSetupSystem (to enqueue pathfind tasks), EndFrameBarrier (for a parallel command buffer), and the SimulationSystem (for accessing the current simulation frame index and random seed). It runs at a reduced frequency (GetUpdateInterval returns 16) to limit how often ambulances are ticked.
Fields
-
private EndFrameBarrier m_EndFrameBarrier
Reference to the EndFrameBarrier system used to create a parallel EntityCommandBuffer for making structural changes safely at end of frame. -
private PathfindSetupSystem m_PathfindSetupSystem
Reference to the system used to enqueue pathfinding setup requests (provides the m_PathfindQueue). -
private SimulationSystem m_SimulationSystem
Reference to the SimulationSystem used to query the current simulation frame index and to obtain random seeds. -
private EntityQuery m_VehicleQuery
Query used to select ambulance entities processed by this system (includes filters like excluding Deleted, Temp, TripSource, OutOfControl). -
private EntityArchetype m_HealthcareRequestArchetype
Archetype used when creating new healthcare request entities (ServiceRequest + HealthcareRequest + RequestGroup). -
private EntityArchetype m_HandleRequestArchetype
Archetype used for handle-request events (HandleRequest + Event). -
private ComponentTypeSet m_MovingToParkedCarRemoveTypes
Set of component types that are removed from a vehicle when it transitions from moving to parked state (e.g., Moving, TransformFrame, PathElement, PathInformation, ServiceDispatch, etc.). -
private ComponentTypeSet m_MovingToParkedAddTypes
Set of component types that are added when a vehicle becomes parked (e.g., ParkedCar, Stopped, Updated). -
private TypeHandle __TypeHandle
Internal container for the various Entity/Component/Buffer type handles and ComponentLookup/BufferLookup instances used by the AmbulanceTickJob. Populated in OnCreateForCompiler and used in OnUpdate to create the job's handles.
Properties
- None (no public properties exposed by this system).
Constructors
public AmbulanceAISystem()
Default constructor. Marked with [Preserve] attribute in the source to avoid stripping. Initialization of references and queries is performed in OnCreate.
Methods
-
public override int GetUpdateInterval(SystemUpdatePhase phase)
Returns 16 in source; the system is scheduled to update once every 16 simulation ticks (coarse-grained update). -
public override int GetUpdateOffset(SystemUpdatePhase phase)
Returns 0 in source; no offset is applied. -
protected override void OnCreate()
Sets up system references and entity query, creates required archetypes and ComponentTypeSets, and calls RequireForUpdate(m_VehicleQuery) to ensure the system only runs when ambulance entities exist. Retrieves EndFrameBarrier, PathfindSetupSystem and SimulationSystem instances. -
protected override void OnUpdate()
Creates and schedules the AmbulanceTickJob (Burst compiled) using the pre-populated type handles and lookups. The job gets a parallel writer command buffer from m_EndFrameBarrier, and a pathfind setup queue writer from m_PathfindSetupSystem. Adds the job handle to PathfindSetupSystem and EndFrameBarrier so the job producers are tracked. -
protected override void OnCreateForCompiler()
Internal helper used by generated code; assigns queries and type handles by calling __AssignQueries and __TypeHandle.__AssignHandles. -
private void __AssignQueries(ref SystemState state)
Internal method used at compile-time to assign any internal queries (generated code stub). -
Nested struct:
AmbulanceTickJob : IJobChunk
(Burst-compiled) - Role: Processes chunks of ambulance entities in parallel. It contains many read-only and read/write component handles and lookups, a parallel command buffer, and a parallel pathfind-setup queue.
- Main per-entity flow implemented in Tick(...):
- CheckServiceDispatches: Validate/trim dispatch queue and set Dispatched flag when applicable.
- RequestTargetIfNeeded: Periodically create a HealthcareRequest if ambulance has a pending target request but no registered request exists.
- ResetPath: Reinitialize path elements when an updated path is consumed and update car flags/parking status/effects.
- Path validity checks: If a target entity no longer exists or pathfinding failed, the vehicle is either deleted (if stuck/returning) or sent back to depot.
- Arrival handling: When an ambulance reaches path end / parking space / is at target, it handles unloading patients, parking, selecting next dispatch, or returning to depot.
- Parking and movement: ParkCar sets parked components and fixes parking location; StopVehicle/StartVehicle toggle movement components and ensure relevant lanes are marked PathfindUpdated.
- LoadPatients/UnloadPatients handle boarding/disembarking logic tied to HealthProblem and CurrentTransport/CurrentBuilding components (including random critical state decisions).
- FindNewPath constructs PathfindParameters and enqueues path setup via VehicleUtils/PathfindSetupSystem when a new path is required (takes into account flags like FindHospital, Dispatched, Transporting, Critical, owner-vs-foreign-target).
- SelectDispatch consumes service dispatches, validates request targets, may append precomputed path elements from the healthcare request to the vehicle's path, and sets path/flags accordingly.
- CheckParkingSpace validates/claims parking curves and parking spaces on the path.
- ResetPath recalculates ambulance.m_PathElementTime, resets parking lane status and effects, and propagates target/destination changes to passengers.
-
Notable helper methods inside the job (signatures trimmed):
- void Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
- private void Tick(...)
- private void ParkCar(int jobIndex, Entity entity, Owner owner, ref Ambulance ambulance, ref Car car, ref CarCurrentLane currentLane)
- private void StopVehicle(int jobIndex, Entity entity, ref CarCurrentLane currentLaneData)
- private void StartVehicle(int jobIndex, Entity entity, ref CarCurrentLane currentLaneData)
- private bool LoadPatients(...)
- private bool UnloadPatients(DynamicBuffer
passengers, ref Ambulance ambulance) - private void FindNewPath(...)
- private Entity FindDistrict(Entity building)
- private void TransportToHospital(...)
- private void ReturnToDepot(...)
- private void CheckServiceDispatches(...)
- private void RequestTargetIfNeeded(int jobIndex, Entity entity, ref Ambulance ambulance)
- private bool SelectDispatch(...)
- private void CheckParkingSpace(...)
- private void ResetPath(...)
-
Notes: The job uses multiple ComponentLookup and BufferLookup instances (e.g., m_PathElements is NativeDisableParallelForRestriction) and requires careful interaction with the command buffer and pathfind queue. Most vehicle state transitions are implemented by adding/removing components via the parallel writer.
Usage Example
// Obtain the system from the default world (common usage in mods/tools)
var ambulanceSystem = World.DefaultGameObjectInjectionWorld
.GetExistingSystemManaged<Game.Simulation.AmbulanceAISystem>();
if (ambulanceSystem != null)
{
// Query the configured update interval (system updates every 16 ticks by default)
int interval = ambulanceSystem.GetUpdateInterval(SystemUpdatePhase.Simulation);
UnityEngine.Debug.Log($"AmbulanceAISystem update interval: {interval}");
}
// You typically don't call OnUpdate manually. To affect ambulances from a mod,
// create/modify components (e.g., ServiceRequest, HealthcareRequest, ServiceDispatch)
// on relevant entities and the system will pick them up on its scheduled ticks.
Notes for modders: - The system depends on many internal game component types (HealthProblem, HealthcareRequest, ServiceDispatch, PathElement, etc.). Changing or creating requests must match the expected archetypes and component semantics. - Because the system uses a parallel command buffer (via EndFrameBarrier), structural changes are safe but deferred — expect changes to be applied at the end of the frame. - To influence pathfind behavior, consider interacting with PathfindSetupSystem queues or by setting appropriate component data (Targets, PathElements) on involved entities.