Game.CityServiceEfficiencySystem
Assembly:
Namespace: Game.Buildings
Type: class
Base: GameSystemBase
Summary:
CityServiceEfficiencySystem is an ECS system used by Cities: Skylines 2 to compute and apply the service-budget-related efficiency factor for buildings that consume city services (i.e., buildings with CityServiceUpkeep). It runs a Burst-compiled IJobChunk (BuildingStateEfficiencyJob) that iterates relevant building chunks, checks whether a building or its installed upgrades require money upkeep, reads the current service budgets (ServiceBudgetData), evaluates an efficiency factor from BuildingEfficiencyParameterData.m_ServiceBudgetEfficiencyFactor, and writes that factor into each building's Efficiency buffer using BuildingUtils.SetEfficiencyFactor. The system schedules work either for all buildings or only changed buildings depending on whether any ServiceBudgetData was updated, minimizing work when budgets are unchanged.
Fields
-
private EntityQuery m_UpdatedBudgetQuery
Used to detect when any ServiceBudgetData entities have been Updated. If not empty, the system will re-evaluate all relevant buildings rather than only changed ones. -
private EntityQuery m_BuildingQuery
EntityQuery matching all buildings with CityServiceUpkeep, PrefabRef and Efficiency (excluding Deleted and Temp). This query is used to update all buildings when budgets changed. -
private EntityQuery m_ChangedBuildingQuery
EntityQuery matching buildings (CityServiceUpkeep + PrefabRef + Efficiency) that were Created or Updated (and not Deleted/Temp). Used to update only changed buildings when budgets are unchanged. -
private TypeHandle __TypeHandle
Holds ComponentTypeHandle / BufferTypeHandle / ComponentLookup / BufferLookup instances used by the job. These handles are assigned in OnCreateForCompiler to allow the job to access components. -
private EntityQuery __query_339138653_0
Internal query used to access the singleton BuildingEfficiencyParameterData (contains the AnimationCurve1 m_ServiceBudgetEfficiencyFactor). -
private EntityQuery __query_339138653_1
Internal query used to access ServiceBudgetData buffer as a singleton buffer (list of service budgets).
Properties
- None
Constructors
public CityServiceEfficiencySystem()
Default constructor. The system uses OnCreate/OnCreateForCompiler to set up queries and type handles; no special construction-time behavior for user code.
Methods
protected override void OnCreate()
: System.Void
Creates entity queries:- m_UpdatedBudgetQuery — to detect Updated ServiceBudgetData
- m_ChangedBuildingQuery — to detect newly created or updated building entities with CityServiceUpkeep
-
m_BuildingQuery — to target all relevant building entities Registers the system's update requirements by calling RequireAnyForUpdate with budget/changed-building queries and RequireForUpdate for ServiceBudgetData and BuildingEfficiencyParameterData.
-
protected override void OnUpdate()
: System.Void
Main update method: - Reads the BuildingEfficiencyParameterData singleton to obtain the service-budget->efficiency AnimationCurve1.
- Builds a BuildingStateEfficiencyJob instance, assigning component handles, lookups, buffer lookups, and the service budgets buffer singleton.
- Chooses either m_BuildingQuery (if budgets were updated) or m_ChangedBuildingQuery (if not) to minimize work.
-
Schedules the job in parallel (Burst-compiled) using JobChunkExtensions.ScheduleParallel and attaches it to the system dependency.
-
protected override void OnCreateForCompiler()
: System.Void
Internal helper called by the generated/compiled pipeline that assigns queries (__AssignQueries) and assigns the TypeHandle handles so the job can access components. -
private void __AssignQueries(ref SystemState state)
: System.Void
Builds the internal queries used to fetch BuildingEfficiencyParameterData and ServiceBudgetData (as a read-only singleton buffer). This method is called from OnCreateForCompiler. -
BuildingStateEfficiencyJob
(private struct) : IJobChunk, BurstCompile
Burst-compiled job that actually modifies each building's Efficiency buffer. Key behavior: - Iterates over chunked entities, retrieves PrefabRef and buffers InstalledUpgrade / Efficiency.
- For each building, attempts to read the ServiceObjectData for its prefab to find which service it belongs to.
- If the building or any of its installed upgrades has money upkeep, it looks up the current budget for that service (from ServiceBudgetData buffer) and evaluates the provided AnimationCurve1 (m_ServiceBudgetEfficiencyFactor) to compute an efficiency multiplier (range from the curve).
- Otherwise sets efficiency to 1.0f.
- Writes the computed factor into the building's Efficiency buffer using BuildingUtils.SetEfficiencyFactor(EfficiencyBuffer, EfficiencyFactor.ServiceBudget, efficiency).
Internal helper methods inside the job:
- private bool HasMoneyUpkeep(Entity prefab)
Checks the prefab's ServiceUpkeepData buffer for any upkeep entries that use Resource.Money.
- private bool HasMoneyUpkeep(DynamicBuffer<InstalledUpgrade> installedUpgrades)
Iterates installed upgrades, resolves each to its PrefabRef (via m_Prefabs lookup), and calls the prefab overload to see if any installed upgrade imposes money upkeep.
- private int GetServiceBudget(Entity service)
Searches the singleton m_ServiceBudgets buffer to find the ServiceBudgetData entry for the given service Entity; returns its m_Budget or 100 if not found.
Notes on job signing:
- The job uses ComponentTypeHandle
Usage Example
// This system runs automatically as part of the game's ECS pipeline.
// Example: ensure BuildingEfficiencyParameterData and ServiceBudgetData singletons exist and have the desired curve/budgets.
// The system will use BuildingEfficiencyParameterData.m_ServiceBudgetEfficiencyFactor to convert a service budget (0..100) into an efficiency factor.
[Preserve]
protected override void OnCreate()
{
base.OnCreate();
// Example: create or update BuildingEfficiencyParameterData singleton
var param = new BuildingEfficiencyParameterData
{
// m_ServiceBudgetEfficiencyFactor must be populated with a curve describing how budget% -> efficiency
m_ServiceBudgetEfficiencyFactor = AnimationCurve1.Linear(0f, 0f, 1f, 1f) // simple example
};
// create/update singleton entity with this data (game code workflow)
}
// The CityServiceEfficiencySystem will then:
// - For each building with CityServiceUpkeep, PrefabRef and Efficiency
// - Check if building or installed upgrades require money upkeep
// - If yes, read the service's current budget from ServiceBudgetData and evaluate the curve
// - Write the result into the building's Efficiency buffer under EfficiencyFactor.ServiceBudget
Additional notes: - The system depends on the presence of BuildingEfficiencyParameterData and ServiceBudgetData; if either is missing the system will not run (RequireForUpdate). - Designed for performance: Burst-compiled chunk job and selective updates (only changed buildings vs. all buildings if budgets updated). - If you are modding budgets or service upkeep, update ServiceBudgetData or building/component states so the system picks up the changes (e.g., mark Updated on budget entities to force a full rebuild).