Skip to content

Game.Areas.GeometrySystem

Assembly: Game
Namespace: Game.Areas

Type: class

Base: GameSystemBase

Summary: GeometrySystem is a core ECS system responsible for generating and updating polygonal area geometry used by rendering and simulation. It collects area node buffers, triangulates polygons (including holes and slave areas), computes triangle height ranges against terrain and water, generates Geometry component data (bounds, center, surface area and LOD-related info), and schedules the heavy work as a Burst-compiled IJobParallelForDefer (TriangulateAreasJob). The system responds to updated area entities as well as full reloads (terrain heights / loading) and integrates with TerrainSystem and WaterSystem to sample heights safely and efficiently.


Fields

  • private TerrainSystem m_TerrainSystem
    GeometrySystem's reference to the TerrainSystem. Used to obtain TerrainHeightData for height sampling and to register CPU height readers for job synchronization.

  • private WaterSystem m_WaterSystem
    Reference to the WaterSystem. Used to obtain water surface data for areas flagged to use water height.

  • private EntityQuery m_UpdatedAreasQuery
    EntityQuery to select areas that have been marked Updated; used to limit work to changed areas during normal updates.

  • private EntityQuery m_AllAreasQuery
    EntityQuery selecting all area entities (Area + Node + Triangle). Used when a full rebuild is required (e.g., after loading terrain heights).

  • private EntityQuery m_CreatedBuildingsQuery
    EntityQuery selecting recently created Building entities (Created + Building + Owner, excluding Temp). Used to include building holes when generating slave areas.

  • private bool m_Loaded
    Flag indicating that a full update of all areas should be performed on the next tick (set via OnGameLoaded or TerrainHeightsReadyAfterLoading).

  • private TypeHandle __TypeHandle
    Generated container holding ComponentLookup/BufferLookup handles used by jobs. Assigned in OnCreateForCompiler and used to create ComponentLookup/BufferLookup instances for TriangulateAreasJob.


Properties

  • None exposed publicly.

Constructors

  • public GeometrySystem()
    Default constructor. The system is set up and OnCreate will initialize queries and cached system references.

Methods

  • protected override void OnCreate()
    Initializes references to TerrainSystem and WaterSystem and constructs EntityQuery instances used to find updated/all areas and created buildings. Called when the system is created.

  • protected override void OnGameLoaded(Context serializationContext)
    Sets the internal m_Loaded flag so that the next update does a full rebuild of all area geometry (used after a game load).

  • private bool GetLoaded()
    Helper that returns true if m_Loaded was set and clears the flag. Used to switch between incremental updates and full rebuilds.

  • public void TerrainHeightsReadyAfterLoading()
    Called by external code (TerrainSystem) when terrain heights are available after loading; sets m_Loaded so areas will be fully rebuilt.

  • protected override void OnUpdate()
    Main update entry. Selects either the updated-areas query or the full-areas query (if GetLoaded()), collects matching entities into NativeLists, collects created buildings, constructs and schedules the Burst TriangulateAreasJob to process area geometry, and registers dependencies with TerrainSystem and WaterSystem. Handles disposing of temporary lists and updates the system's Dependency.

  • protected override void OnCreateForCompiler()
    Compiler-time helper that assigns queries and lookup handles; ensures generated TypeHandle is assigned.

  • private void __AssignQueries(ref SystemState state)
    Internal generated method (compiler helper). Present for generated code structure.

  • public static void BuildEdgeBounds(DynamicBuffer<Node> nodes, NativeArray<float3> expandedNodes, out NativeArray<Bounds2> edgeBounds, out int totalDepth)
    Builds a hierarchical set of 2D bounding boxes for node edges to accelerate spatial queries (used when nodes.Length > 20). Produces edgeBounds and the tree depth (totalDepth). Uses a temporary NativeArray and Allocator.Temp.

  • public static void Triangulate<T>(NativeArray<float3> nodes, T triangles, NativeArray<Bounds2> edgeBounds, int totalDepth, bool isCounterClockwise) where T : INativeList<Triangle>
    Ear-clipping triangulation routine for a polygon (with optional precomputed edge bounds for acceleration). Produces a list of Triangle entries in the provided INativeList. Validates and clears triangles on failure.

  • public static float Area(DynamicBuffer<Node> nodes)
    Computes signed planar area (XZ) of a polygon represented by a DynamicBuffer. Positive/negative indicates winding (counterclockwise vs clockwise).

  • public static float Area(NativeArray<SubAreaNode> nodes)
    Overload that computes the signed area for NativeArray.

  • private static bool Snip(NativeArray<float3> nodes, Index index0, Index index1, Index index2, int nodeCount, int totalDepth, NativeArray<Bounds2> edgeBounds, NativeArray<Index> indexBuffer)
    Internal helper for Triangulate: checks whether a candidate triangle can be clipped (no contained points, correct orientation), uses edgeBounds for acceleration if provided.

  • public static void EqualizeTriangles<T>(NativeArray<float3> nodes, T triangles) where T : INativeList<Triangle>
    Post-processing routine that attempts to flip edges to improve triangle quality (minimize skinny triangles), iterating until no improvement or a cap is reached. Uses a NativeParallelHashMap to map edges to triangles.

  • private static bool TurnEdgeIfNeeded<T>(NativeArray<float3> nodes, T triangles, NativeParallelHashMap<int2, int2> edgeMap, int2 index1, int2 index2) where T : INativeList<Triangle>
    Per-edge check and flip operation used by EqualizeTriangles. Replaces two adjacent triangles if flipping their shared edge improves an equalization metric.

  • private static float GetEqualizationValue(NativeArray<float3> nodes, Triangle triangle)
    Computes a numeric quality metric for a triangle used by the equalization step.

