Game.Simulation.CrimeAccumulationSystem
Assembly: Assembly-CSharp
Namespace: Game.Simulation
Type: class
Base: GameSystemBase
Summary:
CrimeAccumulationSystem accumulates crime for buildings and service objects over time and issues police patrol requests when accumulation exceeds configured thresholds. It runs as a scheduled system using Unity's Job system and Burst (CrimeAccumulationJob). The system:
- Iterates CrimeProducer entities on a shared update frame (sharded across kUpdatesPerDay updates per day).
- Computes per-building crime increase per day from prefab data (SpawnableBuildingData -> CrimeAccumulationData or ServiceObjectData -> CrimeAccumulationData).
- Modifies the raw crime increase by local effects, district modifiers and city modifiers, and reduces it based on police service coverage using PoliceConfigurationData.
- Adds the computed per-frame increment to the CrimeProducer.m_Crime value (clamped to m_MaxCrimeAccumulation).
- If crime exceeds the configured tolerance and no valid patrol request exists, creates a PolicePatrolRequest request entity (using an EndFrameBarrier command buffer) with a RequestGroup.
Inner job CrimeAccumulationJob is Burst-compiled and uses ComponentTypeHandle / BufferLookup / ComponentLookup to do efficient chunked processing. System update frequency is controlled by kUpdateInterval and kUpdatesPerDay constants.
Fields
-
public static readonly int kUpdatesPerDay
Constant default 256: number of updates used to spread daily accumulation into small increments. -
public static readonly int kUpdateInterval
Constant computed as 262144 / (kUpdatesPerDay * 16). The system uses this to determine its scheduling interval (see GetUpdateInterval). -
private CitySystem m_CitySystem
Cached reference to the CitySystem used to access the city entity (city-level modifiers, etc.). -
private LocalEffectSystem m_LocalEffectSystem
Cached reference to the LocalEffectSystem to read local modifiers affecting crime accumulation. -
private SimulationSystem m_SimulationSystem
Cached reference to the SimulationSystem (used to get the current frameIndex for scheduling updates). -
private EndFrameBarrier m_EndFrameBarrier
Barrier used to create command buffers for issuing police patrol request entities at end of frame. -
private EntityQuery m_CrimeProducerQuery
Query used to find CrimeProducer entities that should be processed by the job (filtered by UpdateFrame). -
private EntityQuery m_PoliceConfigurationQuery
Query to obtain the PoliceConfigurationData singleton which controls police-related modifiers, max accumulation, tolerance, etc. -
private EntityArchetype m_PatrolRequestArchetype
Archetype used when creating PolicePatrolRequest entities (ServiceRequest, PolicePatrolRequest, RequestGroup components). -
private TypeHandle __TypeHandle
Internal struct caching ComponentTypeHandle/BufferLookup/ComponentLookup instances used by the job for performance.
Properties
- None (no public properties exposed by this system).
Constructors
public CrimeAccumulationSystem()
Default constructor (preserved). The system's actual initialization is done in OnCreate. The constructor itself doesn't perform initialization logic.
Methods
-
public override int GetUpdateInterval(SystemUpdatePhase phase)
Returns the system update interval value used by the engine for scheduling. This returns kUpdateInterval. -
[Preserve] protected override void OnCreate()
Initializes system dependencies and queries: - Acquires references to CitySystem, LocalEffectSystem, SimulationSystem and EndFrameBarrier.
- Builds m_CrimeProducerQuery to select CrimeProducer entities that have an UpdateFrame and do not have Deleted or Temp.
- Builds m_PatrolRequestArchetype for creating patrol request entities.
- Calls RequireForUpdate(m_CrimeProducerQuery) to ensure the system only runs when matching entities exist.
-
Asserts that the derived interval meets minimum constraints.
-
[Preserve] protected override void OnUpdate()
Main scheduling logic: - Reads PoliceConfigurationData singleton.
- Skips processing if the police service prefab is locked (HasEnabledComponent
). - Computes the appropriate UpdateFrame for this tick and sets a shared component filter on m_CrimeProducerQuery.
- Prepares and schedules the CrimeAccumulationJob (Burst-compiled) as a parallel chunked job, providing:
- ComponentTypeHandles / BufferLookups / ComponentLookups needed by the job.
- City entity, patrol request archetype, police configuration, local effect read data and a parallel command buffer from m_EndFrameBarrier.
- A RandomSeed for per-chunk randomness.
- Adds job handle to m_EndFrameBarrier and m_LocalEffectSystem for proper producer tracking and local effect synchronization.
-
Stores job handle in base.Dependency.
-
private void __AssignQueries(ref SystemState state)
(Internal / compiler helper) Placeholder used by generated-on-compiler path to assign queries. Does a dummy EntityQueryBuilder disposal to satisfy generated code flow. -
protected override void OnCreateForCompiler()
(Internal / compiler helper) Called by generated code path; invokes __AssignQueries and assigns type handles via __TypeHandle.
Nested: CrimeAccumulationJob (private struct) — Burst-compiled IJobChunk implementation:
- Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
Processes each chunk's entities, computing and applying crime increases, applying local/district/city modifiers, considering police coverage, clamping values, updating CrimeProducer components and requesting patrols as needed.
- GetBuildingCrimeIncreasePerDay(Entity prefab) : float
Helper that checks prefab component data to find the base per-day crime rate:
- If prefab has SpawnableBuildingData, checks the spawnable's m_ZonePrefab for CrimeAccumulationData.
- Else if prefab has ServiceObjectData, checks its m_Service for CrimeAccumulationData.
- Returns 0f if no applicable data found.
- RequestPatrolIfNeeded(int jobIndex, Entity entity, ref CrimeProducer producer, ref Random random)
If crime exceeds m_CrimeAccumulationTolerance and there is not already a valid patrol request targeting or matching dispatch index, create a PolicePatrolRequest entity using the provided parallel command buffer. Sets PolicePatrolRequest and RequestGroup on the created entity. Also resets producer.m_PatrolRequest and producer.m_DispatchIndex when issuing a new request.
Nested: TypeHandle (private struct) — holds cached ComponentTypeHandle/ComponentLookup/BufferLookup instances and provides __AssignHandles(ref SystemState) used to initialize these handles from a SystemState.
Usage Example
// Example: Adjust the police coverage factor at runtime to make coverage reduce crime accumulation more strongly.
using Unity.Entities;
using Game.Simulation;
public static class ModHelpers
{
public static void SetPoliceCoverageFactor(World world, float newFactor)
{
var entityManager = world.EntityManager;
// There must be a singleton PoliceConfigurationData entity; the system queries it as a singleton.
var query = entityManager.CreateEntityQuery(ComponentType.ReadOnly<PoliceConfigurationData>());
if (query.IsEmptyIgnoreFilter) return;
var policeConfigEntity = query.GetSingletonEntity();
var policeConfig = entityManager.GetComponentData<PoliceConfigurationData>(policeConfigEntity);
policeConfig.m_CrimePoliceCoverageFactor = newFactor;
entityManager.SetComponentData(policeConfigEntity, policeConfig);
}
}
// Alternatively, obtain the running system to inspect or log its state:
var world = World.DefaultGameObjectInjectionWorld;
var crimeSystem = world.GetExistingSystemManaged<Game.Simulation.CrimeAccumulationSystem>();
if (crimeSystem != null)
{
// You can not directly call internal methods, but you can read/write related singletons/components
// or interact with entities that CrimeAccumulationSystem processes (CrimeProducer components).
}
Notes and tips: - The system uses shared component filtering by UpdateFrame to spread workload across frames; modifying UpdateFrame values on entities will affect when they are processed. - PolicePatrolRequest entities are created via the system's EndFrameBarrier command buffer; if you want to intercept or change request creation you can add another system that runs after this one or intercept entities created with the PolicePatrolRequest component. - Be careful when modifying PoliceConfigurationData fields — these are used globally and can significantly change game balance.