Skip to content

Game.SpawnableAmbienceSystem

Assembly:
Namespace: Game.Simulation

Type: class

Base: GameSystemBase

Summary:
SpawnableAmbienceSystem collects "group ambience" contributions from spawnable entities in the world (buildings with renters, trees, and prefabs that emit ambience) and applies them into the ZoneAmbienceSystem map. It uses Burst-compiled jobs and a NativeParallelQueue to gather contributions in parallel from two source jobs (spawnables and ambience emitters), then applies accumulated effects to ZoneAmbienceCell accumulators. The system runs on a coarse update interval derived from kUpdatesPerDay and integrates with the simulation's update-frame filtering to only process a subset of entities each tick.

Nested/job types: - GroupAmbienceEffect — small POD struct used to enqueue ambience contributions (type, amount, cell index). - SpawnableAmbienceJob (IJobChunk) — inspects spawnables (buildings/trees), computes ambience amount and enqueues GroupAmbienceEffect entries. - EmitterAmbienceJob (IJobChunk) — inspects AmbienceEmitter prefabs and enqueues effects based on AmbienceEmitterData. - ApplyAmbienceJob (IJobParallelFor) — reads the queue partitions and applies contributions to the ZoneAmbienceSystem map. - TypeHandle — helper struct storing ComponentTypeHandle/BufferTypeHandle/ComponentLookup instances and assigning them from SystemState.


Fields

  • public static readonly int kUpdatesPerDay
  • Constant controlling how many update slices are considered a "day" for this system (value: 128). Used to compute the system's update interval.

  • private SimulationSystem m_SimulationSystem

  • Cached reference to the SimulationSystem used to obtain the current global frameIndex and other simulation state.

  • private ZoneAmbienceSystem m_ZoneAmbienceSystem

  • Cached reference to the ZoneAmbienceSystem where ambience contributions are written.

  • private EntityQuery m_SpawnableQuery

  • Query that targets spawnable entities (buildings with renters and trees) filtered by UpdateFrame and excluding removed/temporary entities.

  • private EntityQuery m_EmitterQuery

  • Query that targets AmbienceEmitter prefabs (component composition: AmbienceEmitter, Transform, PrefabRef; excludes Temp/Deleted).

  • private TypeHandle __TypeHandle

  • Internal holder for the ComponentTypeHandle/BufferTypeHandle/ComponentLookup objects used by the jobs. Populated in OnCreateForCompiler / __AssignHandles.

Properties

  • (none public)
  • This system does not expose properties; it operates via overridden lifecycle methods and internal fields.

Constructors

  • public SpawnableAmbienceSystem()
  • Default constructor. The system relies on OnCreate to initialize required queries and cached systems.

