Skip to content

Game.Prefabs.StrictObjectBuiltRequirementSystem

Assembly: Assembly-CSharp (Game)
Namespace: Game.Prefabs

Type: public class StrictObjectBuiltRequirementSystem

Base: GameSystemBase

Summary:
System that enforces "strict object built" unlock requirements. The system watches entities that declare a StrictObjectBuiltRequirementData (a requirement keyed to a specific prefab/entity) and a corresponding UnlockRequirementData while the entity is Locked. It reads global instance counts from the InstanceCountSystem and: - updates the UnlockRequirementData.m_Progress to reflect how many of the required prefab exist (capped at the requirement minimum), and - creates an Unlock event entity (Event + Unlock) for entities whose required count has been reached.

The system uses: - InstanceCountSystem to read per-prefab instance counts, - ModificationEndBarrier to create command buffers for producing Unlock events from a job, - an EntityQuery for requirement entities, and - a concurrent Burst-compiled IJobChunk (TrackObjectsJob) to perform updates in parallel.


Fields

  • private InstanceCountSystem m_InstanceCountSystem
    Used to read current instance counts per prefab. The system calls GetInstanceCounts(readOnly: true, out dependencies) to obtain a NativeParallelHashMap and a job dependency handle.

  • private ModificationEndBarrier m_ModificationEndBarrier
    Used to create a parallel EntityCommandBuffer (AsParallelWriter) so the job can produce Unlock event entities safely from worker threads. The barrier is also given the job handle via AddJobHandleForProducer.

  • private EntityQuery m_ChangedQuery
    Query that detects prefab creation/deletion changes (All: PrefabRef, Any: Created|Deleted, None: Temp). Used to trigger the system when prefab instances change.

  • private EntityQuery m_RequirementQuery
    Query selecting entities that have StrictObjectBuiltRequirementData (read-only), UnlockRequirementData (read-write) and Locked (read-only). The system requires this query for update (RequireForUpdate).

  • private EntityArchetype m_UnlockEventArchetype
    An archetype created at OnCreate that contains Event and Unlock components; used to create unlock event entities when requirements are met.

  • private bool m_Loaded
    Transient flag set by OnGameLoaded to force a single update pass right after load. GetLoaded() returns true once and clears the flag.

  • private TypeHandle __TypeHandle
    A small struct that caches ComponentTypeHandle and EntityTypeHandle instances (for StrictObjectBuiltRequirementData, UnlockRequirementData, Entity) which are assigned during OnCreateForCompiler. These cached handles are used to build the job's component and entity handles safely.

(Additionally the class contains two nested structs used at runtime: TrackObjectsJob (Burst compiled IJobChunk) and TypeHandle (the cached handles).)

Properties

  • None (the system exposes no public properties).

Constructors

  • public StrictObjectBuiltRequirementSystem()
    Default public constructor. Marked with [Preserve] in the compiled code to prevent stripping. Initialization of the system state happens in OnCreate/OnCreateForCompiler.

Methods

  • protected override void OnCreate()
    Initializes the system:
  • Acquires references to InstanceCountSystem and ModificationEndBarrier from the World.
  • Builds m_ChangedQuery and m_RequirementQuery.
  • Creates the m_UnlockEventArchetype (Event + Unlock).
  • Calls RequireForUpdate(m_RequirementQuery) so the system only runs when there are requirement entities. This is where the system wires up dependencies to other systems and sets up queries/archetypes.

  • protected override void OnGameLoaded(Context serializationContext)
    Sets m_Loaded = true so the next OnUpdate will run an initial pass to update progress immediately after a save/load.

  • private bool GetLoaded()
    Utility that returns true exactly once after OnGameLoaded() is called: it clears the m_Loaded flag and returns whether it was set.

  • protected override void OnUpdate()
    Main update. If GetLoaded() returned true or there are relevant changes detected by m_ChangedQuery, the system:

  • obtains instance counts from m_InstanceCountSystem.GetInstanceCounts(readOnly: true, out dependencies),
  • prepares a TrackObjectsJob with component type handles and the instance-count map, and a parallel command buffer writer from m_ModificationEndBarrier,
  • schedules the job in parallel over m_RequirementQuery, combining dependencies appropriately,
  • registers the job handle with m_InstanceCountSystem (AddCountReader) and with m_ModificationEndBarrier (AddJobHandleForProducer).

