void Start() { if (Instance != null) { Destroy(this); Debug.LogError("Two Pathfinding managers exist in the scene. Deleting one"); return; } Instance = this; lightingManager = GetComponent <LightingManager>(); probeData = new NativeArray <TilePathfindingData>(lightingManager.totalProbes, Allocator.Persistent); for (int i = 0; i < lightingManager.totalProbes; i++) { probeData[i] = new TilePathfindingData { distance = 99999, closestSeen = 99999, occupied = true }; } directionData = new NativeArray <float2>(lightingManager.totalProbes, Allocator.Persistent); lightingManager.OnLightingProbesMoved += HandleProbesMoved; }
void Update() { for (int i = 0; i < TestsPerFrame; i++) { float2 probePos = lightingManager.probeIndexToXy(testIndex); bool occupied = Physics2D.OverlapCircle(probePos, 0.3f, pathfindingBlockingLayers); //update data var currentData = probeData[testIndex]; probeData[testIndex] = new TilePathfindingData { closestSeen = currentData.closestSeen, distance = currentData.distance, occupied = occupied }; testIndex = (testIndex + 1) % lightingManager.totalProbes; } float3 playerPosition = PlayerCharacter.GetPostion(); float2 playerPosRelative = (playerPosition - lightingManager.getBottomLeft()).xy; if (math.all(new bool4(playerPosRelative > 0, playerPosRelative < lightingManager.ProbeCounts))) { int index = IndexFromPosition((int2)playerPosRelative, lightingManager.ProbeCounts); var current = probeData[index]; int2 playerPosRounded = (int2)playerPosition.xy; probeData[index] = new TilePathfindingData { distance = 0, closestSeen = playerPosRounded, occupied = current.occupied }; } NativeArray <TilePathfindingData> output = new NativeArray <TilePathfindingData>(probeData.Length, Allocator.TempJob); JobHandle dependency = default(JobHandle); var job = new UpdatePathfindingJob { TileData = probeData, ProbeCounts = lightingManager.ProbeCounts, Output = output, PlayerPosition = PlayerCharacter.GetPostion() }; var handle = job.Schedule(probeData.Length, 8, dependency); dependency = handle; dependency.Complete(); output.CopyTo(probeData); output.Dispose(); UpdateDirections(); }
/// <summary> /// Renders a path from the unit to the selected tile with active tile sprites /// </summary> public static void RenderPathToTile(TilePathfindingData selectedTilePathfindingData, IEnumerable <TilePathfindingData> unitPathfindingData) { var tilePathfindingData = unitPathfindingData.ToList(); ChangeTileSprites(tilePathfindingData.Select(x => x.DestinationGridTile), TileState.Selected); if (selectedTilePathfindingData == null) { return; } var pathfindingDataList = PathfindingHelper.GetPathToTile(tilePathfindingData, selectedTilePathfindingData.DestinationGridTile); ChangeTileSprites(pathfindingDataList, TileState.Active); }
public void Execute(int index) { int2 pos = PositionFromIndex(index, ProbeCounts); var current = TileData[index]; int2 playerPos = (int2)PlayerPosition.xy; int2 closestSeen = 99999; int smallestDist = 99999; if (!current.occupied) { for (int xOffset = -1; xOffset <= 1; xOffset++) { for (int yOffset = -1; yOffset <= 1; yOffset++) { int2 newPos = pos + new int2(xOffset, yOffset); if (math.any(new bool4(newPos < 0, newPos >= ProbeCounts))) { continue; } var data = TileData[IndexFromPosition(newPos, ProbeCounts)]; smallestDist = math.min(smallestDist, data.distance); if (!data.occupied) { if (math.all(playerPos == data.closestSeen)) { if (data.distance <= smallestDist) { smallestDist = data.distance; closestSeen = playerPos; } } } } } } Output[index] = new TilePathfindingData { distance = math.min(smallestDist + 1, 99999), closestSeen = closestSeen, occupied = current.occupied }; }
public void Execute(int index) { int2 pos = PositionFromIndex(index, ProbeCounts); int2 offsetPos = pos + Delta; if (math.any(new bool4(offsetPos < 0, offsetPos >= ProbeCounts))) { Output[index] = new TilePathfindingData { closestSeen = 99999, distance = 99999, occupied = true }; } else { Output[index] = TileData[IndexFromPosition(offsetPos, ProbeCounts)]; } }
/// <summary> /// Calculates and returns the tilePathfindingData of every available move for the selected unit in the grid, using Dijkstra pathfinding algorithm /// </summary> private static List <TilePathfindingData> CalculatePathfindingForAvailableMoves(GridTile[,] tileGrid, GridTile startingGridTile, int moveCount) { var remainingTilesToAnalyze = new List <TilePathfindingData>(); var analyzedTiles = new List <TilePathfindingData>(); //pathfindingData for the starting tile var startingTilePathfindingData = new TilePathfindingData(startingGridTile, null, 0, 0); remainingTilesToAnalyze.Add(startingTilePathfindingData); //We check the adjacent tiles of the first tile in remainingTilesToAnalyze, then we remove that tile from the list and then we order the list by totalTilePathCost do { var tileToAnalyze = remainingTilesToAnalyze[0]; var adjacentTilesPathfindingData = CalculateAdjacentTilePathfindingData(tileGrid, tileToAnalyze, analyzedTiles); foreach (var tilePathfindingData in adjacentTilesPathfindingData) { var existingTilePathfindingData = remainingTilesToAnalyze.FirstOrDefault(x => x.DestinationGridTile == tilePathfindingData.DestinationGridTile); //If we find a faster way to get to a tile that is already on the remainingTilesToAnalyze, we replace it with the new pathfinding data if (existingTilePathfindingData != null && existingTilePathfindingData.MoveCost > tilePathfindingData.MoveCost) { remainingTilesToAnalyze.Remove(existingTilePathfindingData); remainingTilesToAnalyze.Add(tilePathfindingData); } //if the destinationTile is not on the remainingTilesToAnalyze list, we add it else if (existingTilePathfindingData == null) { remainingTilesToAnalyze.Add(tilePathfindingData); } } analyzedTiles.Add(tileToAnalyze); remainingTilesToAnalyze.Remove(tileToAnalyze); remainingTilesToAnalyze = remainingTilesToAnalyze.OrderBy(x => x.TotalTilePathCost).ToList(); } while (remainingTilesToAnalyze.Any(x => x.MoveCost <= moveCount)); //we stop the pathfinding when all our moves cost more than the unit's movementSpeed return(analyzedTiles); }
/// <summary> /// Takes a tile's pathfinding data, and calculates the adjacent tiles' pathfinding data /// </summary> private static IEnumerable <TilePathfindingData> CalculateAdjacentTilePathfindingData(GridTile[,] tileGrid, TilePathfindingData sourceTilePathfindingData, IReadOnlyCollection <TilePathfindingData> analyzedTiles) { return((from adjacentTile in tileGrid.GetAdjacentGridTiles(sourceTilePathfindingData.DestinationGridTile) where (adjacentTile.TerrainType != TerrainType.Impassable && (ReferenceEquals(adjacentTile.CurrentUnit, null) || adjacentTile.CurrentUnit.Faction != UnitFaction.Monster)) && analyzedTiles.All(x => x.DestinationGridTile != adjacentTile) let tileMoveCost = sourceTilePathfindingData.MoveCost + TerrainMoveCost[adjacentTile.TerrainType] select new TilePathfindingData(adjacentTile, sourceTilePathfindingData, tileMoveCost, 0)).ToList()); }