Game.Serialization.ResolvePrefabsSystem
Assembly: Assembly-CSharp
Namespace: Game.Serialization
Type: class
Base: GameSystemBase
Summary:
ResolvePrefabsSystem is a runtime ECS system used during game load to reconcile and "resolve" prefab entities that were referenced/loaded from save data. It collects currently loaded prefab entities, maps loaded indices to live entities, copies over certain runtime budget/fee/upkeep data between original and loaded prefab entities, fixes zone-type references for zone cells/vacant lots, and enqueues component additions/removals (e.g., placed signature building component) as needed. The system schedules several Burst-compiled IJobChunk jobs to process chunks in parallel and coordinates with other systems such as LoadGameSystem, PrefabSystem, UpdateSystem, and CheckPrefabReferencesSystem to complete prefab resolution during the load process.
Fields
-
private LoadGameSystem m_LoadGameSystem
Reference to the LoadGameSystem; used to access load context (e.g., Purpose.LoadGame) and coordinate behavior when resolving prefabs during a load. -
private PrefabSystem m_PrefabSystem
Reference to the PrefabSystem; used to look up loaded/obsolete prefab IDs and to register obsolete IDs after resolving. -
private UpdateSystem m_UpdateSystem
Reference to the UpdateSystem, used to trigger updates for the PrefabReferences phase. -
private CheckPrefabReferencesSystem m_CheckPrefabReferencesSystem
Reference to the system that validates and updates prefab references; this ResolvePrefabsSystem begins and ends a prefab reference check during its update. -
private EntityQuery m_ActualPrefabQuery
EntityQuery matching prefab entities that have LoadedIndex (actual loaded prefabs); used to operate on prefabs that represent the actual in-world prefab instances. -
private EntityQuery m_EnabledLoadedPrefabQuery
EntityQuery for enabled loaded prefabs: PrefabData present but no LoadedIndex (i.e., prefabs that are loaded but not yet marked as "actual" with LoadedIndex). Used to build temporary arrays of loaded entities. -
private EntityQuery m_AllLoadedPrefabQuery
EntityQuery for all loaded prefabs (PrefabData without LoadedIndex). Used to destroy duplicate/obsolete loaded prefab entities once resolution is finished. -
private EntityQuery m_LoadedZonePrefabQuery
EntityQuery for loaded prefabs that also have ZoneData (and are not LoadedIndex); used when filling mapping of zone types. -
private EntityQuery m_LoadedZoneCellQuery
EntityQuery for Cell buffers; used by the job that fixes zone types for zone cells. -
private EntityQuery m_ActualBudgetQuery
EntityQuery used to find prefabs that have budget/fee/upkeep data and LoadedIndex so CopyBudgetDataJob can transfer runtime-collected city service data between the old and new prefab entities. -
private TypeHandle __TypeHandle
A generated container holding various Entity/Component/Buffer type handles and lookups used by the jobs. Assigned in OnCreateForCompiler.
Properties
- None (no public properties exposed by this system).
Constructors
public ResolvePrefabsSystem()
Default constructor. Marked with [Preserve] in source to avoid stripping; actual initialization happens in OnCreate / OnCreateForCompiler where queries, handles and system references are set up.
Methods
-
protected override void OnCreate()
Initializes references to other systems (LoadGameSystem, PrefabSystem, UpdateSystem, CheckPrefabReferencesSystem) and constructs the EntityQuery instances used during OnUpdate. Prepares queries to find loaded prefabs, zone prefabs, budget-related prefabs, and cell buffers. -
protected override void OnUpdate()
Main runtime logic executed each frame/update while the system runs. High-level flow: - Allocates temporary NativeArray/NativeQueue buffers (entity mapping array, prefab component flags array, zone type array, queue for component modifications).
- Schedules parallel Burst jobs:
- FillLoadedPrefabsJob: populates a NativeArray mapping prefab indices to Entity and collects simple PrefabComponents flags (e.g., Locked, PlacedSignatureBuilding).
- CopyBudgetDataJob: copies budget/fee/upkeep collected city service data from original prefab entities to the loaded ones.
- CheckActualPrefabsJob: determines actual prefab components required on the "actual"/existing prefab entities and enqueues Add/Remove component operations into a NativeQueue.
- FillZoneTypeArrayJob: builds an array mapping zone type indices based on loaded zone prefabs.
- FixZoneTypeJob: updates Cell and VacantLot buffers to point to corrected zone types.
- Calls PrefabSystem.UpdateLoadedIndices() and coordinates with CheckPrefabReferencesSystem.BeginPrefabCheck/EndPrefabCheck to ensure prefab references are validated.
- Temporarily disables PrefabData component on various queries to avoid re-entrancy.
- Dequeues component modifications and applies them via AddOrRemoveComponent.
- Converts enabled loaded prefabs into LoadedIndex-marked prefabs, updating PrefabData.m_Index to an obsolete index and registering obsolete IDs with PrefabSystem.
-
Destroys leftover loaded prefabs that are not needed and disposes temporary arrays/queues.
-
private void AddOrRemoveComponent(ComponentModification componentModification, PrefabComponents mask, ComponentType type)
Helper that applies a single component add/remove action to an EntityManager based on the bitmask results. If the mask is present in m_Remove, the component is removed; otherwise if in m_Add it gets added. -
private void __AssignQueries(ref SystemState state)
Compiler/generated helper. In the provided code it instantiates and disposes an EntityQueryBuilder; present to satisfy codegen requirements. Invoked from OnCreateForCompiler. -
protected override void OnCreateForCompiler()
Compiler hook that calls __AssignQueries and assigns type handles via the TypeHandle struct. Ensures the TypeHandle fields are initialized for subsequent job usage. -
private struct ComponentModification
Nested struct representing an enqueued modification (Entity + PrefabComponents add-mask + remove-mask). Used by jobs to indicate component changes that must be applied on the main thread. -
private struct TypeHandle { void __AssignHandles(ref SystemState state) }
Generated struct containing all Entity/Component/Buffer type handles and lookups consumed by the jobs. __AssignHandles resolves and stores handles from the provided SystemState. -
Job Execute methods (Burst-compiled IJobChunk implementations):
FillLoadedPrefabsJob.Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
Builds arrays mapping prefab indices to loaded Entities and records whether each prefab has PlacedSignatureBuilding and Locked flags (based on component enabled state).CheckActualPrefabsJob.Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
For each candidate prefab entity, inspects LoadedIndex buffers to determine the referenced "actual" prefab entity. Computes required PrefabComponents and enqueues a ComponentModification when differences are detected. Also uses LoadGame context to preserve Locked flags when loading.CopyBudgetDataJob.Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
Copies runtime-collected city service budget/fee/upkeep data from original prefab entities to the corresponding loaded entities (matches by mapped prefab index).FillZoneTypeArrayJob.Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
Builds an array mapping zone type indices by checking ZoneData on loaded zone prefabs; used to remap Cell and VacantLot zone types when resolving prefabs.FixZoneTypeJob.Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
Applies the zone-type remapping to Cell and VacantLot buffers so that zone cells reference correct zone types after prefabs are resolved.
Usage Example
// The ResolvePrefabsSystem is normally created and managed by the game's Worlds/System injection.
// You can obtain and (if required) manually update it like this in a mod initialization context:
var world = Unity.Entities.World.DefaultGameObjectInjectionWorld;
var resolveSystem = world.GetOrCreateSystemManaged<Game.Serialization.ResolvePrefabsSystem>();
// Normally you do not need to call Update manually; the game runs systems automatically.
// But for testing you can force an update (runs the OnUpdate logic):
resolveSystem.Update();
// The system coordinates with PrefabSystem and LoadGameSystem during load to map saved prefab indices
// to runtime Entities, copy budget/fee/upkeep data, and fix zone-type references.
Notes and tips for modders - This system runs as part of the load/resolve sequence; be careful when modifying PrefabData, LoadedIndex, or related components during load — it may interfere with the resolution process. - The system uses low-level ECS constructs (IJobChunk, ComponentLookup, BufferLookup, enabled component masks). When creating your own systems that interact with prefabs during load, follow similar patterns for safety and performance. - If you need to extend behavior (e.g., add a new prefab-related component that should be preserved/propagated when prefabs are resolved), consider hooking into the job pipeline or adding a separate system that runs in the PrefabReferences update phase (UpdateSystem.SystemUpdatePhase.PrefabReferences).