Skip to content

Game.ObjectBuiltRequirementSystem

Assembly: Assembly-CSharp.dll
Namespace: Game.Prefabs

Type: public class

Base: GameSystemBase

Summary:
ObjectBuiltRequirementSystem is an ECS system that tracks built/destroyed prefab instances and updates unlock requirements that depend on the number of built objects. It schedules a parallel IJobChunk (UnlockOnBuildJob) which inspects PrefabRef components, looks up any UnlockOnBuildData buffers on the referenced prefab, and adjusts UnlockRequirementData progress on the requirement entities. When a requirement reaches its minimum count and the requirement entity is currently Locked, the system creates an Unlock event entity so other systems can process unlocking. The system runs on creation and on load; it uses a ModificationEndBarrier command buffer to create unlock events safely from jobs.


Fields

  • private ModificationEndBarrier m_ModificationEndBarrier
    Used to obtain a command buffer (parallel writer) for creating Unlock event entities and setting components from the job. Ensures commands are applied after the job finishes.

  • private EntityQuery m_ChangedQuery
    Query that matches entities with PrefabRef and either Created or Deleted component (and excludes Native/Temp). Used for incremental updates when not doing a full rescan.

  • private EntityQuery m_AllQuery
    Query that matches all PrefabRef entities (excluding Native/Temp). Used to do a full pass when the world has just been loaded.

  • private EntityArchetype m_UnlockEventArchetype
    Archetype used to create the temporary Unlock event entities (components: Event, Unlock).

  • private bool m_Loaded
    Flag set when OnGameLoaded is called; causes the next update to use the full m_AllQuery once and then clear the flag.

  • private TypeHandle __TypeHandle
    Compiler-generated struct that caches component/buffer/lookup handles used by the job. Populated in OnCreateForCompiler.

Properties

  • (No public properties exposed)
    All work is done via queries, job data and internal handles. The system exposes no public properties.

Constructors

  • public ObjectBuiltRequirementSystem()
    Default parameterless constructor (preserved). Typical ECS system construction; most initialization is done in OnCreate / OnCreateForCompiler.

Methods

  • protected override void OnCreate()
    Initializes queries, gets/creates the ModificationEndBarrier, prepares the m_UnlockEventArchetype and other runtime state:
  • m_ModificationEndBarrier = World.GetOrCreateSystemManaged()
  • Builds m_ChangedQuery to catch PrefabRef entities with Created/Deleted
  • Builds m_AllQuery to catch all PrefabRef entities (non-native/non-temp)
  • Creates the Unlock event archetype (Event + Unlock)

  • protected override void OnGameLoaded(Context serializationContext)
    Called after the game is loaded; sets m_Loaded = true so the next update performs a full pass (m_AllQuery) to recalc progress from scratch.

  • private bool GetLoaded()
    Internal helper to return true once when m_Loaded was set, and then reset it to false. Used in OnUpdate to decide whether to use m_AllQuery or m_ChangedQuery.

  • protected override void OnUpdate()
    Main update logic:

  • Chooses query = m_AllQuery if GetLoaded() returned true (full pass on load), otherwise m_ChangedQuery (incremental).
  • If query is not empty, constructs an UnlockOnBuildJob with:
    • m_UnlockEventArchetype
    • m_Buffer = m_ModificationEndBarrier.CreateCommandBuffer().AsParallelWriter()
    • component/buffer/lookup handles obtained via InternalCompilerInterface.GetComponentTypeHandle/GetComponentLookup/GetBufferLookup using __TypeHandle fields
  • Schedules the job with JobChunkExtensions.ScheduleParallel and assigns the returned dependency to base.Dependency.
  • Registers the job handle with m_ModificationEndBarrier.AddJobHandleForProducer so command buffer is applied after the job completes.

  • private void __AssignQueries(ref SystemState state)
    Compiler helper (currently a no-op aside from a temporary EntityQueryBuilder disposal). Present to satisfy generated code paths.

  • protected override void OnCreateForCompiler()
    Called by generated bootstrap to assign cached TypeHandle handles and queries for the compiler path:

  • Calls __AssignQueries and __TypeHandle.__AssignHandles(ref state)

