Skip to content

Game.Areas.AreaUtils

Assembly:
Assembly-CSharp (typical Unity / Cities: Skylines 2 runtime assembly)
Namespace:
Game.Areas

Type:
public static class

Base:
System.Object

Summary:
Utility static class containing helper functions for working with Area geometry, node math, object placement and spatial queries used by area systems (lots, districts, map tiles, extractors, storage areas, etc.). Includes small helper structs for representing placed objects and internal path-fixing items. Useful for modders who need to query/modify area geometry, place objects inside areas, compute label transforms, or perform collision/intersection checks.


Fields

  • public const float NODE_DISTANCE_TOLERANCE = 0.1f
    Utility constant used as a small tolerance when comparing node distances/positions. Useful to avoid floating point equality issues when working with area nodes.

  • public struct ObjectItem
    Small public struct representing a circular object used when placing many objects inside an area. Contains a Circle2 (radius + position) and an Entity reference to the placed object. Used by placement methods to avoid overlaps.

  • private struct FixPathItem : ILessThan<FixPathItem>
    Internal helper struct used by the path-finding routine (FindAreaPath). Holds a PathNode, a PathElement and a cost for use in a min-heap. Implements ILessThan for heap ordering.

Properties

  • None (static utility class — no instance properties)

Constructors

  • (none) — AreaUtils is a static class; no public constructors. All members are static.

