Skip to content

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.