Game.Prefabs.UnlockSystem
Assembly: Assembly-CSharp
Namespace: Game.Prefabs
Type: public class UnlockSystem
Base: GameSystemBase
Summary:
UnlockSystem is an ECS system responsible for managing prefab "locked" state and processing unlock requirements and unlock events. It:
- Scans entities with UnlockRequirement buffers and Locked components to determine when prefabs should be unlocked (via a parallel IJobChunk).
- Processes explicit Unlock events that request unlocking a prefab.
- Toggles the Locked component, emits Unlock event entities, and logs unlocks via a PrefabSystem instance.
This system runs only in game mode and handles initial load detection to force processing on first frame after load.
Fields
-
private PrefabSystem m_PrefabSystem
Holds a reference to the PrefabSystem (retrieved from the world) used to query prefabs, get obsolete IDs, and check/convert prefab data. -
private EntityQuery m_LockedQuery
Query that matches entities having Locked and UnlockRequirement — used by the job that checks unlock requirements. -
private EntityQuery m_UpdatedQuery
Query that matches entities with Locked, UnlockRequirement and Updated — used to detect recently-updated prefabs and trigger re-checks. -
private EntityQuery m_EventQuery
Query that matches entities with an Unlock component — used to process explicit unlock events. -
private EntityArchetype m_UnlockEventArchetype
Archetype used to create Unlock event entities (Event + Unlock components). -
private bool m_Loaded
Internal flag set when the game has finished loading to force a first processing pass. -
private ILog m_Log
Logger instance used for debug logging of unlock events. -
private TypeHandle __TypeHandle
Compiler-generated container holding entity/component type handles used by jobs and runtime methods. -
private struct CheckUnlockRequirementsJob.m_EntityType : EntityTypeHandle
(inside nested job) Type handle used by the job to fetch entity array from chunks. -
private struct CheckUnlockRequirementsJob.m_UnlockRequirementType : BufferTypeHandle<UnlockRequirement>
(inside nested job) Buffer type handle used to read UnlockRequirement buffers. -
private struct CheckUnlockRequirementsJob.m_LockedData : ComponentLookup<Locked>
(inside nested job) ComponentLookup for checking whether referenced prefabs are currently locked/enabled. -
private struct CheckUnlockRequirementsJob.m_UnlockQueue : NativeQueue<Entity>.ParallelWriter
(inside nested job) Parallel writer used to enqueue entities that should be unlocked.
Properties
- This type exposes no public properties.
{{ The system exposes methods (like IsLocked) for external queries but no public auto-properties. }}
Constructors
public UnlockSystem()
Default constructor. The system is attributed with [Preserve] to avoid stripping. Initialization is done in OnCreate rather than constructor.
{{ OnCreate registers queries, fetches the PrefabSystem from the world and prepares the unlock event archetype and logger. The constructor itself is empty and preserved for runtime. }}
Methods
protected override void OnCreate()
Initializes the system. Retrieves PrefabSystem from the world, builds entity queries:- m_LockedQuery: Locked + UnlockRequirement
- m_UpdatedQuery: Locked + UnlockRequirement + Updated
-
m_EventQuery: Unlock Creates m_UnlockEventArchetype (Event + Unlock) and obtains a logger.
-
protected override void OnGamePreload(Purpose purpose, GameMode mode)
Enables or disables the system depending on the provided game mode. The system is enabled only when mode.IsGame() is true to ensure it runs only in gameplay. -
protected override void OnGameLoaded(Context context)
Marks internal m_Loaded flag true so the next update will perform a forced processing pass (to handle initial unlocking after load). -
private bool GetLoaded()
Atomically checks and consumes the m_Loaded flag. Returns true once after OnGameLoaded has been called, false afterwards. -
protected override void OnUpdate()
Main update loop. Behavior: - If there are explicit Unlock events, ProcessEvents() will run to handle them.
- If no events and not just loaded and no updated Locked/UnlockRequirement entities, it returns early.
- Otherwise it constructs a NativeQueue
, schedules and immediately completes a parallel CheckUnlockRequirementsJob that enqueues prefabs that meet unlock conditions, then dequeues and calls UnlockPrefab for each. -
Repeats scheduling-dequeue loop until no more queued unlocks (to handle cascaded unlocks).
-
private bool ProcessEvents()
Processes existing Unlock event entities (m_EventQuery). For each Unlock component's prefab, if the prefab currently has Enabled Locked component, it calls UnlockPrefab(prefab, createEvent: false). Returns true if it processed at least one unlock; false otherwise. -
private void UnlockPrefab(Entity unlock, bool createEvent)
Performs the actual unlock: - Disables the Locked component on the prefab entity (EntityManager.SetComponentEnabled
(... false)). - If createEvent is true, creates an Event+Unlock entity and sets Unlock to reference the unlocked prefab.
-
Logs the unlocked prefab. If the entity does not have PrefabData enabled, logs its obsolete ID via PrefabSystem.GetObsoleteID; otherwise gets PrefabBase and logs its name/ID.
-
public bool IsLocked(PrefabBase prefab)
Public helper that queries PrefabSystem.HasEnabledComponent(prefab) to determine whether a prefab is currently locked. -
private void __AssignQueries(ref SystemState state)
Compiler-generated method for assigning queries at compile-time; here it creates an EntityQueryBuilder and disposes it (placeholder for generated code). Used from OnCreateForCompiler. -
protected override void OnCreateForCompiler()
Compiler hook used to assign queries and type handles for the Burst/IJob chunk scheduling path by calling __AssignQueries and __TypeHandle.__AssignHandles.
Nested types / Jobs:
- CheckUnlockRequirementsJob : IJobChunk (Burst-compiled)
Job iterates over chunks matching m_LockedQuery, reads each entity's UnlockRequirement dynamic buffer and decides whether that prefab should be unlocked: - For each UnlockRequirement entry it checks whether the referenced prefab has an enabled Locked component.
- It evaluates flags UnlockFlags.RequireAll and UnlockFlags.RequireAny to determine whether all required prefabs are unlocked or any are unlocked (or the inverse) and enqueues the entity if conditions indicate it should be unlocked.
- Enqueues candidate entities into m_UnlockQueue.AsParallelWriter() to be consumed on main thread.
{{ The job uses ComponentLookup
Usage Example
// Example: Query whether a prefab is currently locked from game code
// (UnlockPrefab is private; external code should use IsLocked or emit an Unlock event)
var unlockSystem = World.DefaultGameObjectInjectionWorld.GetOrCreateSystemManaged<Game.Prefabs.UnlockSystem>();
PrefabBase somePrefab = ...;
if (unlockSystem.IsLocked(somePrefab))
{
// prefab is locked — you can create an Unlock event entity to request unlock:
EntityManager em = World.DefaultGameObjectInjectionWorld.EntityManager;
Entity archetypeEntity = em.CreateEntity(
ComponentType.ReadWrite<Event>(),
ComponentType.ReadWrite<Unlock>()
);
em.SetComponentData(archetypeEntity, new Unlock(em.GetPrimaryEntity(somePrefab)));
}
{{ Notes and tips: - Unlock requirements are evaluated on the main thread by scheduling and completing a Burst IJobChunk; this allows the system to test many entities in parallel but the final state changes (disabling Locked and creating events) happen on the main thread. - The system intentionally re-runs unlocking in a loop in OnUpdate to handle chains of unlocks (unlocking one prefab may satisfy another prefab’s requirements). - The system only runs in game mode and performs one forced pass immediately after a game load (m_Loaded). - Use the public IsLocked(PrefabBase) to check lock state from other game code; to request an unlock externally, create an entity with the Unlock component (the system will pick it up via m_EventQuery). }}