Skip to content

Game.CommercialDemandSystem

Assembly: Assembly-CSharp (game runtime)
Namespace: Game.Simulation

Type: class

Base: GameSystemBase, IDefaultSerializable, ISerializable

Summary:
CommercialDemandSystem is responsible for calculating commercial resource demand and related metrics (company demand, building demand, per-resource demand, consumption and free property counts) for the city's commercial economy. It collects information from commercial properties, commercial companies, population and tourism data, tax rates and various game parameters, then schedules a Burst-compiled IJob (UpdateCommercialDemandJob) to compute demand values into NativeArrays that other systems can read. The system persists demand state, supports serialization/deserialization across save versions, and exposes read-only debug properties for the last computed company and building demand values.


Fields

  • private ResourceSystem m_ResourceSystem
    Reference to the ResourceSystem; used to obtain resource prefabs and related data.

  • private TaxSystem m_TaxSystem
    Reference to the TaxSystem; used to fetch commercial tax rates used in demand calculations.

  • private CountCompanyDataSystem m_CountCompanyDataSystem
    Reference used to read aggregated commercial company production/availability data.

  • private CountHouseholdDataSystem m_CountHouseholdDataSystem
    Reference used only to register dependency readers (ensuring correct scheduling).

  • private CitySystem m_CitySystem
    Provides access to city-wide components (e.g., Population, Tourism Entity).

  • private EntityQuery m_EconomyParameterQuery
    Query to require economy parameters to exist for the system to run.

  • private EntityQuery m_DemandParameterQuery
    Query to fetch DemandParameterData singleton used by the job.

  • private EntityQuery m_CommercialQuery
    Query for commercial properties (PrefabRef, CommercialProperty, excluding abandoned/destroyed/etc.) used to enumerate market listings.

  • private EntityQuery m_CommercialProcessDataQuery
    Query used to require commercial process/service company data to be present.

  • private EntityQuery m_UnlockedZoneDataQuery
    Query to read unlocked ZoneData (to detect whether commercial area exists).

  • private EntityQuery m_GameModeSettingQuery
    Query to read optional ModeSettingData (affects commercial tax offset if enabled).

  • private NativeValue<int> m_CompanyDemand
    Writable NativeValue storing intermediate company demand (used by job and serialized).

  • private NativeValue<int> m_BuildingDemand
    Writable NativeValue storing intermediate building demand (used by job and serialized).

  • [EnumArray(typeof(DemandFactor))][DebugWatchValue] private NativeArray<int> m_DemandFactors
    NativeArray of demand factor buckets (18 entries by default). Used for debugging and aggregated demand factor outputs.

  • [ResourceArray][DebugWatchValue] private NativeArray<int> m_ResourceDemands
    Per-resource demand values (NativeArray sized to EconomyUtils.ResourceCount).

  • [ResourceArray][DebugWatchValue] private NativeArray<int> m_BuildingDemands
    Per-resource building demand (how many buildings should be built for each resource).

  • [ResourceArray][DebugWatchValue] private NativeArray<int> m_Consumption
    Per-resource consumption counters (maintained and serialized).

  • [ResourceArray][DebugWatchValue] private NativeArray<int> m_FreeProperties
    Per-resource count of free properties able to sell a given resource.

  • [DebugWatchDeps] private JobHandle m_WriteDependencies
    JobHandle representing the scheduled write dependency for readers.

  • private JobHandle m_ReadDependencies
    Combined read dependencies added by readers calling AddReader.

  • private int m_LastCompanyDemand
    Stores last tick's computed company demand (for debug property).

  • private int m_LastBuildingDemand
    Stores last tick's computed building demand (for debug property).

  • private float m_CommercialTaxEffectDemandOffset
    Optional offset to commercial tax effect on demand (can be modified by game mode settings).

  • private TypeHandle __TypeHandle
    Internal cached ComponentTypeHandle/BufferTypeHandle/ComponentLookup instances packaged into a struct for fast handle assignment.

  • private struct UpdateCommercialDemandJob (nested)
    Burst-compiled IJob that performs the heavy per-frame demand computation on Native data and component lookups. See Methods section for a summary.

  • private struct TypeHandle (nested)
    Internal structure to store and assign component/buffer/lookup handles used by the job.