Notes about nested job: - The class contains a nested, Burst-compiled TriangulateAreasJob struct (IJobParallelForDefer) that performs the per-area work on worker threads. TriangulateAreasJob: - Reads/writes many component lookups and buffers (Area, Node, Triangle, PrefabRef, Transform, Owner, Building, etc.). - Generates slave areas (GenerateSlaveArea) by copying owner area outlines and inserting holes for objects/buildings. - Expands nodes, optionally builds edge bounds, triangulates, equalizes triangles, updates Area flags (CounterClockwise, NoTriangles), computes triangle height ranges (UpdateHeightRange / GetHeightRange), and calculates Geometry (CalculateGeometry) including LOD limits and center position sampling terrain/water heights. - Interacts with TerrainHeightData and WaterSurfaceData and uses MathUtils/TerrainUtils/WaterUtils helpers.

Usage Example

[Preserve]
protected override void OnCreate()
{
    base.OnCreate();
    // Cache Terrain/Water systems and set up queries as the original system does.
    m_TerrainSystem = base.World.GetOrCreateSystemManaged<TerrainSystem>();
    m_WaterSystem = base.World.GetOrCreateSystemManaged<WaterSystem>();
    m_UpdatedAreasQuery = GetEntityQuery(ComponentType.ReadOnly<Area>(), ComponentType.ReadOnly<Updated>(), ComponentType.ReadOnly<Node>(), ComponentType.ReadWrite<Triangle>());
    m_AllAreasQuery = GetEntityQuery(ComponentType.ReadOnly<Area>(), ComponentType.ReadOnly<Node>(), ComponentType.ReadWrite<Triangle>());
    m_CreatedBuildingsQuery = GetEntityQuery(ComponentType.ReadOnly<Created>(), ComponentType.ReadOnly<Building>(), ComponentType.ReadOnly<Owner>(), ComponentType.Exclude<Temp>());
}

Additional notes for modders: - If you modify an area's node buffer at runtime, mark the entity with the Updated component (or remove Updated after creation) so GeometrySystem will re-triangulate only the changed areas. - For custom area prefabs, set appropriate AreaGeometryData flags (OnWaterSurface) and LodBias to influence geometry generation. - Be careful when changing node buffers from jobs or background threads: node buffers are accessed by geometry jobs; coordinate with the system's scheduling (Dependency) or update entities on the main thread to avoid races. - The triangulation and equalization routines use Native collections and Burst; avoid holding references to these internal arrays beyond the scheduling scope.