Skip to content

Game.Notifications.IconClusterSystem

Assembly: Game (Assembly-CSharp)
Namespace: Game.Notifications

Type: class

Base: GameSystemBase, IPreDeserialize

Summary: IconClusterSystem gathers notification icons (Icon components) and groups them into spatial clusters for efficient rendering/processing. It maintains a quadtree of clusters, allocates storage for cluster icons, merges nearby icons into clusters (including special handling for temporary icons and moving groups), and exposes a read-only ClusterData view for other systems via job dependencies. The system is Burst-compatible for core clustering jobs and uses Unity.Collections native containers and Jobs to run most work off the main thread. It also supports pre-deserialization (loading) so clusters are recomputed after load.


Fields

  • private Unity.Entities.EntityQuery m_IconQuery
    Holds a query that selects non-temporary, non-deleted, cluster-eligible Icon entities. Used to enumerate all icons when fully rebuilding clusters.

  • private Unity.Entities.EntityQuery m_ModifiedQuery
    Query selecting Icon entities that have been modified (Updated or Deleted). Used to drive incremental updates.

  • private Unity.Entities.EntityQuery m_ModifiedAndTempQuery
    Query selecting Icon entities that are temporary or modified. Used during incremental processing where temporary icons must be handled.

  • private NativeQuadTree<int, TreeBounds> m_ClusterTree
    Quadtree storing cluster bounds indexed by cluster index. Used for spatial searches when pairing/merging clusters.

  • private NativeHeapAllocator m_IconAllocator
    Heap-style allocator used for cluster icon storage. Allocations return NativeHeapBlock describing where cluster icons are stored in m_ClusterIcons.

  • private NativeList<IconCluster> m_IconClusters
    List of IconCluster structures representing all clusters (root + internal clusters). index 0 is reserved/empty.

  • private NativeList<ClusterIcon> m_ClusterIcons
    Flat array of ClusterIcon entries. IconCluster stores a NativeHeapBlock with Begin/Size to reference a contiguous range in this list.

  • private NativeList<int> m_RootClusters
    List of cluster indices considered roots for the current frame / tree levels.

  • private NativeList<int> m_FreeClusterIndices
    Pool of free cluster indices for reuse when clusters are removed.

  • private Unity.Jobs.JobHandle m_ClusterReadDeps
    Combined JobHandle representing readers that depend on cluster data. Used to chain job dependencies for safe concurrent reads.

  • private Unity.Jobs.JobHandle m_ClusterWriteDeps
    JobHandle representing the job writing/updating cluster data. Readers get combined dependency with this to ensure correctness.

  • private bool m_Loaded
    Flag set during PreDeserialize to force a full rebuild on the next update (used when loading save data).

  • private TypeHandle __TypeHandle
    Internal generated struct containing Entity/Component type handles used to build job data (assigned in OnCreate/OnCreateForCompiler).

Properties

  • None (this system exposes cluster data through GetIconClusterData rather than public properties).

Constructors

  • public IconClusterSystem()
    Default constructor. The system performs native allocations in OnCreate; constructor itself is preserved/empty.

