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