Methods

  • public override int GetUpdateInterval(SystemUpdatePhase phase)
  • Returns the integer update interval used by the base system scheduling. Computed as 262144 / (kUpdatesPerDay * 16). With kUpdatesPerDay = 128, this evaluates to 128. Controls how frequently the system runs relative to the simulation.

  • [Preserve] protected override void OnCreate()

  • Initializes the system: acquires SimulationSystem and ZoneAmbienceSystem, builds the spawnable and emitter EntityQueries, and performs an assertion. The spawnable query targets building renter updates and tree update frames while excluding abandoned/destroyed/deleted/temp entities. The emitter query targets AmbienceEmitter prefabs.

  • [Preserve] protected override void OnUpdate()

  • Main runtime logic:

    • Compute the per-slice updateFrame using SimulationUtils.GetUpdateFrame.
    • Reset and set a shared-component filter on m_SpawnableQuery to process only a slice of spawnable entities.
    • Create a NativeParallelQueue sized relative to JobsUtility.JobWorkerCount.
    • Schedule SpawnableAmbienceJob (parallel IJobChunk) to enqueue ambience from spawnables.
    • Schedule EmitterAmbienceJob (parallel IJobChunk) to enqueue ambience from emitters; chained after spawnable job.
    • Schedule ApplyAmbienceJob (IJobParallelFor) over queue.HashRange to apply queued contributions into the ZoneAmbienceSystem map (obtained via m_ZoneAmbienceSystem.GetMap).
    • Register the ApplyAmbienceJob as a writer to m_ZoneAmbienceSystem (m_ZoneAmbienceSystem.AddWriter).
    • Dispose the NativeParallelQueue with the appropriate dependency.
    • Update the base.Dependency to include job scheduling where appropriate.
  • Notes on job behavior:

    • SpawnableAmbienceJob: if a building prefab has GroupAmbienceData and BuildingData, it computes contribution amount using renter count, lot size and building efficiency; otherwise (e.g., trees) it enqueues a default Forest contribution of amount 1. It maps world position to a cell index and uses queue.HashRange to compute an enqueue bucket.
    • EmitterAmbienceJob: reads PrefabRef and Transform, checks AmbienceEmitterData for intensity and maps emitter position to the same zone cell space, enqueuing contributions.
    • ApplyAmbienceJob: iterates over queue partitions and calls ZoneAmbienceCell.m_Accumulator.AddAmbience(type, amount) for each enqueued GroupAmbienceEffect.
  • [MethodImpl(MethodImplOptions.AggressiveInlining)] private void __AssignQueries(ref SystemState state)

  • Compiler helper that currently instantiates and disposes a temporary EntityQueryBuilder. Present to satisfy generated/compile-time needs.

  • protected override void OnCreateForCompiler()

  • Compiler-time initialization: calls __AssignQueries and __TypeHandle.__AssignHandles to populate type handle fields for job scheduling.

Usage Example

[Preserve]
protected override void OnCreate()
{
    base.OnCreate();
    // cache systems
    m_SimulationSystem = base.World.GetOrCreateSystemManaged<SimulationSystem>();
    m_ZoneAmbienceSystem = base.World.GetOrCreateSystemManaged<ZoneAmbienceSystem>();

    // build queries (simplified; see source for full query composition)
    m_SpawnableQuery = GetEntityQuery(new EntityQueryDesc {
        All = new[] { ComponentType.ReadOnly<BuildingCondition>(), ComponentType.ReadOnly<UpdateFrame>(), ComponentType.ReadOnly<Renter>() },
        Any = new[] { ComponentType.ReadOnly<ResidentialProperty>(), ComponentType.ReadOnly<Efficiency>() },
        None = new[] { ComponentType.ReadOnly<Abandoned>(), ComponentType.ReadOnly<Destroyed>(), ComponentType.ReadOnly<Deleted>(), ComponentType.ReadOnly<Temp>() }
    }, new EntityQueryDesc {
        All = new[] { ComponentType.ReadOnly<Tree>(), ComponentType.ReadOnly<UpdateFrame>() },
        None = new[] { ComponentType.ReadOnly<Owner>(), ComponentType.ReadOnly<Deleted>(), ComponentType.ReadOnly<Destroyed>(), ComponentType.ReadOnly<Temp>() }
    });

    m_EmitterQuery = GetEntityQuery(
        ComponentType.ReadOnly<AmbienceEmitter>(),
        ComponentType.ReadOnly<Transform>(),
        ComponentType.ReadOnly<PrefabRef>(),
        ComponentType.Exclude<Temp>(),
        ComponentType.Exclude<Deleted>()
    );
}

Notes and implementation details: - The system uses a NativeParallelQueue partitioned by HashRange to allow threads to enqueue concurrently; ApplyAmbienceJob then iterates per-partition to apply to the zone map. - ZoneAmbienceSystem.kTextureSize and CellMapSystem.GetCell are used to convert world positions to per-cell indexes; out-of-range cells are ignored. - Jobs are Burst-compiled for performance; component handles and lookups are provided via the TypeHandle helper to avoid redundant allocations at runtime. - The system integrates with the Simulation update-frame system, processing only a fraction of spawnables each system tick (via UpdateFrame shared component filtering).