Methods

  • protected override void OnCreate()
    Initializes entity queries and allocates persistent native containers: quadtree, heap allocator, and lists. Adds a placeholder IconCluster at index 0 and resizes m_ClusterIcons to match the initial allocator size.

  • protected override void OnDestroy()
    Disposes/cleans up all created native containers. Completes outstanding read/write job dependencies before disposal to avoid race conditions. Calls base.OnDestroy().

  • protected override void OnUpdate()
    Core update loop. If there are new/modified icons (based on queries), schedules two jobs:

  • IconChunkJob: iterates icon archetype chunks, collects temp icons and orphans, and prepares per-chunk updates.
  • IconClusterJob: processes orphaned clusters and temporary clusters to add/merge clusters and update the quadtree. Manages job dependency wiring, disposes temporary lists using job handles, and updates internal job dependency fields.

  • public void PreDeserialize(Context context)
    Called before deserialization (e.g., loading). Clears existing cluster data and sets m_Loaded = true so OnUpdate will perform a full rebuild.

  • public ClusterData GetIconClusterData(bool readOnly, out JobHandle dependencies)
    Returns a ClusterData view (struct with references to m_IconClusters, m_ClusterIcons, and m_RootClusters) along with a JobHandle representing the required dependency callers must respect. If readOnly == true the returned dependencies are the writer handle; otherwise it combines read and write dependencies. Consumers must Complete the handle (or include in their job dependency) before reading/writing.

  • public void AddIconClusterReader(JobHandle jobHandle)
    Adds a reader dependency so the system waits for that job in subsequent writes. Combines the provided jobHandle into m_ClusterReadDeps.

  • public void AddIconClusterWriter(JobHandle jobHandle)
    Sets m_ClusterWriteDeps to the provided jobHandle (the external writer). Used to chain external writers into the system's scheduling.

  • public void RecalculateClusters()
    Marks the system to fully rebuild clusters on the next update (sets m_Loaded = true).

  • private void ClearData()
    Internal helper to reset cluster structures. Completes read/write job dependencies, clears the quadtree and allocator, and resets lists to the empty initial state (keeps a placeholder index 0).

  • private bool GetLoaded()
    Helper that returns true once if m_Loaded is set; after calling it clears the flag. Used to detect when a full rebuild is required.

  • protected override void OnCreateForCompiler()
    Generated method used by the compiled codepath to assign query/type handle boilerplate. Calls __AssignQueries and assigns handles from __TypeHandle.

  • private void __AssignQueries(ref SystemState state)
    Generated stub for query assignment; currently empty aside from a temp builder call (kept to satisfy compiler generation).

  • Additional nested types and job structs:

  • ClusterData (struct): view returned by GetIconClusterData. Provides helpers GetRoot, GetCluster, GetIcons.
  • IconCluster (struct): represents a cluster, contains center/size/level/prefabIndex/layer/flags, icon allocation metadata, helpers to compute radius/bounds and to check whether to keep cluster at a given distance.
  • ClusterIcon (struct): single icon entry stored in m_ClusterIcons (entity, prefab, order, priority, flags).
  • TempIconCluster (struct): temporary cluster used during clustering step; comparable for sorting.
  • TreeBounds (struct): quadtree item bounds + level/layer masks; implements necessary interface for quadtree.
  • IconChunkJob (Burst-compiled IJob): collects icons from archetype chunks into temp buffers and marks orphans; runs concurrently with minimal main-thread interaction.
  • IconClusterJob (Burst-compiled IJob): consumes orphans and temp icon buffers to form/merge clusters and update quadtree.
  • IconData (struct): encapsulates cluster data and the logic to allocate icons, merge clusters, handle orphans and temp clusters. Many private helpers sit here (AllocateIcons, AddIcon, GetNewClusterIndex, Remove, HandleOrphans, HandleTemps, etc.).
  • TypeHandle (struct): generated container for ComponentTypeHandle and ComponentLookup instances used by jobs.

Notes about threading and safety: - Consumers must respect the returned JobHandle from GetIconClusterData before reading the returned ClusterData (or add their jobs using AddIconClusterReader/Writer). - All heavy clustering work is done in jobs (Burst) and uses NativeCollections; the system manages job handles to coordinate reads/writes to cluster data.

Usage Example

// Example: safely read cluster data from another system/job
void SomeMethod(IconClusterSystem iconSystem)
{
    // Request read-only access and get the dependency handle
    Unity.Jobs.JobHandle deps;
    var clusterData = iconSystem.GetIconClusterData(readOnly: true, out deps);

    // If you want to read immediately on main thread:
    deps.Complete();

    // Iterate root clusters
    int idx = 0;
    IconCluster cluster;
    while (clusterData.GetRoot(ref idx, out cluster))
    {
        // Use cluster.center, cluster.GetBounds(distance, cameraUp), etc.
        UnityEngine.Vector3 center = new UnityEngine.Vector3(cluster.center.x, cluster.center.y, cluster.center.z);
        // To access icons of that cluster:
        int firstIcon, iconCount;
        var allocation = cluster.GetIcons(out firstIcon, out iconCount);
        var icons = allocation.GetIcons(clusterData); // or cluster.GetIcons(clusterData)
        for (int i = 0; i < iconCount; i++)
        {
            var ci = icons[i];
            // ci.icon, ci.prefab, ci.priority, ci.flags
        }
    }

    // Alternatively, schedule a job that depends on 'deps' and call
    // iconSystem.AddIconClusterReader(yourJobHandle) so the system tracks the new dependency.
}

If you need examples for writing/modifying cluster data from jobs, ensure you: - Request non-readOnly cluster data (GetIconClusterData(readOnly: false, out deps)) and include the returned dependency in your job dependency chain. - Use AddIconClusterReader / AddIconClusterWriter to register your job handles with IconClusterSystem so it can combine them with its internal scheduling.