using Pathfinding.Jobs; using Pathfinding.Util; using Unity.Collections; using Unity.Jobs; using UnityEngine; using UnityEngine.Profiling; namespace Pathfinding.Graphs.Navmesh.Jobs { /// /// Builds nodes and tiles and prepares them for pathfinding. /// /// Takes input from a job and outputs a . /// /// This job takes the following steps: /// - Calculate connections between nodes inside each tile /// - Create node and tile objects /// - Connect adjacent tiles together /// public struct JobBuildNodes { AstarPath astar; uint graphIndex; public uint initialPenalty; public bool recalculateNormals; public float maxTileConnectionEdgeDistance; Matrix4x4 graphToWorldSpace; TileLayout tileLayout; public class BuildNodeTilesOutput : IProgress, System.IDisposable { public TileBuilder.TileBuilderOutput dependency; public NavmeshTile[] tiles; public float Progress => dependency.Progress; public void Dispose () { } } internal JobBuildNodes(RecastGraph graph, TileLayout tileLayout) { this.astar = graph.active; this.tileLayout = tileLayout; this.graphIndex = graph.graphIndex; this.initialPenalty = graph.initialPenalty; this.recalculateNormals = graph.RecalculateNormals; this.maxTileConnectionEdgeDistance = graph.MaxTileConnectionEdgeDistance; this.graphToWorldSpace = tileLayout.transform.matrix; } public Promise Schedule (DisposeArena arena, Promise dependency) { var input = dependency.GetValue(); var tileRect = input.tileMeshes.tileRect; UnityEngine.Assertions.Assert.AreEqual(input.tileMeshes.tileMeshes.Length, tileRect.Area); var tiles = new NavmeshTile[tileRect.Area]; var tilesGCHandle = System.Runtime.InteropServices.GCHandle.Alloc(tiles); var nodeConnections = new NativeArray(tileRect.Area, Allocator.Persistent); var calculateConnectionsJob = new JobCalculateTriangleConnections { tileMeshes = input.tileMeshes.tileMeshes, nodeConnections = nodeConnections, }.Schedule(dependency.handle); var tileWorldSize = new Vector2(tileLayout.TileWorldSizeX, tileLayout.TileWorldSizeZ); var createTilesJob = new JobCreateTiles { tileMeshes = input.tileMeshes.tileMeshes, tiles = tilesGCHandle, tileRect = tileRect, graphTileCount = tileLayout.tileCount, graphIndex = graphIndex, initialPenalty = initialPenalty, recalculateNormals = recalculateNormals, graphToWorldSpace = this.graphToWorldSpace, tileWorldSize = tileWorldSize, }.Schedule(dependency.handle); var applyConnectionsJob = new JobWriteNodeConnections { nodeConnections = nodeConnections, tiles = tilesGCHandle, }.Schedule(JobHandle.CombineDependencies(calculateConnectionsJob, createTilesJob)); Profiler.BeginSample("Scheduling ConnectTiles"); var connectTilesDependency = JobConnectTiles.ScheduleBatch(tilesGCHandle, applyConnectionsJob, tileRect, tileWorldSize, maxTileConnectionEdgeDistance); Profiler.EndSample(); arena.Add(tilesGCHandle); arena.Add(nodeConnections); return new Promise(connectTilesDependency, new BuildNodeTilesOutput { dependency = input, tiles = tiles, }); } } }