103 lines
3.9 KiB
C#
103 lines
3.9 KiB
C#
using Pathfinding.Jobs;
|
|
using Pathfinding.Sync;
|
|
using Unity.Collections;
|
|
using Unity.Jobs;
|
|
using UnityEngine;
|
|
using UnityEngine.Profiling;
|
|
|
|
namespace Pathfinding.Graphs.Navmesh.Jobs {
|
|
/// <summary>
|
|
/// Builds nodes and tiles and prepares them for pathfinding.
|
|
///
|
|
/// Takes input from a <see cref="TileBuilder"/> job and outputs a <see cref="BuildNodeTilesOutput"/>.
|
|
///
|
|
/// This job takes the following steps:
|
|
/// - Calculate connections between nodes inside each tile
|
|
/// - Create node and tile objects
|
|
/// - Connect adjacent tiles together
|
|
/// </summary>
|
|
public struct JobBuildNodes {
|
|
uint graphIndex;
|
|
public uint initialPenalty;
|
|
public bool recalculateNormals;
|
|
public float maxTileConnectionEdgeDistance;
|
|
Matrix4x4 graphToWorldSpace;
|
|
TileLayout tileLayout;
|
|
|
|
public class BuildNodeTilesOutput : IProgress, System.IDisposable {
|
|
public TileBuilder.TileBuilderOutput progressSource;
|
|
public NavmeshTile[] tiles;
|
|
|
|
public float Progress => progressSource.Progress;
|
|
|
|
public void Dispose () {
|
|
}
|
|
}
|
|
|
|
internal JobBuildNodes(RecastGraph graph, TileLayout tileLayout) {
|
|
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<BuildNodeTilesOutput> Schedule (DisposeArena arena, Promise<TileBuilder.TileBuilderOutput> preCutDependency, Promise<TileCutter.TileCutterOutput> postCutDependency) {
|
|
var postCutInput = postCutDependency.GetValue();
|
|
var preCutInput = preCutDependency.GetValue();
|
|
var tileRect = preCutInput.tileMeshes.tileRect;
|
|
|
|
NativeArray<TileMesh.TileMeshUnsafe> finalTileMeshes;
|
|
if (postCutInput.tileMeshes.tileMeshes.IsCreated) {
|
|
UnityEngine.Assertions.Assert.AreEqual(postCutInput.tileMeshes.tileMeshes.Length, tileRect.Area);
|
|
finalTileMeshes = postCutInput.tileMeshes.tileMeshes;
|
|
} else {
|
|
finalTileMeshes = preCutInput.tileMeshes.tileMeshes;
|
|
}
|
|
|
|
UnityEngine.Assertions.Assert.AreEqual(preCutInput.tileMeshes.tileMeshes.Length, tileRect.Area);
|
|
var tiles = new NavmeshTile[tileRect.Area];
|
|
var tilesGCHandle = System.Runtime.InteropServices.GCHandle.Alloc(tiles);
|
|
var nodeConnections = new NativeArray<JobCalculateTriangleConnections.TileNodeConnectionsUnsafe>(tileRect.Area, Allocator.Persistent);
|
|
|
|
var calculateConnectionsJob = new JobCalculateTriangleConnections {
|
|
tileMeshes = finalTileMeshes,
|
|
nodeConnections = nodeConnections,
|
|
}.Schedule(postCutDependency.handle);
|
|
|
|
var tileWorldSize = new Vector2(tileLayout.TileWorldSizeX, tileLayout.TileWorldSizeZ);
|
|
var createTilesJob = new JobCreateTiles {
|
|
// If any cutting is done, we need to save the pre-cut data to be able to re-cut tiles later
|
|
preCutTileMeshes = postCutInput.tileMeshes.tileMeshes.IsCreated ? preCutInput.tileMeshes.tileMeshes : default,
|
|
tileMeshes = finalTileMeshes,
|
|
tiles = tilesGCHandle,
|
|
tileRect = tileRect,
|
|
graphTileCount = tileLayout.tileCount,
|
|
graphIndex = graphIndex,
|
|
initialPenalty = initialPenalty,
|
|
recalculateNormals = recalculateNormals,
|
|
graphToWorldSpace = this.graphToWorldSpace,
|
|
tileWorldSize = tileWorldSize,
|
|
}.Schedule(postCutDependency.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<BuildNodeTilesOutput>(connectTilesDependency, new BuildNodeTilesOutput {
|
|
progressSource = preCutInput,
|
|
tiles = tiles,
|
|
});
|
|
}
|
|
}
|
|
}
|