Skip to content

Game.Simulation.AgingSystem

Assembly: Assembly-CSharp
Namespace: Game.Simulation

Type: class

Base: GameSystemBase

Summary:
AgingSystem is an ECS system that advances citizen ages based on in-game days and handles the transitions and side-effects when citizens become teens, adults, or elderly. It schedules a parallel IJobChunk (AgingJob) over household entities and uses NativeCounters to accumulate how many citizens crossed each age boundary during the update. The job may remove or add components (via an EndFrameBarrier command buffer) such as Student, TravelPurpose, Worker, and LeaveHouseholdTag to reflect the new citizen state. The system exposes debug watchable counters (NativeValue) and a static flag to force aging every update for testing.


Fields

  • private EntityQuery m_HouseholdQuery
    Holds the query used to select households (entities with Household buffer, excluding Deleted and Temp). Required for system updates.

  • private EntityQuery m_TimeDataQuery
    Query to get the singleton TimeData (used to determine current day).

  • private SimulationSystem m_SimulationSystem
    Reference to the SimulationSystem used to access the current simulation frame index.

  • private EndFrameBarrier m_EndFrameBarrier
    Barrier used to create an EntityCommandBuffer. Changes made by the job are applied at the end of the frame via this barrier.

  • public static bool s_DebugAgeAllCitizens
    Static debug flag. When true, the job ages all citizens every update frame regardless of shared UpdateFrame scheduling. Useful for testing.

  • [DebugWatchValue] public NativeValue<int> m_BecomeTeen
    Debug-watchable counter value for how many citizens became teens (updated from m_BecomeTeenCounter).

  • [DebugWatchValue] public NativeValue<int> m_BecomeAdult
    Debug-watchable counter value for how many citizens became adults (updated from m_BecomeAdultCounter).

  • [DebugWatchValue] public NativeValue<int> m_BecomeElder
    Debug-watchable counter value for how many citizens became elderly (updated from m_BecomeElderCounter).

  • public NativeCounter m_BecomeTeenCounter
    NativeCounter used by the parallel job to count citizens becoming teens. Converted to Concurrent for job use.

  • public NativeCounter m_BecomeAdultCounter
    NativeCounter used by the parallel job to count citizens becoming adults. Converted to Concurrent for job use.

  • public NativeCounter m_BecomeElderCounter
    NativeCounter used by the parallel job to count citizens becoming elderly. Converted to Concurrent for job use.

  • private TypeHandle __TypeHandle
    Internal struct storing type handles used to access component and buffer types inside the job. Assigned during OnCreateForCompiler.

Properties

  • (none public)
    The system exposes no public C# properties. It relies on fields and the scheduled job for behavior.

Constructors

  • public AgingSystem()
    Default constructor. The system uses OnCreate to set up queries, counters, and required systems.

Methods

  • public override int GetUpdateInterval(SystemUpdatePhase phase)
    Returns the interval (in frames) at which this system should update. Implementation uses a formula: 262144 / (kUpdatesPerDay * 16). With kUpdatesPerDay = 1, this yields the configured interval used by the simulation update scheduling.

  • [Preserve] protected override void OnCreate()
    Initializes the system: obtains SimulationSystem and EndFrameBarrier references, creates entity queries (household/time), allocates Persistent NativeValue counters and NativeCounter instances, and calls RequireForUpdate on the household query to enable the system only when households exist.

  • [Preserve] protected override void OnDestroy()
    Disposes NativeValue and NativeCounter resources to avoid leaks.

  • public static int GetTeenAgeLimitInDays()
    Returns the day threshold (21) at which a Child becomes a Teen. These age limits are static constants and can be called by other systems or mods.

  • public static int GetAdultAgeLimitInDays()
    Returns the day threshold (36) at which a Teen becomes an Adult.

  • public static int GetElderAgeLimitInDays()
    Returns the day threshold (84) at which an Adult becomes Elderly.

  • [Preserve] protected override void OnUpdate()
    Main scheduling method. Builds an AgingJob instance, fills type handles and shared data (current simulation frame, TimeData, updateFrame index, command buffer, debug flag), schedules it in parallel over the household query, and registers the resulting job handle with the EndFrameBarrier so command buffer changes are applied after jobs complete.

Important behaviors inside the job: - Uses TimeSystem.GetDay to compute a citizen's age in days. - For each household buffer entry, checks each citizen and compares age-in-days against age limit thresholds (using the static Get*AgeLimitInDays methods). - When a citizen crosses an age boundary: - Child -> Teen: increment m_BecomeTeenCounter, set Citizen age to Teen, remove Student component via command buffer if present, and add StudentsRemoved component to the school entity. - Teen -> Adult: increment m_BecomeAdultCounter, set age to Adult, remove Student if present, add LeaveHouseholdTag via command buffer so household will update. - Adult -> Elderly: increment m_BecomeElderCounter, set age to Elderly, remove Worker component via command buffer, and remove TravelPurpose if citizen is currently going to work or working. - Skips chunks that are not scheduled for this update based on the UpdateFrame shared component unless s_DebugAgeAllCitizens == true.

  • private void __AssignQueries(ref SystemState state)
    Compiler helper used during OnCreateForCompiler (internal). In this decompiled implementation it only creates and disposes an EntityQueryBuilder; real generated code sets up queries.

  • protected override void OnCreateForCompiler()
    Compiler/runtime helper invoked to assign type handles and queries for burst/compiled usage. Calls __AssignQueries and assigns handles inside __TypeHandle.

Nested types of note: - private struct AgingJob : IJobChunk
- Burst-compiled job that iterates household chunks, reads HouseholdCitizen buffers, reads/writes Citizen components, checks/updates ages, updates counters, and enqueues structural changes through a parallel EntityCommandBuffer. - Uses ComponentLookup and BufferTypeHandle to access components inside the job. - Contains a helper LeaveSchool to remove Student component and signal StudentsRemoved on the school entity. - Honors m_DebugAgeAllCitizens to optionally bypass shared UpdateFrame filtering.

  • private struct TypeHandle
  • Holds SharedComponentTypeHandle, BufferTypeHandle, and ComponentLookup handles used by the job and assigned via __AssignHandles.

Usage Example

// Example: force aging every update (debug) and inspect counters in OnCreate/OnUpdate
[Preserve]
protected override void OnCreate()
{
    base.OnCreate();

    // Enable debug mode to age all citizens on every update (testing only)
    Game.Simulation.AgingSystem.s_DebugAgeAllCitizens = true;

    // The base system already creates and configures counters; you can read
    // m_BecomeTeen, m_BecomeAdult, m_BecomeElder in a debug display or profiler.
}

// Example: reading static age limits
int teenLimit = Game.Simulation.AgingSystem.GetTeenAgeLimitInDays();    // 21
int adultLimit = Game.Simulation.AgingSystem.GetAdultAgeLimitInDays();  // 36
int elderLimit = Game.Simulation.AgingSystem.GetElderAgeLimitInDays();  // 84

Notes and Modding Tips: - If you add or alter citizen lifecycle behavior, consider the job's use of EndFrameBarrier and the fact that structural changes are deferred via the command buffer; attempting to change components directly inside jobs is prohibited. - The system relies on time expressed in days (TimeData / TimeSystem.GetDay). If you change time scaling, ensure age thresholds remain appropriate. - The NativeCounters are used to safely increment counts from parallel jobs; after scheduling you'll typically read back the totals on the main thread (these are stored in NativeValue for debug display). - s_DebugAgeAllCitizens is global and affects all instances — only enable it for testing.