Game.CrimeStatisticsSystem
Assembly: Assembly-CSharp
Namespace: Game.Simulation
Type: class
Base: GameSystemBase
Summary:
CrimeStatisticsSystem is an ECS game system that collects crime values from building CrimeProducer components, computes an average (normalized by the police configuration maximum), and emits a City statistics event (StatisticType.CrimeRate) containing the computed crime-rate change. The system uses Burst-compiled jobs (an IJobChunk to accumulate per-chunk crime values and an IJob to convert the accumulator result into a StatisticsEvent) and a NativeAccumulator
Fields
-
private CityStatisticsSystem m_CityStatisticsSystem
Holds a reference to the CityStatisticsSystem instance used to obtain the statistics event queue and to register this system as a writer. Populated in OnCreate via World.GetOrCreateSystemManaged(). -
private EntityQuery m_CrimeProducerQuery
EntityQuery that selects building entities with CrimeProducer and PrefabRef components and excludes Deleted and Temp. This query is the target for the AverageCrimeJob and is required for the system to update (RequireForUpdate is called on it in OnCreate). -
private TypeHandle __TypeHandle
Internal struct instance used to cache ComponentTypeHandlefor use in job scheduling. The handle is assigned in OnCreateForCompiler by calling __AssignHandles on this struct. -
private EntityQuery __query_263205583_0
Internal EntityQuery built in __AssignQueries that selects the PoliceConfigurationData singleton (with IncludeSystems option). This is used to read the police configuration values (m_MaxCrimeAccumulation and m_PoliceServicePrefab) during OnUpdate.
Properties
- None (the system exposes no public properties).
Constructors
public CrimeStatisticsSystem()
Default constructor. The system uses standard ECS lifecycle methods (OnCreate / OnUpdate). The constructor is preserved but performs no custom initialization beyond what base class provides.
Methods
-
public override int GetUpdateInterval(SystemUpdatePhase phase)
Returns 8192. This indicates the system's update interval relative to the system phase; the system does not run every single frame. The value 8192 reflects the intended update cadence for crime statistics. -
[Preserve] protected override void OnCreate()
Initializes the system: - Retrieves or creates the CityStatisticsSystem.
- Builds m_CrimeProducerQuery to select Building + CrimeProducer + PrefabRef and exclude Deleted and Temp.
-
Calls RequireForUpdate on the crime producer query and on the PoliceConfigurationData singleton to ensure the system only runs when those pieces exist.
-
[Preserve] protected override void OnUpdate()
Core runtime behavior: - Reads the PoliceConfigurationData singleton (via __query_263205583_0).
- If the configured police service prefab entity does not have an enabled Locked component, schedules the work:
- Creates a NativeAccumulator
(Allocator.TempJob). - Configures and schedules a Burst-compiled AverageCrimeJob (IJobChunk) across m_CrimeProducerQuery. The job reads CrimeProducer components and accumulates normalized crime (m_Crime / m_MaxCrimeAccumulation) into the accumulator as AverageFloat items.
- Obtains the CityStatisticsSystem statistics event queue and a dependent JobHandle (deps).
- Schedules a StatisticsJob (IJob) which reads the accumulator result and enqueues a StatisticsEvent with StatisticType.CrimeRate and the change (100f * average).
- Ensures dependencies are combined, registers this system as a writer via m_CityStatisticsSystem.AddWriter(base.Dependency), and schedules disposal of the accumulator with the combined dependency (averageCrime.Dispose(base.Dependency)).
- Creates a NativeAccumulator
-
If the police prefab is Locked, the system skips scheduling work.
-
private void __AssignQueries(ref SystemState state)
Generated helper that builds the internal EntityQuery for PoliceConfigurationData (with IncludeSystems option) and assigns it to __query_263205583_0. Called from OnCreateForCompiler during system initialization. -
protected override void OnCreateForCompiler()
Compiler-time helper invoked to assign the queries and component type handles used by the generated code, calling __AssignQueries and __TypeHandle.__AssignHandles to populate the internal bookkeeping before runtime.
Nested / Job types (summary)
- AverageCrimeJob (private struct, [BurstCompile], implements IJobChunk)
- Inputs: ComponentTypeHandle
(read-only), float m_MaxCrimeAccumulation, NativeAccumulator .ParallelWriter m_AverageCrime. -
Behavior: Iterates items in each chunk, reads CrimeProducer.m_Crime and accumulates an AverageFloat { m_Count = 1, m_Total = crime / m_MaxCrimeAccumulation } into the accumulator parallel writer. Run in parallel across archetype chunks.
-
StatisticsJob (private struct, [BurstCompile], implements IJob)
- Inputs: NativeAccumulator
m_AverageCrime, NativeQueue m_StatisticsEventQueue. -
Behavior: Reads the accumulator result, computes the average and enqueues a StatisticsEvent with m_Statistic = StatisticType.CrimeRate and m_Change = 100f * average.
-
TypeHandle.__AssignHandles(ref SystemState state)
- Internal method used to request and cache ComponentTypeHandle
for read-only access from the SystemState. Called as part of OnCreateForCompiler.
Notes on safety and performance: - Uses Burst-compiled jobs and a NativeAccumulator to perform a parallel-safe average computation. This minimizes main-thread work and leverages multi-core processing for large numbers of buildings. - The accumulator is allocated with Allocator.TempJob and disposed with the job dependency to avoid leaking. - The system checks a Locked component on the police service prefab to avoid running when the assigned police service is not available or locked. - The statistics event is enqueued on CityStatisticsSystem's queue; the system also registers itself as a writer to guarantee proper ordering.
Usage Example
This system is an automatic ECS system and normally requires no direct invocation. To ensure the system runs, provide the relevant components and singletons:
// Ensure PoliceConfigurationData singleton exists and has appropriate values
// (constructed elsewhere in game initialization)
var policeConfig = new PoliceConfigurationData { m_MaxCrimeAccumulation = 50f, m_PoliceServicePrefab = policePrefabEntity };
entityManager.AddComponentData(singletonEntity, policeConfig);
// Ensure buildings that produce crime have a CrimeProducer component:
entityManager.AddComponentData(buildingEntity, new CrimeProducer { m_Crime = 5f });
// CrimeStatisticsSystem will pick up CrimeProducer components via its query,
// compute the normalized average crime (crime / m_MaxCrimeAccumulation), and
// enqueue a StatisticsEvent { m_Statistic = CrimeRate, m_Change = 100f * average } into CityStatisticsSystem.
Additional tips: - To influence the system's behavior, adjust PoliceConfigurationData.m_MaxCrimeAccumulation or toggle the Locked component on the configured police prefab. - Because the system runs on a periodic interval (GetUpdateInterval returns 8192), updates are not per-frame — design any gameplay logic that depends on crime statistics accordingly.