Skip to content

Game.Prefabs.PrefabInitializeSystem

Assembly: Assembly-CSharp.dll (typical for Cities: Skylines 2 game code / mods)
Namespace: Game.Prefabs

Type: class

Base: GameSystemBase

Summary:
System responsible for discovering entities that represent newly created prefabs (entities with Created + PrefabData), initializing their components and resolving prefab dependencies. It collects all matching entities from an EntityQuery, invokes component.Initialize on each Prefab component, queues and adds any dependent prefabs via the PrefabSystem, and finally calls LateInitialize on components (handling unlockable prefabs specially). The system ensures dependencies are resolved in breadth-first order via a queue and logs exceptions per-prefab to help debugging mod/prefab initialization errors.


Fields

  • private EntityQuery m_PrefabQuery
    Used to find entities that have been marked as Created and have PrefabData. The query is required for Update so the system only runs when relevant entities exist.

  • private PrefabSystem m_PrefabSystem
    Reference to the global PrefabSystem (retrieved in OnCreate). Used to map PrefabData to PrefabBase instances, add dependent prefabs to the global registry, and query unlockable status or get the spawned entity for a prefab.

  • private TypeHandle __TypeHandle
    Internal struct that caches EntityTypeHandle and a read-only ComponentTypeHandle to efficiently read archetype chunk data during OnUpdate. Assigned during OnCreateForCompiler.

  • (nested types) ListItem, QueueItem, TypeHandle
    Helper nested structs used to hold iteration state:

  • ListItem: pairs an Entity with its PrefabBase for later LateInitialize passes.
  • QueueItem: represents a prefab dependency to enqueue (prefab, parentPrefab, parentComponent).
  • TypeHandle: holds the EntityTypeHandle and PrefabData ComponentTypeHandle and provides a method to assign them from a SystemState.

Properties

  • (no public properties)
    The system exposes no public properties. All work is driven by the EntityQuery and the PrefabSystem.

Constructors

  • public PrefabInitializeSystem()
    Default parameterless constructor. The system relies on Unity/Entities lifecycle methods (OnCreate / OnUpdate) for initialization and runtime behavior.

Methods

  • protected override void OnCreate()
    Called when the system is created. Obtains the PrefabSystem instance from the World, builds the EntityQuery that matches Created + PrefabData, and calls RequireForUpdate to make the system run only when matching entities exist.

  • protected override void OnUpdate()
    Main update loop:

  • Converts the query to an archetype chunk array.
  • Obtains EntityTypeHandle and PrefabData ComponentTypeHandle (from cached __TypeHandle).
  • Calls CompleteDependency() to ensure job dependencies are finished before reading entity/component data.
  • Iterates chunks and builds a list of ListItem (Entity + PrefabBase) and a HashSet of prefabs encountered.
  • For each item, calls InitializePrefab to invoke Initialize() on components and enqueue dependencies.
  • Dequeues queued dependent prefabs, adds them to the PrefabSystem (via m_PrefabSystem.AddPrefab), and if actually added, gets the created entity and initializes that prefab too (and appends it to the processing list).
  • After all Initialize passes, iterates list and calls LateInitializePrefab for each prefab (handles unlockables and unlock dependencies).

The method uses temporary lists/queue/hashset for breadth-first dependency resolution and ensures proper disposal of the chunk array.

  • private void InitializePrefab(Entity entity, PrefabBase prefab, Queue<QueueItem> queue, HashSet<PrefabBase> prefabSet, List<PrefabBase> dependencies, List<ComponentBase> components)
    Per-prefab Initialize pass:
  • Collects components from the prefab into the provided components list.
  • For each ComponentBase: calls Initialize(EntityManager, entity) inside try/catch to log exceptions.
  • After Initialize, calls componentBase.GetDependencies(dependencies) to collect declared prefab dependencies.
  • Enqueues any dependencies that are null or not already in prefabSet into the provided queue as QueueItem (child dependency, parent prefab, parent component), and clears the dependencies list per-component.
  • Clears components list before returning.

Notes: Exceptions during Initialize are logged with COSystemBase.baseLog.ErrorFormat along with prefab name and asset info.

  • private void LateInitializePrefab(Entity entity, PrefabBase prefab, List<PrefabBase> dependencies, List<ComponentBase> components)
    Per-prefab LateInitialize pass:
  • Determines whether the prefab is unlockable via m_PrefabSystem.IsUnlockable(prefab) and whether it can ignore unlock dependencies (prefab.canIgnoreUnlockDependencies).
  • Gathers components for the prefab and finds the UnlockableBase component if the prefab is unlockable.
  • For each component (except the UnlockableBase itself) calls LateInitialize(EntityManager, entity) and conditionally collects dependencies unless they are to be ignored due to unlock settings.
  • If the prefab is unlockable, calls either unlockableBase.LateInitialize(EntityManager, entity, dependencies) or UnlockableBase.DefaultLateInitialize(EntityManager, entity, dependencies) inside try/catch to handle errors.
  • Clears components and dependencies lists.

Purpose: performs second-phase initialization where dependencies and unlockable-specific initialization are handled.

  • private void __AssignQueries(ref SystemState state)
    Compiler-generated helper used during OnCreateForCompiler to assign any query-related objects. In this class the method creates and disposes an EntityQueryBuilder(Allocator.Temp) (likely placeholder to satisfy generated code patterns).

  • protected override void OnCreateForCompiler()
    Compiler helper invoked during system creation to wire up cached type handles and queries. Calls __AssignQueries and assigns handles in __TypeHandle via __AssignHandles.

  • private void __AssignHandles(ref SystemState state) (method on nested TypeHandle)
    Assigns EntityTypeHandle and ComponentTypeHandle from the SystemState so chunk access can be done efficiently during OnUpdate. Marked AggressiveInlining.

Usage Example

This system runs automatically as part of the ECS world. It processes entities that have been created with a PrefabData component and a Created tag. Example (conceptual) showing how a prefab entity would be created so PrefabInitializeSystem picks it up:

// Conceptual example: create an entity that represents a prefab so the PrefabInitializeSystem will initialize it.
// Exact construction of PrefabData depends on the game's prefab registration API.

var em = World.DefaultGameObjectInjectionWorld.EntityManager;
Entity prefabEntity = em.CreateEntity();

// Suppose PrefabData has an implicit constructor or factory; replace with actual code to obtain/populate PrefabData:
PrefabData prefabData = /* obtain or construct PrefabData that references your prefab */;

em.AddComponentData(prefabEntity, prefabData);
em.AddComponent(prefabEntity, typeof(Created));

// After this, PrefabInitializeSystem will see the entity, call Initialize() on each Prefab component,
// queue and add any dependent prefabs through PrefabSystem, and run LateInitialize() accordingly.

Notes and tips: - Exceptions thrown by component Initialize/LateInitialize are caught and logged per-prefab; use those logs to debug initialization problems. - Prefab dependencies are processed breadth-first and will be added to PrefabSystem; dependent prefab addition may result in new entities that are also initialized in the same OnUpdate. - Unlockable prefabs receive special handling so that unlock-related dependencies can be deferred/overridden by UnlockableBase.