Skip to content

Game.UI.InGame.UniqueAssetTrackingSystem

Assembly: Game (Game.dll)
Namespace: Game.UI.InGame

Type: public class

Base: GameSystemBase, implements IUniqueAssetTrackingSystem

Summary:
Tracks "unique" placeable assets (unique objects/prefab instances) in the game world. The system maintains a persistent NativeParallelHashSet of placed unique assets and raises an event when a unique asset is placed or removed. It builds EntityQueries to detect loaded, newly created (placed) and deleted unique assets and updates its internal set accordingly. The system also supports a short "loaded" phase after a game load to report already-placed unique assets once after loading completes.


Fields

  • private EntityQuery m_LoadedUniqueAssetQuery
    Used to query unique objects that are present (UniqueObject + PrefabRef) and not marked Temp. This query is checked during updates to register assets that were loaded with the game.

  • private EntityQuery m_DeletedUniqueAssetQuery
    Query for unique objects that have been deleted (UniqueObject + PrefabRef + Deleted, excluding Temp). Entities matching this query are removed from the placedUniqueAssets set and trigger a "removed" event.

  • private EntityQuery m_PlacedUniqueAssetQuery
    Query for unique objects that were created/placed during runtime (UniqueObject + PrefabRef + Created, excluding Temp). Entities matching this query are added to the placedUniqueAssets set and trigger a "placed" event.

  • private bool m_Loaded
    Internal flag used to defer handling of loaded unique assets until the first update after a load. OnGameLoaded sets this flag; GetLoaded() flips and returns it so loaded assets are only processed once.

  • public NativeParallelHashSet<Entity> placedUniqueAssets { get; private set; }
    Persistent NativeParallelHashSet that contains Entities corresponding to placed/active unique assets. Allocated with Allocator.Persistent in OnCreate and disposed in OnDestroy. Can be queried by other systems to check if an Entity is a placed unique asset (but must be used with care because it is a native container).

  • public Action<Entity, bool> EventUniqueAssetStatusChanged { get; set; }
    Event invoked when a unique asset is added or removed. The first parameter is the asset Entity, the second parameter is a bool: true => placed/active, false => removed/deleted. Can be subscribed to by other systems/mods to react to unique asset placement/removal.

Properties

  • public NativeParallelHashSet<Entity> placedUniqueAssets { get; private set; }
    Exposes the hash set of placed unique assets (readable publicly, privately set by the system). The hash set is persistent and must not be disposed by consumers.

  • public Action<Entity, bool> EventUniqueAssetStatusChanged { get; set; }
    Event property for status change notifications (see Fields above).

Constructors

  • public UniqueAssetTrackingSystem()
    [Preserve] attribute applied. Default constructor — no custom initialization beyond what the base system does; real initialization happens in OnCreate. The [Preserve] attribute ensures the constructor is preserved by code stripping.

Methods

  • protected override void OnCreate() : System.Void
    [Preserve] Creates the EntityQueries used to detect loaded, created, and deleted unique assets:
  • m_LoadedUniqueAssetQuery: UniqueObject + PrefabRef, excluding Temp
  • m_DeletedUniqueAssetQuery: UniqueObject + PrefabRef + Deleted, excluding Temp
  • m_PlacedUniqueAssetQuery: UniqueObject + PrefabRef + Created, excluding Temp
    Also allocates placedUniqueAssets = new NativeParallelHashSet(32, Allocator.Persistent).

  • protected override void OnDestroy() : System.Void
    [Preserve] Disposes placedUniqueAssets and then calls base.OnDestroy(). Important to avoid Native container leaks.

  • private bool GetLoaded() : System.Boolean
    Internal helper used to implement a one-time processed "loaded" state. If m_Loaded is true, flips it to false and returns true; otherwise returns false.

  • protected override void OnUpdate() : System.Void
    [Preserve] Core update logic run each frame:

  • If GetLoaded() returns true and m_LoadedUniqueAssetQuery is not empty, iterate PrefabRef components from that query and add their Entities to placedUniqueAssets and invoke EventUniqueAssetStatusChanged(..., true). This ensures assets that existed at game load are reported once.
  • Iterate m_PlacedUniqueAssetQuery to add newly created/placed unique assets and invoke EventUniqueAssetStatusChanged(..., true).
  • Iterate m_DeletedUniqueAssetQuery to remove deleted unique assets from the set and invoke EventUniqueAssetStatusChanged(..., false).
  • All component arrays are retrieved via ToComponentDataArray(Allocator.TempJob) and disposed after use.

  • protected override void OnGameLoaded(Context serializationContext) : System.Void
    Called when a game is loaded. Clears the placedUniqueAssets set and sets m_Loaded = true so OnUpdate will report already-placed unique assets on the next update.

  • public bool IsUniqueAsset(Entity entity) : System.Boolean
    Checks whether the given Entity represents a unique placeable asset by trying to get PlaceableObjectData from the EntityManager and testing the PlacementFlags.Unique bit in component.m_Flags. Returns true if the Unique flag is present.

  • public bool IsPlacedUniqueAsset(Entity entity) : System.Boolean
    Returns true if the entity is a unique asset (IsUniqueAsset(entity) == true) and it is contained in placedUniqueAssets. Otherwise false.

Usage Example

// Example: how to subscribe to events and query the system from another system or mod class.

[Preserve]
protected override void OnCreate()
{
    base.OnCreate();

    var trackingSystem = World.GetOrCreateSystem<UniqueAssetTrackingSystem>();
    // Subscribe to notifications when unique assets are placed or removed.
    trackingSystem.EventUniqueAssetStatusChanged += OnUniqueAssetStatusChanged;
}

private void OnUniqueAssetStatusChanged(Entity assetEntity, bool placed)
{
    if (placed)
    {
        // A unique asset was placed or detected after load.
        Debug.Log($"Unique asset placed: {assetEntity}");
    }
    else
    {
        // A unique asset was removed/deleted.
        Debug.Log($"Unique asset removed: {assetEntity}");
    }
}

// Example check: determine whether a specific entity is a placed unique asset.
public void SomeMethod(Entity entity)
{
    var trackingSystem = World.GetExistingSystem<UniqueAssetTrackingSystem>();
    if (trackingSystem != null && trackingSystem.IsPlacedUniqueAsset(entity))
    {
        // Do something with the placed unique asset...
    }
}

// Cleanup (unsubscribe) is recommended on destroy to avoid dangling handlers:
protected override void OnDestroy()
{
    var trackingSystem = World.GetExistingSystem<UniqueAssetTrackingSystem>();
    if (trackingSystem != null)
        trackingSystem.EventUniqueAssetStatusChanged -= OnUniqueAssetStatusChanged;

    base.OnDestroy();
}

Additional notes and tips: - placedUniqueAssets is a NativeParallelHashSet with Allocator.Persistent. Do not dispose it from outside the system; rely on the system's OnDestroy to free it. - EventUniqueAssetStatusChanged provides a simple notification mechanism; subscribers should be careful about thread context (events are raised during the system's OnUpdate on the main thread). - IsUniqueAsset uses PlaceableObjectData and PlacementFlags.Unique — this is the authoritative check for whether a placeable entity is considered "unique".