Skip to content

Game.Routes.RaycastJobs

Assembly: Game
Namespace: Game.Routes

Type: public static class

Base: System.Object

Summary:
Contains Burst-compiled Unity DOTS jobs used to perform raycasts against route entities (route waypoints and route segments) in Cities: Skylines 2. The class exposes two job types: - FindRoutesFromTreeJob — a single-threaded IJob that uses a NativeQuadTree to collect candidate route elements that intersect raycast lines and writes them into a NativeList. - RaycastRoutesJob — an IJobParallelForDefer that performs the precise distance checks against waypoints and curve segments and accumulates RaycastResult entries into a NativeAccumulator for later consumption.

These jobs are performance-focused (Burst compatible), use Unity.Collections native containers and DOTS Component/Buffer lookups, and implement a broadphase (quad-tree based) + narrowphase (distance checks) pattern to efficiently raycast many lines against many route entities.


Fields

  • FindRoutesFromTreeJob.m_Input : NativeArray<RaycastInput> (ReadOnly)
    Input raycast requests. Each entry supplies a line, type masks, filters (transport/route types), and flags used to decide which route elements to test.

  • FindRoutesFromTreeJob.m_SearchTree : NativeQuadTree<RouteSearchItem, QuadTreeBoundsXZ> (ReadOnly)
    Broadphase spatial index that stores route search items (waypoints/segments) organized by QuadTreeBoundsXZ. Used by the iterator to quickly find candidate route elements whose bounds intersect the raycast line.

  • FindRoutesFromTreeJob.m_RouteList : NativeList<RouteItem> (WriteOnly)
    Output list populated with RouteItem entries for each candidate route element discovered by the broadphase iteration. Each RouteItem links to an entity, element index and the originating raycast index.

  • FindRoutesFromTreeJob.FindRoutesIterator (private nested iterator)
    Internal quad-tree iterator that implements INativeQuadTreeIterator. It stores:

  • m_RaycastIndex — index of the raycast in m_Input
  • m_Line — Line3.Segment being tested
  • m_RouteList — reference to the native list to append candidates to
    Implements Intersect(QuadTreeBoundsXZ) and Iterate(...) used by the quad-tree to test and record candidate items.

  • RaycastRoutesJob.m_Input : NativeArray<RaycastInput> (ReadOnly)
    The same raycast request array used by the narrowphase job to resolve final hits.

  • RaycastRoutesJob.m_Routes : NativeArray<RouteItem> (ReadOnly)
    Array of candidate RouteItem entries produced by the broadphase (FindRoutesFromTreeJob). The parallel job iterates this array (deferred length) to perform precise checks.

  • RaycastRoutesJob component lookup fields (ReadOnly)
    ComponentLookup and BufferLookup references used to fetch data for candidate entities:

  • m_PrefabRefData : ComponentLookup<PrefabRef>
  • m_PrefabRouteData : ComponentLookup<RouteData>
  • m_PrefabTransportLineData : ComponentLookup<TransportLineData>
  • m_WaypointData : ComponentLookup<Waypoint>
  • m_SegmentData : ComponentLookup<Segment>
  • m_PositionData : ComponentLookup<Position>
  • m_HiddenRouteData : ComponentLookup<HiddenRoute>
  • m_OwnerData : ComponentLookup<Owner>
  • m_CurveElements : BufferLookup<CurveElement>

  • RaycastRoutesJob.m_Results : NativeAccumulator<RaycastResult>.ParallelWriter (NativeDisableContainerSafetyRestriction)
    Parallel accumulator used to collect final RaycastResult values for each raycast index. Marked with NativeDisableContainerSafetyRestriction to allow concurrent accumulation from multiple threads.

Properties

  • None (this static helper contains only nested types and jobs; the jobs expose fields rather than properties).

Constructors

  • RaycastJobs() (implicit static class constructor)
    No explicit constructor — RaycastJobs is a static container type for the nested job structs.

  • FindRoutesFromTreeJob / RaycastRoutesJob
    Both are value types (structs). They use the default implicit constructors generated by the compiler. All configuration is done by assigning the public fields prior to scheduling.

