Game.Prefabs.PrefabUnlockedRequirementSystem
Assembly:
Assembly-CSharp (game runtime assembly; the system is defined in the game's managed assembly)
Namespace:
Game.Prefabs
Type:
class
Base:
GameSystemBase
Summary:
PrefabUnlockedRequirementSystem is a runtime ECS system that listens for Unlock components and, when a prefab is unlocked, generates Unlock events for entities that have matching PrefabUnlockedRequirement buffers and are currently Locked. It uses a Burst-compiled IJobChunk (UnlockJob) scheduled in parallel to scan Unlock components against the PrefabUnlockedRequirement buffers, and writes entity creation / component setting commands via a ModificationEndBarrier's EntityCommandBuffer. The system uses EntityQuery to find Unlock components and to gather entities that carry PrefabUnlockedRequirement buffers. It is designed for efficient, parallel processing of unlock propagation within the Cities: Skylines 2 modding ECS environment.
Fields
-
private ModificationEndBarrier m_ModificationEndBarrier
Holds a reference to the world ModificationEndBarrier system used to create an EntityCommandBuffer (as a ParallelWriter) for safely issuing entity creation and component mutation commands from jobs. -
private EntityQuery m_UnlockQuery
EntityQuery that matches entities with the Unlock component. Used to detect whether there are any unlock events to process and to drive scheduling of the UnlockJob. -
private EntityQuery m_PrefabUnlockedQuery
EntityQuery that matches entities having a PrefabUnlockedRequirement buffer. The system captures a list of those entities to iterate over inside the job. -
private EntityArchetype m_UnlockEventArchetype
Archetype for creating Unlock event entities (contains Event and Unlock components). The UnlockJob creates new entities of this archetype to raise unlock events on matching entities. -
private TypeHandle __TypeHandle
Internal struct storing ComponentLookup / BufferLookup / ComponentTypeHandle instances required by the job. This is populated in OnCreateForCompiler and used to obtain the lookups for scheduling the job and for internal compiler interoperability. -
private struct UnlockJob
(nested)
Burst-compiled IJobChunk implementation that does the core work: it iterates the chunk's Unlock components, compares them against requirements listed in PrefabUnlockedRequirement buffers of target entities, checks whether target entities are Locked (enabled), and uses the parallel EntityCommandBuffer to create Unlock event entities for matching targets. -
private struct TypeHandle
(nested)
Contains read-only BufferLookup, ComponentLookup , and ComponentTypeHandle . It provides __AssignHandles to initialize these lookups from a SystemState.
Properties
- (No public properties)
This system does not expose public properties. It uses internal fields and type handles to operate.
Constructors
public PrefabUnlockedRequirementSystem()
Parameterless constructor. The system is initialized by the ECS runtime; most initialization is performed in OnCreate and OnCreateForCompiler.
Methods
protected override void OnCreate()
Initializes the system at creation time. Tasks performed:- Acquires the ModificationEndBarrier system from the world (m_ModificationEndBarrier).
- Creates m_UnlockQuery (ReadOnly
) and m_PrefabUnlockedQuery (ReadOnly ). -
Creates the m_UnlockEventArchetype with Event and Unlock components. This setup prepares lookups, queries, and archetype used at runtime.
-
protected override void OnUpdate()
Main runtime logic executed each frame (or system tick). Behavior: - If there are no Unlock components present (m_UnlockQuery.IsEmptyIgnoreFilter), the method returns early.
- Otherwise, it asynchronously collects the list of entities that have PrefabUnlockedRequirement buffers into a NativeList
. - Schedules the Burst-compiled UnlockJob in parallel, providing:
- the unlock event archetype,
- a parallel EntityCommandBuffer from the ModificationEndBarrier,
- the list of PrefabUnlockedRequirement entities,
- buffer/component lookups from the internal TypeHandle,
- the Unlock component type handle.
-
Disposes the NativeList in a job-aware manner and registers the job handle with ModificationEndBarrier to ensure commands are applied after the job completes. This method orchestrates the scheduling of parallel processing that generates Unlock events for matching entities.
-
protected override void OnCreateForCompiler()
Called to prepare state for code generated by the compiler. It calls __AssignQueries (a no-op builder in this file) and assigns the TypeHandle's internal lookup handles using the CheckedStateRef SystemState. -
private void __AssignQueries(ref SystemState state)
A small helper used in the compiler path (here it creates and disposes an EntityQueryBuilder). Present for compiler compatibility; actual queries are created in OnCreate. -
private struct UnlockJob.Execute(...)
(method inside UnlockJob)
Detailed job logic: - Retrieves the chunk's NativeArray
using the Unlock ComponentTypeHandle. - Iterates every entity in m_PrefabUnlockedRequirementEntities:
- Skips target entities that do not have the Locked component enabled or that do not have a PrefabUnlockedRequirement buffer (using the provided lookups).
- For each requirement entry in the buffer, compares the required prefab Entity to each Unlock.m_Prefab in the chunk's Unlock array.
- On match, creates a new Unlock event entity (of m_UnlockEventArchetype) using the parallel EntityCommandBuffer and sets its Unlock component to reference the target entity.
- This logic is designed to be parallel and Burst-friendly; it minimizes structural changes during iteration by using the command buffer.
Notes and caveats:
- The job uses NativeList
Usage Example
This system runs automatically under the ECS world. Example showing how a modder might prepare an entity so it will receive an Unlock event when a required prefab is unlocked:
// Create an entity that can be unlocked when a specific prefab becomes available.
// 'entityManager' is the World.EntityManager, and 'prefabEntity' is the Entity to be required.
var e = entityManager.CreateEntity();
var buffer = entityManager.AddBuffer<PrefabUnlockedRequirement>(e);
buffer.Add(new PrefabUnlockedRequirement { m_Requirement = prefabEntity });
// Mark this entity as Locked (so the system checks the Locked component enabled state).
entityManager.AddComponentData(e, new Locked());
// Somewhere else, when a prefab becomes unlocked, create an Unlock component on an entity:
// (The system's m_UnlockQuery will pick this up and propagate Unlock events.)
var unlockEntity = entityManager.CreateEntity();
entityManager.AddComponentData(unlockEntity, new Unlock { m_Prefab = prefabEntity });
This will cause PrefabUnlockedRequirementSystem to create an Unlock event entity targeting the entity that had the corresponding PrefabUnlockedRequirement buffer entry, if that target is currently Locked.
Additional tips: - Ensure PrefabUnlockedRequirement and Locked component types are correctly defined and enabled/disabled as intended. - Because the system uses parallel jobs and command buffers, be cautious with mixing immediate structural changes in other systems running concurrently — follow ECS dependency practices and add job handles to barriers where required.