Properties

  • public int companyDemand { get; } (debug property)
    Read-only debug property exposing m_LastCompanyDemand. Updated each OnUpdate before scheduling the update job.

  • public int buildingDemand { get; } (debug property)
    Read-only debug property exposing m_LastBuildingDemand. Updated each OnUpdate before scheduling the update job.

Constructors

  • public CommercialDemandSystem()
    Default constructor. System initialization occurs in OnCreate; the constructor exists to satisfy managed system instantiation.

Methods

  • public override int GetUpdateInterval(SystemUpdatePhase phase)
    Returns 16 — the system update interval (used by game loop scheduling).

  • public override int GetUpdateOffset(SystemUpdatePhase phase)
    Returns 4 — the update offset used by the scheduler.

  • public NativeArray<int> GetDemandFactors(out JobHandle deps)
    Returns the native array m_DemandFactors and outputs the current write JobHandle (deps) that must be combined by callers before reading.

  • public NativeArray<int> GetResourceDemands(out JobHandle deps)
    Returns m_ResourceDemands and its write dependency.

  • public NativeArray<int> GetBuildingDemands(out JobHandle deps)
    Returns m_BuildingDemands and its write dependency.

  • public NativeArray<int> GetConsumption(out JobHandle deps)
    Returns m_Consumption and its write dependency.

  • public void AddReader(JobHandle reader)
    Register a reader JobHandle so that the system combines read dependencies with its own m_ReadDependencies to ensure proper job ordering.

  • protected override void OnGameLoaded(Context serializationContext)
    Called after the game loads — clears m_Consumption and reads ModeSettingData (if present) to apply any commercial tax effect demand offset from game modes.

  • [Preserve] protected override void OnCreate()
    System initialization:

  • Retrieves references to dependent systems (ResourceSystem, TaxSystem, CountCompanyDataSystem, CountHouseholdDataSystem, CitySystem).
  • Builds EntityQueries used by the system.
  • Allocates persistent Native containers (m_CompanyDemand, m_BuildingDemand, m_DemandFactors, m_ResourceDemands, m_BuildingDemands, m_Consumption, m_FreeProperties).
  • Sets m_CommercialTaxEffectDemandOffset = 0 by default.
  • Calls RequireForUpdate for queries that must exist for the system to run.

  • [Preserve] protected override void OnDestroy()
    Disposes all persistent Native containers and calls base.OnDestroy().

  • public void SetDefaults(Context context)
    Resets all demand and internal arrays to zero and clears last-demand debug values. Called to initialize or reset state.

  • public void Serialize<TWriter>(TWriter writer) where TWriter : IWriter
    Writes out the system state to a writer: company/building demand, demand factors count + values, resource & building demands, consumption, free properties and last demand ints. Handles current in-memory shapes (writes full arrays).

  • public void Deserialize<TReader>(TReader reader) where TReader : IReader
    Reads saved state with backward compatibility handling:

  • Handles older versions where demand factor count differs.
  • Handles whether FishResource (a format tag) exists to read full-length arrays or truncated (legacy 40-length) arrays and zero-filling the remaining slot.
  • Handles older saves prior to companyDemandOptimization where intermediate arrays were serialized differently.
  • Restores m_CompanyDemand, m_BuildingDemand, m_DemandFactors, m_ResourceDemands, m_BuildingDemands, m_Consumption, m_FreeProperties, m_LastCompanyDemand, m_LastBuildingDemand.

  • [Preserve] protected override void OnUpdate()
    Main runtime update:

  • Early-exits if demand/economy parameter singletons are missing.
  • Copies last demand values (m_LastCompanyDemand/m_LastBuildingDemand).
  • Gets aggregated commercial company data from CountCompanyDataSystem (out JobHandle deps).
  • Prepares an UpdateCommercialDemandJob instance with:
    • Chunk list for commercial properties (m_CommercialQuery.ToArchetypeChunkListAsync).
    • Unlocked zone data array.
    • ComponentTypeHandle/BufferTypeHandle/ComponentLookup handles via internal TypeHandle.
    • Resource prefabs, demand parameters, tax rates, city entity, arrays for demands/consumption/free properties, produce capacity/current available/propertyless arrays from aggregated commercial data.
    • m_CommercialTaxEffectDemandOffset (possibly modified by game mode).
  • Schedules the job with JobUtils/CombineDependencies, stores the resulting dependency into m_WriteDependencies and registers read dependencies with other systems (CountHouseholdDataSystem, ResourceSystem, TaxSystem) so they wait on this job when required.

  • private void __AssignQueries(ref SystemState state)
    Internal function used by OnCreateForCompiler to initialize queries for compiler-generated flow; here it effectively ensures query builder initialization (no custom queries declared beyond those created in OnCreate).

  • protected override void OnCreateForCompiler()
    Compiler helper which assigns queries and component handles through __TypeHandle.__AssignHandles.

  • [MethodImpl(MethodImplOptions.AggressiveInlining)] private void __AssignHandles(ref SystemState state) (in TypeHandle)
    Called by OnCreateForCompiler to cache component/buffer/lookup handles used by the scheduled job.

  • Nested: UpdateCommercialDemandJob.Execute() (Burst-compiled)
    Summary of algorithm:

  • Scans unlocked zone data to detect if any commercial zone exists (flag).
  • Initializes per-resource counters (free properties, building demands, resource demands) to zero.
  • Iterates through commercial property archetype chunks:
    • Skips chunks that don't have PropertyOnMarket.
    • For each property (PrefabRef), ensures the prefab has BuildingPropertyData.
    • Skips properties whose renters include commercial companies (occupied by companies).
    • For eligible properties, iterates allowed-sold resources from BuildingPropertyData and increments free property counts for those resources.
  • Computes base resource demand for each commercial resource present in ResourcePrefabs:
    • Applies tax effect: scales demand by factor derived from commercial tax rate and DemandParameterData.
    • For non-lodging resources, computes demand from current available stocks and a population-derived baseline (log-based).
    • For lodging (hotels), uses tourism counts / hotel room requirement to potentially set demand to 100.
    • Adjusts demand by tax multiplier/offset and records a demand factor contribution.
  • Aggregates company demand as average of resource demands (if any), aggregates building demand from resource demands where free properties exceed propertyless count and where commercial zones exist.
  • Populates m_DemandFactors buckets (e.g., retail/service/others) and clamps values; sets defaults (e.g., m_DemandFactors[4] minimums).
  • Writes results back to m_CompanyDemand, m_BuildingDemand, m_ResourceDemands, m_BuildingDemands, m_FreeProperties. Notes: uses EconomyUtils helpers and commercial aggregated company data (produce capacity/current available/propertyless) passed into the job.

Usage Example

[Preserve]
protected override void OnCreate()
{
    base.OnCreate();

    // System obtains other systems and allocates its Native arrays in OnCreate() automatically.
    // If you need to read resource demands from another system, request the array and combine
    // the returned dependency with your reader job.

    JobHandle deps;
    var demands = World.GetExistingSystemManaged<CommercialDemandSystem>().GetResourceDemands(out deps);

    // If scheduling a job that reads these demands:
    // myReaderJobHandle = JobHandle.CombineDependencies(myReaderJobHandle, deps);
}

Notes and tips: - The system schedules a Burst IJob (UpdateCommercialDemandJob) and writes into Native containers. Consumers must call AddReader to register read dependencies or obtain arrays via the Get* methods which return the write JobHandle to chain dependencies properly. - The system respects save-version compatibility — saved demand arrays are read with several legacy-handling branches. - For modding: to affect commercial demand, you can hook into tax system rates, DemandParameterData, ModeSettingData, or provide custom ResourcePrefabs/components. To read live demand values, call GetResourceDemands/GetBuildingDemands/GetDemandFactors and combine the returned JobHandle before accessing the array contents on the main thread.