Nested / Job types (important behavior)

  • private struct UnlockOnBuildJob : IJobChunk
    Burst-compiled parallel job that executes per chunk of entities with PrefabRef:
  • Fields:
    • EntityArchetype m_UnlockEventArchetype
    • EntityCommandBuffer.ParallelWriter m_Buffer
    • [ReadOnly] ComponentTypeHandle m_PrefabRefTypeHandle
    • [ReadOnly] ComponentTypeHandle m_DeletedTypeHandle
    • [ReadOnly] ComponentLookup m_LockedDataFromEntity
    • [ReadOnly] BufferLookup m_UnlockOnBuildDataFromEntity
    • [ReadOnly] ComponentLookup m_UnlockRequirementDataFromEntity
    • [ReadOnly] ComponentLookup m_UnlockOnBuildRequirementDataFromEntity
  • Execute behavior (per chunk):
    • Gets PrefabRef array from the chunk
    • For each prefab referred to by entities in the chunk:
    • Tries to get the UnlockOnBuildData buffer on the prefab (if none, skip)
    • Determines whether the chunk has Deleted (flag) to know if building or deleting
    • For each entry in the UnlockOnBuildData buffer (each entry points to a requirement entity):
      • Reads ObjectBuiltRequirementData and UnlockRequirementData for the requirement entity
      • Calculates num = max(component.m_Progress + (Deleted ? -1 : +1), 0)
      • Updates component.m_Progress = min(objectBuiltRequirementData.m_MinimumCount, num)
      • Writes the modified UnlockRequirementData back via m_Buffer.SetComponent
      • If the requirement entity has an enabled Locked component and num >= objectBuiltRequirementData.m_MinimumCount:
      • Creates an Unlock event entity via m_Buffer.CreateEntity and writes an Unlock component referring to the requirement entity
  • Purpose: increment/decrement progress and produce Unlock events when thresholds are met; avoids race conditions by using an ECB.

  • private struct TypeHandle
    Contains cached handles used by the job and method to assign them:

  • ComponentTypeHandle (read-only)
  • ComponentTypeHandle (read-only)
  • ComponentLookup (read-only)
  • BufferLookup (read-only)
  • ComponentLookup (read-write)
  • ComponentLookup (read-only)
  • Method __AssignHandles(ref SystemState state) populates these handles via state.GetComponentTypeHandle/GetBufferLookup/GetComponentLookup.

Notes and behavior details - The system uses a command buffer (ModificationEndBarrier) to safely create event entities and set components from worker threads. - The job is Burst compiled and scheduled in parallel using JobChunkExtensions.ScheduleParallel. - UnlockOnBuildData is expected to be a dynamic buffer on the prefab entity containing entries that point to requirement entities. ObjectBuiltRequirementData contains the threshold (m_MinimumCount). UnlockRequirementData holds current progress (m_Progress). Locked is used to check whether unlocking should produce an Unlock event. - On load the system does a full pass to ensure progress values are correctly initialized from existing prefabs; subsequent runtime updates are incremental (Created/Deleted).

Usage Example

// Example: Attach requirement components so that building a specific prefab
// increments a requirement until it reaches 5 and then emits an Unlock event.
//
// This pseudo-code runs during mod setup or while creating prefabs/entities.

Entity prefabEntity = /* obtain prefab entity for the building type */;

// Add a buffer entry on the prefab so the system knows which requirement to update:
var buffer = entityManager.AddBuffer<UnlockOnBuildData>(prefabEntity);
buffer.Add(new UnlockOnBuildData { m_Entity = requirementEntity });

// Create the requirement entity (initially locked):
var req = entityManager.CreateEntity(typeof(UnlockRequirementData), typeof(ObjectBuiltRequirementData), typeof(Locked));
entityManager.SetComponentData(req, new UnlockRequirementData { m_Progress = 0 });
entityManager.SetComponentData(req, new ObjectBuiltRequirementData { m_MinimumCount = 5 });

// The ObjectBuiltRequirementSystem will:
// - increment m_Progress each time an entity with PrefabRef to the above prefab is Created,
// - decrement on Deleted,
// - and create an Unlock event entity when m_Progress >= m_MinimumCount and the requirement entity is Locked.

If you want, I can also produce example definitions for UnlockOnBuildData, ObjectBuiltRequirementData, UnlockRequirementData and a simple test scenario showing the system producing an Unlock event.