Methods

  • public static float GetMinNodeDistance(AreaGeometryData areaData)
    Returns a minimum node distance for an area based on areaData.m_SnapDistance (half the snap distance). Useful when editing or snapping nodes.

  • public static Triangle3 GetTriangle3(DynamicBuffer<Node> nodes, Triangle triangle)
    Builds a Triangle3 from node positions given a Triangle (indices). Returns the 3D triangle positions.

  • public static float3 GetElevations(DynamicBuffer<Node> nodes, Triangle triangle)
    Returns a float3 containing the elevations (y) of the triangle's three nodes.

  • public static Bounds3 GetBounds(Triangle triangle, Triangle3 triangle3, AreaGeometryData areaData)
    Computes an expanded 3D bounds for a triangle using its height range and the area's max height. Useful for spatial queries and culling.

  • public static int CalculateStorageCapacity(Geometry geometry, StorageAreaData prefabStorageData)
    Estimates storage capacity based on geometry surface area and prefab storage parameters.

  • public static float CalculateStorageObjectArea(Geometry geometry, Storage storage, StorageAreaData prefabStorageData)
    Calculates how much surface area should be occupied by storage objects based on current storage amount and capacity.

  • public static float CalculateExtractorObjectArea(Geometry geometry, Extractor extractor, ExtractorAreaData extractorAreaData)
    Calculates object spawn area for extractors based on extracted amount and area parameters.

  • public static Triangle2 GetTriangle2(DynamicBuffer<Node> nodes, Triangle triangle)
    Returns a 2D triangle (xz plane) from nodes and triangle indices.

  • public static Triangle2 GetTriangle2(DynamicBuffer<Node> nodes, Triangle triangle, float expandAmount, bool isCounterClockwise)
    Returns a 2D triangle with nodes expanded by expandAmount (useful for collision/placement checks with padding). Expansion respects winding direction.

  • public static bool3 IsEdge(DynamicBuffer<Node> nodes, Triangle triangle)
    Returns a bool3 indicating which triangle edges are boundary edges (based on index adjacency). Useful when rendering or seam-detection is required.

  • public static quaternion CalculateLabelRotation(float3 cameraRight)
    Calculates a quaternion to orient labels so they face the camera correctly.

  • public static float3 CalculateLabelPosition(Geometry geometry)
    Returns the label position for an area (currently the geometry center).

  • public static float CalculateLabelScale(float3 cameraPosition, float3 labelPosition)
    Computes a scale for labels based on camera distance (avoids labels being too small).

  • public static float4x4 CalculateLabelMatrix(float3 cameraPosition, float3 labelPosition, quaternion labelRotation)
    Builds a TRS matrix for label rendering using calculated scale and rotation.

  • public static bool CheckOption(District district, DistrictOption option)
    Checks if a District has a given option flag set.

  • public static void ApplyModifier(ref float value, DynamicBuffer<DistrictModifier> modifiers, DistrictModifierType type)
    Applies a modifier (additive and multiplicative stored in DistrictModifier) to a float value if available.

  • public static bool HasOption(DistrictOptionData optionData, DistrictOption option)
    Checks a DistrictOptionData option mask for a specific option.

  • public static bool CheckServiceDistrict(Entity district, Entity service, BufferLookup<ServiceDistrict> serviceDistricts)
    Checks whether a service (entity) services a particular district. Handles missing buffers and empty service entries.

  • public static bool CheckServiceDistrict(Entity district1, Entity district2, Entity service, BufferLookup<ServiceDistrict> serviceDistricts)
    Overload that checks two districts (e.g., for area edges shared by two districts) against a service's service list.

  • public static bool CheckServiceDistrict(Entity building, DynamicBuffer<ServiceDistrict> serviceDistricts, ref ComponentLookup<CurrentDistrict> currentDistricts)
    Checks whether a service district buffer contains the current district of a building. Uses CurrentDistrict component lookup.

  • public static CollisionMask GetCollisionMask(AreaGeometryData areaGeometryData)
    Returns a CollisionMask appropriate for the area type (includes underground unless area is a Lot).

  • public static bool TryGetRandomObjectLocation(ref Unity.Mathematics.Random random, ObjectGeometryData objectGeometryData, Area area, Geometry geometry, float extraRadius, DynamicBuffer<Node> nodes, DynamicBuffer<Triangle> triangles, NativeList<ObjectItem> objects, out Game.Objects.Transform transform)
    Attempts to place an object randomly inside an area. Computes a random position inside geometry, tries to fit inside area and avoid edges/other objects, calculates rotation and returns a transform. Returns true when placement succeeded.

  • public static float3 GetRandomPosition(ref Unity.Mathematics.Random random, Geometry geometry, DynamicBuffer<Node> nodes, DynamicBuffer<Triangle> triangles)
    Picks a uniformly random position over the area's surface by weighted sampling across triangles. Falls back to node interpolation when triangles are missing.

  • public static quaternion GetRandomRotation(ref Unity.Mathematics.Random random, float3 position, DynamicBuffer<Node> nodes)
    Computes a rotation for an object aligned to nearest boundary segment if available; otherwise returns a random Y rotation. Useful to orient props along area edges.

  • public static bool TryFitInside(ref float3 position, float radius, float extraRadius, Area area, DynamicBuffer<Node> nodes, NativeList<ObjectItem> objects, bool canOverride = false)
    Attempts to nudge a candidate position to fit inside an area's polygon and avoid overlapping other objects. Returns true if final position is valid. Performs edge push-out and object-avoidance, with an optional small override allowance.

  • public static bool IntersectArea(float3 position, float radius, DynamicBuffer<Node> nodes, DynamicBuffer<Triangle> triangles)
    Checks if a circle (position.xz + radius) intersects any triangle of the area. Used for collision and validity checks.

  • public static bool IntersectEdges(float3 position, float radius, float extraRadius, DynamicBuffer<Node> nodes)
    Checks if a circle intersects area boundary edges (fast edge distance check).

  • public static bool IntersectObjects(float3 position, float radius, float extraRadius, NativeList<ObjectItem> objects, bool canOverride = false)
    Checks for overlaps with existing placed objects. Respects canOverride threshold.

  • public static float GetMinNodeDistance(AreaType areaType)
    Returns a minimum node distance (snap/merge threshold) based on AreaType (Lot, District, MapTile, Space, Surface, default).

  • public static AreaTypeMask GetTypeMask(AreaType type)
    Returns a bitmask for a single AreaType (or None mask for AreaType.None). Useful when filtering areas by type.

  • public static float3 GetExpandedNode(DynamicBuffer<Node> nodes, int index, float expandAmount, bool isComplete, bool isCounterClockwise)
    Calculates a node position expanded outward by expandAmount, taking into account neighbors and winding. Handles open or closed node lists.

  • public static float3 GetExpandedNode(NativeArray<SubAreaNode> nodes, int index, float expandAmount, bool isComplete, bool isCounterClockwise)
    Same as above but for a NativeArray of SubAreaNode.

  • public static float3 GetExpandedNode<TNodeList>(TNodeList nodes, int index, int prevIndex, int nextIndex, float expandAmount, bool isCounterClockwise) where TNodeList : INativeList<Node>
    Generic expansion using explicit prev/next indices. Useful for generic native lists.

  • public static bool SelectAreaPrefab(DynamicBuffer<PlaceholderObjectElement> placeholderElements, ComponentLookup<SpawnableObjectData> spawnableDatas, NativeParallelHashMap<Entity, int> selectedSpawnables, ref Unity.Mathematics.Random random, out Entity result, out int seed)
    Selects a prefab/entity to spawn from placeholder elements using per-prefab probabilities. Tracks selected spawnables to reuse seeds for consistency. Returns true if a selection was made.

  • public static void FindAreaPath(ref Unity.Mathematics.Random random, NativeList<PathElement> path, DynamicBuffer<Game.Net.SubLane> lanes, Entity startEntity, float startCurvePos, Entity endEntity, float endCurvePos, ComponentLookup<Lane> laneData, ComponentLookup<Curve> curveData)
    Pathfinding helper that finds a lane-based path between lanes/sub-lanes. Uses a backward Dijkstra/A* style search with randomized costs to pick a plausible lane-level path and writes PathElements into the provided path list.

  • public static Node AdjustPosition(Node node, ref TerrainHeightData terrainHeightData, ref WaterSurfaceData waterSurfaceData)
    Samples water/terrain to set node.m_Position.y correctly when both water and terrain height data are needed.

  • public static Node AdjustPosition(Node node, ref TerrainHeightData terrainHeightData)
    Samples terrain height only and returns the adjusted Node.

  • public static void SetCollisionFlags(ref AreaGeometryData areaGeometryData, bool ignoreMarkers)
    Sets the PhysicalGeometry flag on area geometry when appropriate, unless ignoreMarkers is true. Used to mark area geometry as collidable depending on area type.


Usage Example

// Example: Try placing a random object inside an area and get its transform.
var random = new Unity.Mathematics.Random((uint)System.DateTime.Now.Ticks);

// Assume you have the following from the ECS world / area system:
ObjectGeometryData objectGeometryData = ...;
Area area = ...;
Geometry geometry = ...;
DynamicBuffer<Node> nodes = ...;
DynamicBuffer<Triangle> triangles = ...;
NativeList<AreaUtils.ObjectItem> objects = new NativeList<AreaUtils.ObjectItem>(Allocator.Temp);

// extraRadius allows spacing from other objects/edges
float extraRadius = 0.5f;

Game.Objects.Transform objTransform;
bool placed = AreaUtils.TryGetRandomObjectLocation(ref random, objectGeometryData, area, geometry, extraRadius, nodes, triangles, objects, out objTransform);

if (placed)
{
    // objTransform contains position and rotation suitable for instantiation
    Debug.Log($"Placed object at {objTransform.m_Position} rotation {objTransform.m_Rotation}");
}

objects.Dispose();