Game.ResidentialDemandSystem
Assembly: Assembly-CSharp
Namespace: Game.Simulation
Type: class
Base: GameSystemBase, IDefaultSerializable, ISerializable
Summary:
ResidentialDemandSystem is an ECS-managed game system that computes residential demand for Cities: Skylines 2. It periodically (every 16 ticks with an update offset) runs a Burst-compiled job (UpdateResidentialDemandJob) that collects data from multiple supporting systems (taxes, study positions, workplaces, household counts, residential property counts, city population, zone prefabs, etc.), calculates household and per-density building demand (low/medium/high), populates demand factor arrays used for debugging/UI, and enqueues a ResidentialDemand trigger when appropriate. The system stores the last-computed demands and exposes readers for other systems/jobs via NativeContainers and JobHandles.
Fields
-
public static readonly int kMaxFactorEffect
Maximum cap used for some factor effects (value = 15). -
private TaxSystem m_TaxSystem
Reference to the TaxSystem used to read residential tax rates. -
private CountStudyPositionsSystem m_CountStudyPositionsSystem
System used to count study (student) positions by education. -
private CountWorkplacesSystem m_CountWorkplacesSystem
System used to query free/total workplaces across simple/complex types. -
private CountHouseholdDataSystem m_CountHouseholdDataSystem
Provides household counts, homelessness and unemployment rates. -
private CountResidentialPropertySystem m_CountResidentialPropertySystem
Provides counts of free and total residential properties by density. -
private CitySystem m_CitySystem
Provides the city entity reference. -
private TriggerSystem m_TriggerSystem
Used to enqueue TriggerAction instances (e.g., ResidentialDemand trigger). -
private EntityQuery m_DemandParameterGroup
EntityQuery to fetch DemandParameterData. -
private EntityQuery m_UnlockedZonePrefabQuery
EntityQuery to enumerate unlocked Zone prefabs (ZoneData + ZonePropertiesData). -
private EntityQuery m_GameModeSettingQuery
EntityQuery to fetch ModeSettingData (game mode tweaks to demand weighting). -
private NativeValue<int> m_HouseholdDemand
Persistent NativeValue holding the current household demand (written by the job). -
private NativeValue<int3> m_BuildingDemand
Persistent NativeValue holding the current per-density building demand (low/med/high). -
private NativeArray<int> m_LowDemandFactors
EnumArray-sized NativeArray storing individual demand factor contributions for low density (debug/UI). -
private NativeArray<int> m_MediumDemandFactors
EnumArray-sized NativeArray storing individual demand factor contributions for medium density (debug/UI). -
private NativeArray<int> m_HighDemandFactors
EnumArray-sized NativeArray storing individual demand factor contributions for high density (debug/UI). -
private JobHandle m_WriteDependencies
Latest JobHandle that writers produce — used to expose dependency to readers. -
private JobHandle m_ReadDependencies
Combined JobHandle of readers; used to combine with new scheduled jobs. -
private int m_LastHouseholdDemand
Cached value of the last-known household demand (used by property). -
private int3 m_LastBuildingDemand
Cached value of the last-known building demand per density. -
private float2 m_ResidentialDemandWeightsSelector
Weight selector used to convert factor floats into integer contributions; comes from ModeSettingData or defaults to (1,1). -
private TypeHandle __TypeHandle
Internal struct holding ComponentLookup handles assigned at creation for safe access in jobs.
Properties
-
public int householdDemand { get; }
Returns the last computed household demand (m_LastHouseholdDemand). This value is updated each OnUpdate when demand is recomputed. -
public int3 buildingDemand { get; }
Returns the last computed per-density building demand (m_LastBuildingDemand). int3 components correspond to low, medium, high densities.
Constructors
public ResidentialDemandSystem()
Default constructor. The system initializes internal references and Native containers during OnCreate. No custom parameters.
Methods
-
public override int GetUpdateInterval(SystemUpdatePhase phase)
Returns the update interval (16). Controls how often the system recalculates demand. -
public override int GetUpdateOffset(SystemUpdatePhase phase)
Returns the update offset (10). Used by scheduler to offset when the system runs relative to other systems. -
public NativeArray<int> GetLowDensityDemandFactors(out JobHandle deps)
Returns the NativeArray for low-density demand factors and outputs a JobHandle (deps) representing writers' dependencies. Callers must respect the JobHandle. -
public NativeArray<int> GetMediumDensityDemandFactors(out JobHandle deps)
Same as above for medium-density factors. -
public NativeArray<int> GetHighDensityDemandFactors(out JobHandle deps)
Same as above for high-density factors. -
public void AddReader(JobHandle reader)
Add a reader dependency so the system can combine it when scheduling. Combines with internal m_ReadDependencies. -
protected override void OnGameLoaded(Context serializationContext)
Called when a saved game is loaded. Reads ModeSettingData (if present and enabled) to set m_ResidentialDemandWeightsSelector; otherwise sets default (1,1). -
protected override void OnCreate()
Sets up EntityQueries, fetches or creates references to dependent systems (tax, workplaces, counts, triggers, city system), and allocates persistent Native containers: m_HouseholdDemand, m_BuildingDemand, and the three demand factor arrays. Also sets default weight selector. -
protected override void OnDestroy()
Disposes the persistent NativeValue and NativeArray containers to avoid leaks and calls base.OnDestroy(). -
public void SetDefaults(Context context)
Resets demand values and factor arrays to zero and clears cached last values — often used on new game or reset. -
public void Serialize<TWriter>(TWriter writer) where TWriter : IWriter
Writes current demand state and demand factor arrays to the save writer: household demand, building demand (int3), factor length and arrays, last cached demand values. Used by the save system. -
public void Deserialize<TReader>(TReader reader) where TReader : IReader
Reads serialized state. Includes version compatibility handling: - For versions before residentialDemandSplit, a single building demand int is read and split across densities.
- For earlier factor-count versions, it reads a shorter factor array and copies into the internal arrays safely.
-
Restores last cached demand values accordingly.
-
protected override void OnUpdate()
Main runtime method. If DemandParameterData is present, it: - Backs up last demand values,
- Builds an UpdateResidentialDemandJob with data fetched asynchronously (unlocked zone prefabs, demand parameters list, study positions, workplace counts, household/property counts, tax rates, population, etc.),
- Schedules the job (Burst) combining existing dependencies and readers,
-
Stores the resulting write dependency in m_WriteDependencies and registers readers with dependent systems (study positions, taxes, trigger buffer writer, etc.). The scheduled job computes all demand math and enqueues a ResidentialDemand trigger when appropriate.
-
private void __AssignQueries(ref SystemState state)
Internal helper for compiler-inserted query assignment (kept for compatibility with generated code). -
protected override void OnCreateForCompiler()
Internal initialization that assigns queries and component lookups to __TypeHandle.
Inner types:
- UpdateResidentialDemandJob (private struct, BurstCompile, implements IJob)
Core job that performs the demand calculation. Highlights: - Receives read-only lists/lookups for unlocked zone prefabs, populations, zone data/properties, demand parameters, study positions, tax rates, and unemployment rate.
- Receives value/arrays to write: m_HouseholdDemand, m_BuildingDemand and the three m_*DemandFactors arrays.
- Computes which residential densities are unlocked, retrieves population and demand parameters, and computes multiple factor contributions:
- Population smoothing (reduces demand as population grows),
- Happiness effect,
- Tax effect across tax brackets,
- Homelessness effect (with caps),
- Available workplace effects for simple/complex workplaces,
- Student (study positions) effect,
- Unemployment effect.
- Uses GetFactorValue to convert float factor values into integer contributions using m_ResidentialDemandWeightsSelector (different weight for negative vs positive values).
- Computes household demand (clamped to 200) and per-density building demand (combining household demand halves, property shortages, and factor sums).
- Writes factor arrays for each density to allow debugging/UI introspection.
- Enqueues a TriggerAction(TriggerType.ResidentialDemand) with a value representing relative demand if residential properties exceed thresholds.
-
GetFactorValue(factorValue, weightSelector) helper multiplies factor by weightSelector.y when factor >= 0, weightSelector.x when factor < 0.
-
TypeHandle (private struct)
Holds ComponentLookup instances that are assigned in OnCreateForCompiler and used to get read-only component lookups for jobs.
Usage Example
Example: reading the computed demands from another managed system (or mod code) and getting factor arrays safely.
protected override void OnUpdate()
{
base.OnUpdate();
// Resolve the system (example inside another system)
var resDemandSystem = World.GetOrCreateSystemManaged<ResidentialDemandSystem>();
// Get last computed values (cheap direct properties)
int households = resDemandSystem.householdDemand;
int3 buildings = resDemandSystem.buildingDemand;
// If you need the factor arrays inside a job, request the JobHandle
JobHandle deps;
NativeArray<int> lowFactors = resDemandSystem.GetLowDensityDemandFactors(out deps);
// Combine deps with your job scheduling to respect read/write ordering.
}
Notes for modders: - Respect JobHandles returned by Get*DemandFactors and AddReader to avoid race conditions. - The system reads ModeSettingData to apply alternative weighting; mods can provide or alter ModeSettingData to affect demand weighting. - TriggerAction enqueued by the job allows UI/hud or other systems to react to residential demand changes.