Game.SchoolAISystem
Assembly: Game
Namespace: Game.Simulation
Type: class SchoolAISystem
Base: GameSystemBase
Summary:
SchoolAISystem is an ECS simulation system responsible for updating school buildings and their enrolled students each simulation tick. It schedules a Burst-compiled parallel IJobChunk (SchoolTickJob) that:
- iterates school entities and their student buffers,
- computes average graduation time, average fail/dropout probability, student wellbeing and health based on building efficiency, installed upgrades, city modifiers and fees,
- updates ServiceUsage for the school,
- removes the Student component (and TravelPurpose when appropriate) from citizens who leave an inoperable school.
The system depends on singletons like EconomyParameterData, EducationParameterData and TimeData, and uses CitySystem and EndFrameBarrier to create command buffers for safe structural changes at end-of-frame.
Fields
-
private SimulationSystem m_SimulationSystem
Holds the SimulationSystem instance (used to read the current simulation frame index). -
private CitySystem m_CitySystem
Reference to the CitySystem, used to access the current City entity and city-wide buffers (modifiers, fees). -
private EndFrameBarrier m_EndFrameBarrier
Used to create an EntityCommandBuffer.ParallelWriter to apply structural changes (e.g., removing components) safely at end of frame. -
private EntityQuery m_SchoolQuery
EntityQuery selecting school entities (reads/writes School and Student components, reads PrefabRef, excludes Temp and Deleted). The system requires this query to run. -
private TypeHandle __TypeHandle
Internal struct caching ComponentTypeHandle/BufferTypeHandle/ComponentLookup/BufferLookup instances required by the job. -
private EntityQuery __query_1235104412_0
Internal query for retrieving a singleton EconomyParameterData. -
private EntityQuery __query_1235104412_1
Internal query for retrieving a singleton EducationParameterData. -
private EntityQuery __query_1235104412_2
Internal query for retrieving a singleton TimeData. -
(Nested)
SchoolTickJob
(private struct)
Burst-compiled IJobChunk that performs the per-chunk school & student simulation logic. Contains many fields used by the job: ComponentTypeHandle/BufferTypeHandle/ComponentLookup/BufferLookup, command buffer, parameter data, random seed, city entity and simulation frame. -
(Nested)
TypeHandle
(private struct)
Holds and assigns all component/buffer/lookup handles used by the system/job to avoid repeated lookups each update.
Properties
- None (the system exposes no public properties)
Constructors
public SchoolAISystem()
Default constructor. System is created by the world; initialization is performed in OnCreate/OnCreateForCompiler.
Methods
-
public override int GetUpdateInterval(SystemUpdatePhase phase)
Returns the update interval for this system. In this implementation it returns 256, which controls how often the system runs relative to the simulation frame/tick cadence. -
public override int GetUpdateOffset(SystemUpdatePhase phase)
Returns the update offset for scheduling the system. This implementation returns 96. -
[Preserve] protected override void OnCreate()
OnCreate sets up required systems and queries: - Acquires SimulationSystem, CitySystem and EndFrameBarrier.
- Builds the m_SchoolQuery to select schools and students.
-
Calls RequireForUpdate for the school query and singletons EconomyParameterData, EducationParameterData and TimeData so the system only runs when those exist.
-
[Preserve] protected override void OnUpdate()
Creates and schedules the SchoolTickJob (Burst compiled) as a parallel chunk job: - Fills job fields (type handles, lookups, command buffer, parameter data, random seed, city, frame index).
-
Schedules the job via JobChunkExtensions.ScheduleParallel with m_SchoolQuery and attaches the dependency to the EndFrameBarrier.
-
private void __AssignQueries(ref SystemState state)
Internal helper that constructs internal EntityQuery instances for retrieving singletons (EconomyParameterData, EducationParameterData, TimeData). Used from OnCreateForCompiler. -
protected override void OnCreateForCompiler()
Compiler-time initialization helper: calls __AssignQueries and assigns handles from __TypeHandle. -
(Nested SchoolTickJob)
public void Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
Main per-chunk work method: - Reads prefab refs, installed upgrades, efficiency buffers, school component, service usage buffer, student buffer and performs per-student evaluation.
- Combines prefab school data with installed upgrades when present.
- Computes fee from ServiceFeeSystem and the city fees.
- Iterates students in the school's student buffer (from back to front); for each valid student/citizen:
- Possibly removes students from school if school efficiency is extremely low and a random chance triggers (uses LeaveSchool).
- Otherwise computes graduationProbability (via GraduationSystem), adds to average graduation time and fail probability accumulators, and increases counts for averages.
- Updates the School component fields:
- m_AverageGraduationTime, m_AverageFailProbability
- m_StudentWellbeing and m_StudentHealth (scaled by efficiency and clamped to [-100,100])
- Updates ServiceUsage.m_Usage for the school based on student count and capacity.
- Removes invalid student entities from the buffer.
-
Uses RandomSeed to create per-chunk Random.
-
(Nested SchoolTickJob)
private void LeaveSchool(int chunkIndex, Entity entity)
Helper to remove the Student component from the citizen entity via the parallel command buffer. If the citizen had a TravelPurpose equal to GoingToSchool or Studying, the TravelPurpose component is also removed. -
(Nested SchoolTickJob)
void IJobChunk.Execute(...)
Explicit interface implementation that forwards to the public Execute method.
Usage Example
// The system is managed/created by the World. You can get it like this in other systems/classes:
var schoolSystem = World.DefaultGameObjectInjectionWorld.GetOrCreateSystemManaged<Game.Simulation.SchoolAISystem>();
// Example: inspect when the system is scheduled and the simulation frame it uses:
int interval = schoolSystem.GetUpdateInterval(SystemUpdatePhase.Simulation);
int offset = schoolSystem.GetUpdateOffset(SystemUpdatePhase.Simulation);
// The core logic runs in the nested SchoolTickJob. To add custom behavior,
// you would typically create a separate system that runs before/after SchoolAISystem
// or extend game data (e.g., SchoolData, CityModifier, ServiceFee) that SchoolAISystem reads.
Notes for modders: - The heavy lifting is done in a Burst-compiled IJobChunk; changes to component layouts or names must be mirrored in both the job handles (TypeHandle) and the query. - Structural changes to entities are made via EndFrameBarrier.CreateCommandBuffer(). As a modder, if you need to perform structural modifications in parallel jobs, use the same pattern. - The system expects singletons EconomyParameterData, EducationParameterData and TimeData to be present; ensure these exist when enabling/modifying education-related features.