Skip to content

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 (read-only), BufferTypeHandle (read-only), BufferTypeHandle (write), ComponentLookup and BufferLookup accesses for prefab-related data, and a DynamicBuffer read-only singleton for budgets. - The job is implemented with an explicit Execute(in ArchetypeChunk, ...) and also provides the IJobChunk.Execute wrapper.

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).