Methods

  • FindRoutesFromTreeJob.Execute() : void
    Iterates the input raycasts (m_Input). For each raycast whose TypeMask includes RouteWaypoints or RouteSegments, it constructs a FindRoutesIterator configured with the ray's Line and index, then calls m_SearchTree.Iterate(ref iterator) to collect candidate RouteItem entries into m_RouteList. The quad-tree iterator uses a bounding-box intersection test (MathUtils.Intersect) to prune the search.

  • FindRoutesFromTreeJob.FindRoutesIterator.Intersect(QuadTreeBoundsXZ) : bool
    Bounding-box intersection test between the quad-tree node bounds and the job's line segment. Returns true if the node should be visited.

  • FindRoutesFromTreeJob.FindRoutesIterator.Iterate(QuadTreeBoundsXZ, RouteSearchItem) : void
    Called for each item in a visited quad-tree node. If the item’s bounds intersect the line, creates a RouteItem (entity, element index, raycast index) and appends it to m_RouteList.

  • RaycastRoutesJob.Execute(int index) : void
    The narrowphase per-candidate execution. For the RouteItem at the given index:

  • Reads the originating RaycastInput (by m_RaycastIndex).
  • If the candidate entity is a waypoint and the raycast requested RouteWaypoints:
    • Checks prefab/route/transport type filters, hidden route flags, and computes distance from the ray line to the waypoint position (MathUtils.Distance).
    • If within routeData.m_SnapDistance, constructs a RaycastResult (owner, hit entity, positions, normalized distance, cell index) and accumulates it into m_Results for the originating raycast index.
  • If the candidate entity is a route segment and the raycast requested RouteSegments:
    • Retrieves the corresponding CurveElement from the entity's CurveElement buffer using the element index, checks filters and curve length.
    • Computes distance between the ray line and the cubic curve (MathUtils.Distance), compares with half the snap distance, and on hit constructs/accumulates a RaycastResult with appropriate hit positions and metadata.
  • Several small position/distance adjustments are applied to normalized distances to order hits (subtracting a normalized line-length factor and applying a tiny scale of the overlap distance).

Notes: - Both jobs are Burst-compiled via [BurstCompile]. - RaycastRoutesJob is an IJobParallelForDefer to allow scheduling with the m_Routes array produced at runtime (deferred length). - The jobs use TryGetComponent / HasComponent combinations to avoid errors when components are missing and to early-out for hidden routes.

Usage Example

// Pseudocode showing typical usage flow inside a system:

// 1) Prepare inputs
NativeArray<RaycastInput> inputs = /* prepared raycast inputs */;
NativeList<RouteItem> routeCandidates = new NativeList<RouteItem>(Allocator.TempJob);

// 2) Broadphase: find candidate route entities that intersect the ray lines.
// Feed a NativeQuadTree<RouteSearchItem, QuadTreeBoundsXZ> (m_SearchTree) built elsewhere.
var findJob = new RaycastJobs.FindRoutesFromTreeJob {
    m_Input = inputs,
    m_SearchTree = searchTree,
    m_RouteList = routeCandidates
};

JobHandle findHandle = findJob.Schedule();

// 3) Convert candidate list to array for deferred parallel job
NativeArray<RouteItem> routesArray = routeCandidates.AsDeferredJobArray(ref findHandle);

// 4) Narrowphase: precise tests in parallel and accumulate results
var raycastJob = new RaycastJobs.RaycastRoutesJob {
    m_Input = inputs,
    m_Routes = routesArray,
    m_PrefabRefData = GetComponentLookup<PrefabRef>(true),
    m_PrefabRouteData = GetComponentLookup<RouteData>(true),
    m_PrefabTransportLineData = GetComponentLookup<TransportLineData>(true),
    m_WaypointData = GetComponentLookup<Waypoint>(true),
    m_SegmentData = GetComponentLookup<Segment>(true),
    m_PositionData = GetComponentLookup<Position>(true),
    m_HiddenRouteData = GetComponentLookup<HiddenRoute>(true),
    m_OwnerData = GetComponentLookup<Owner>(true),
    m_CurveElements = GetBufferLookup<CurveElement>(true),
    m_Results = raycastResults.AsParallelWriter()
};

JobHandle raycastHandle = raycastJob.Schedule(routesArray.Length, 64, findHandle);

// 5) Complete and read out results after job completion
raycastHandle.Complete();
// Consume raycastResults accumulator to get final RaycastResult lists per input index.

// Dispose temp containers when done
routeCandidates.Dispose();
inputs.Dispose();
routesArray.Dispose();

Notes and tips: - Ensure ComponentLookup/BufferLookup instances are updated (with system state) and accessed with the correct read-only/write permissions. - Use conservative batch sizes in Schedule to balance overhead and parallel throughput (example uses batchSize = 64). - The code relies on many game-specific types (RaycastInput, RaycastResult, RouteData, CurveElement, etc.). Make sure your mod provides the same component definitions or references the game's assemblies.