Game.Rendering.AggregateMeshSystem
Assembly:
Namespace: Game.Rendering
Type: class
Base: GameSystemBase
Summary:
AggregateMeshSystem is an ECS system responsible for generating and managing aggregated meshes and materials for network labels (names) and lane/turn arrows in the rendering pipeline. It collects per-entity text/arrow vertex data, schedules Jobs (Burst-compiled) to build GPU-ready MeshData, creates Unity Mesh/Material instances when needed, and exposes methods to retrieve meshes/materials for rendering overlays. The system works with several queries, uses Unity.Jobs and Burst for heavy work, and integrates with other game systems (PrefabSystem, NameSystem, OverlayRenderSystem, UndergroundViewSystem, ToolSystem).
Fields
-
private EntityQuery m_CreatedPrefabQuery
Holds entities for newly created aggregate prefabs (used to initialize per-prefab material/mesh data). -
private EntityQuery m_UpdatedLabelQuery
Query for aggregates with LabelMaterial and updated/batched/deleted markers used to update label geometry. -
private EntityQuery m_LabelQuery
Query for current label aggregates (excludes Deleted) used to collect data when building meshes. -
private EntityQuery m_UpdatedArrowQuery
Query for aggregates with ArrowMaterial and updated/batched/deleted markers used to update arrow geometry. -
private EntityQuery m_ArrowQuery
Query for current arrow aggregates (excludes Deleted) used to collect arrow data when building meshes. -
private EntityQuery m_TempAggregatedQuery
Query used to build a temporary mapping when handling Temp/Aggregated entities (used for arrow placement when temporary edges replace originals). -
private OverlayRenderSystem m_OverlayRenderSystem
Reference to overlay rendering helper used to copy font atlas parameters and get TextMeshPro instance. -
private UndergroundViewSystem m_UndergroundViewSystem
Used to determine underground/tunnel view state to select underground vs. normal materials and transparency. -
private PrefabSystem m_PrefabSystem
Reference to PrefabSystem for accessing prefab components and AggregateNetPrefab. -
private NameSystem m_NameSystem
Used to produce rendered label strings for entities (taking localization & formatting into account). -
private ToolSystem m_ToolSystem
Used to determine editor mode / tool state (affects arrow placement logic). -
private List<MeshData> m_LabelData
Per-label-material mesh management data (contains original material ref, mutable MaterialData list, Mesh, MeshDataArray, flags, job handle dependencies, etc.). -
private List<MeshData> m_ArrowData
Per-arrow-material mesh management data (similar to m_LabelData but for arrows). -
private Dictionary<Entity, string> m_CachedLabels
Cache of last rendered label string per entity to avoid rebuilding label geometry if text didn't change. -
private int m_FaceColor
Shader property id (Shader.PropertyToID) used to apply face color/alpha on generated materials. -
private bool m_TunnelSelectOn
Tracks last-known underground/tunnel toggle state to update materials' transparency when the view toggles. -
private bool m_Loaded
Flag set during PreDeserialize to indicate a one-time "loaded" update pass is required. -
private TypeHandle __TypeHandle
Internal struct that caches ComponentTypeHandle/BufferTypeHandle/ComponentLookup handles used by jobs and query scheduling.
Properties
- No public properties. (All state is managed internally; the system exposes explicit Get* methods for meshes/materials and counts.)
Constructors
public AggregateMeshSystem()
Default constructor. The system is instantiated by the ECS world; initialization logic happens in OnCreate.
Methods
-
protected override void OnCreate()
Setups queries, caches system references (OverlayRenderSystem, UndergroundViewSystem, PrefabSystem, NameSystem, ToolSystem), registers localization change callback, and initializes Shader property ids. -
protected override void OnDestroy()
Cleans up created Mesh and Material objects and unregisters callbacks. Calls DestroyMeshData for label and arrow data. -
public void PreDeserialize(Context context)
Called before scene/entity deserialization. Clears mesh state and cached labels to ensure meshes/materials are rebuilt after load. -
protected override void OnUpdate()
Main update loop: checks created prefabs to initialize per-prefab materials, detects if label/arrow queries have work, updates underground material state, schedules jobs to compute label/arrow positions and fills MeshData via FillName/FillArrow jobs, and manages job dependencies. -
private void InitializePrefabs()
Runs on newly created prefab entities. Finds NetLabel/NetArrow components on prefabs, creates MeshData and initial MaterialData instances (including separate underground variants), sets material indices in NetNameData/NetArrowData components. -
private void UpdateLabelVertices(bool isLoaded)
Iterates label query chunks, uses TextMeshPro via OverlayRenderSystem to generate per-character vertex data for each label, builds LabelVertex buffers, creates/assigns per-texture materials for label atlases, marks related MeshData as dirty when text or material mappings change, and updates shared LabelMaterial indices on entities as needed. -
private void UpdateArrowMaterials(bool isLoaded)
Iterates arrow query chunks and ensures ArrowMaterial shared components are up-to-date. Marks Arrow MeshData as dirty when needed. -
private JobHandle UpdateLabelPositions(JobHandle inputDeps, bool isLoaded)
Schedules the Burst IJobChunk UpdateLabelPositionsJob which computes placement (LabelPosition buffers) for each aggregate (chooses where along aggregated edges to place each label) and returns a JobHandle for dependency chaining. -
private JobHandle UpdateArrowPositions(JobHandle inputDeps, bool isLoaded)
Builds a temporary mapping for Temp/Aggregated entities (FillTempMapJob) and schedules UpdateArrowPositionsJob to compute ArrowPosition buffers that place arrows along aggregates. Returns JobHandle and ensures temporary map disposal is chained. -
private JobHandle FillNameMeshData(JobHandle inputDeps)
For each dirty label MeshData, collects matching archetype chunks into a NativeList and schedules FillNameDataJob (IJob) which allocates vertex/index buffers in MeshDataArray for all labels of that material. Stores job handle in MeshData for later completion. -
private JobHandle FillArrowMeshData(JobHandle inputDeps)
For each dirty arrow MeshData, collects matching archetype chunks into a NativeList and schedules FillArrowDataJob (IJob) which builds arrow vertex/index buffers in MeshDataArray. Stores job handle in MeshData for later completion. -
private void DestroyMeshData(List<MeshData> meshData)
Frees/destroys all Mesh and Material objects created by the system and disposes MeshDataArray where allocated. -
private void ClearMeshData(List<MeshData> meshData)
Marks existing MeshData entries as having no mesh (m_HasMesh = false), destroys any cached Mesh object and disposes MeshDataArray so they will be rebuilt later (used on PreDeserialize/load). -
private void UpdateUndergroundState(List<MeshData> meshData, bool undergroundOn)
Iterates meshData materials and updates their face-color alpha to the appropriate transparency for underground view toggling. -
private void OnDictionaryChanged()
Callback for localization dictionary change; marks label query entities as Updated so label text will be regenerated with the new language. -
private bool GetLoaded()
Internal helper used to read and reset m_Loaded flag, indicating a one-time loaded pass. -
public int GetNameMaterialCount()
Returns number of distinct label/material groups that have been initialized (m_LabelData.Count) — used by renderers to know how many material variants exist. -
public int GetArrowMaterialCount()
Returns number of distinct arrow material groups (m_ArrowData.Count). -
public bool GetNameMesh(int index, out Mesh mesh, out int subMeshCount)
If the specified label MeshData has produced MeshDataArray results, completes the job dependencies, applies MeshData to a Unity Mesh and returns it and the subMesh count. Returns true if the mesh contains any geometry. -
public bool GetNameMaterial(int index, int subMeshIndex, out Material material)
Retrieves the generated Material instance for the requested label material submesh and returns whether it contains geometry (m_HasMesh). -
public bool GetArrowMesh(int index, out Mesh mesh, out int subMeshCount)
Same as GetNameMesh but for arrow meshes. -
public bool GetArrowMaterial(int index, int subMeshIndex, out Material material)
Same as GetNameMaterial but for arrow materials. -
plus several internal nested types and Burst jobs (UpdateLabelPositionsJob, FillTempMapJob, UpdateArrowPositionsJob, FillNameDataJob, FillArrowDataJob) used to compute positions and fill MeshDataArray. These are Burst-compiled for performance and operate on ComponentLookups, BufferLookups and chunk data.
Usage Example
// Get the system from the world (example; call from your mod initialization or a MonoBehaviour)
var world = World.DefaultGameObjectInjectionWorld;
var aggregateSystem = world.GetExistingSystemManaged<Game.Rendering.AggregateMeshSystem>();
// Query how many label/arrow material groups exist
int nameMatCount = aggregateSystem.GetNameMaterialCount();
int arrowMatCount = aggregateSystem.GetArrowMaterialCount();
// Retrieve a mesh and material if available (index 0 used as an example)
if (nameMatCount > 0 && aggregateSystem.GetNameMesh(0, out Mesh nameMesh, out int nameSubCount))
{
// nameMesh is a Unity Mesh ready for rendering; get its material(s)
for (int s = 0; s < nameSubCount; s++)
{
if (aggregateSystem.GetNameMaterial(0, s, out Material mat))
{
// Use nameMesh and mat with Graphics.DrawMesh or a custom renderer
}
}
}
Notes: - Many operations are asynchronous (jobs). Callers retrieving meshes should expect that GetNameMesh/GetArrowMesh will complete job dependencies and produce the final Mesh only when data was available. - Materials and Mesh instances created by this system are owned by the system and will be destroyed in OnDestroy; do not destroy them yourself. - This system integrates tightly with the game's ECS components (LabelVertex, LabelPosition, ArrowPosition, NetNameData, NetArrowData, PrefabRef, Temp, Aggregated, etc.). Use the provided public getters for rendering and avoid manipulating internal buffers directly unless you are familiar with the ECS/data ownership patterns.