The job will update UnlockRequirementData.m_Progress and create Unlock event entities for satisfied requirements.

  • private void __AssignQueries(ref SystemState state)
    Called from OnCreateForCompiler; currently constructs and disposes an empty EntityQueryBuilder (compiler helper). Present for compiler-generated wiring; in this compiled form it does not populate additional queries beyond those created in OnCreate.

  • protected override void OnCreateForCompiler()
    Compiler helper invoked to assign cached type handles and queries before normal execution. Calls __AssignQueries and TypeHandle.__AssignHandles to populate __TypeHandle entries.

Nested/type-level methods (important runtime pieces):

  • TrackObjectsJob.Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
    Burst-compiled IJobChunk implementation that:
  • obtains arrays for StrictObjectBuiltRequirementData, UnlockRequirementData, and Entity from the chunk,
  • iterates chunk entities (honoring enabled mask if any),
  • for each requirement, tries to find the current instance count in m_InstanceCounts using the requirement's m_Requirement (an Entity key),
  • updates the corresponding UnlockRequirementData.m_Progress to min(m_MinimumCount, actualCount),
  • if actualCount >= m_MinimumCount, creates an Unlock event entity with the source entity as payload using the parallel command buffer writer.

  • TypeHandle.__AssignHandles(ref SystemState state)
    Assigns the ComponentTypeHandle (read-only), ComponentTypeHandle (read-write), and EntityTypeHandle from the provided SystemState. These handles are used by the TrackObjectsJob.

Notes on threading and safety: - TrackObjectsJob is Burst-compiled and scheduled in parallel; component type handles are requested with proper read/write flags. - Entity commands (creating Unlock event entities and setting their Unlock component) are emitted via an EntityCommandBuffer.ParallelWriter produced by ModificationEndBarrier to avoid direct structural changes in worker threads. - The system informs the InstanceCountSystem about its read dependency (AddCountReader) so instance counts remain valid while the job runs.

Usage Example

Example snippets showing how the system is initialized internally (simplified) and how a mod could create a requirement entity that this system will process.

System-like initialization (similar to the system's OnCreate):

[Preserve]
protected override void OnCreate()
{
    base.OnCreate();
    m_InstanceCountSystem = World.GetOrCreateSystemManaged<InstanceCountSystem>();
    m_ModificationEndBarrier = World.GetOrCreateSystemManaged<ModificationEndBarrier>();

    m_ChangedQuery = GetEntityQuery(new EntityQueryDesc {
        All = new ComponentType[] { ComponentType.ReadOnly<PrefabRef>() },
        Any = new ComponentType[] { ComponentType.ReadOnly<Created>(), ComponentType.ReadOnly<Deleted>() },
        None = new ComponentType[] { ComponentType.ReadOnly<Temp>() }
    });

    m_RequirementQuery = GetEntityQuery(
        ComponentType.ReadOnly<StrictObjectBuiltRequirementData>(),
        ComponentType.ReadWrite<UnlockRequirementData>(),
        ComponentType.ReadOnly<Locked>());

    m_UnlockEventArchetype = EntityManager.CreateArchetype(
        ComponentType.ReadWrite<Event>(),
        ComponentType.ReadWrite<Unlock>());

    RequireForUpdate(m_RequirementQuery);
}

How a mod could create a requirement entity that this system will handle:

// create a requirement to unlock when 5 instances of prefabEntity exist
Entity requirementEntity = entityManager.CreateEntity(
    typeof(StrictObjectBuiltRequirementData),
    typeof(UnlockRequirementData),
    typeof(Locked));

// set the requirement target and threshold
entityManager.SetComponentData(requirementEntity, new StrictObjectBuiltRequirementData {
    m_Requirement = prefabEntity,     // Entity reference to the prefab to count
    m_MinimumCount = 5
});

// initialize progress (system will update this)
entityManager.SetComponentData(requirementEntity, new UnlockRequirementData {
    m_Progress = 0
});

Developer tips: - If you need to react when the unlock occurs, listen for Event + Unlock entities (created by this system) or subscribe to whatever higher-level unlock processing is in the game. - Use the InstanceCountSystem API when writing jobs or systems that also need to observe instance counts — call AddCountReader/AddCountWriter appropriately to coordinate dependencies.