Advertisement
JohnnyTurbo

Unity Flow Field: FlowField.cs

Aug 14th, 2020
3,148
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 3.82 KB | None | 0 0
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5.  
  6. public class FlowField
  7. {
  8.     public Cell[,] grid { get; private set; }
  9.     public Vector2Int gridSize { get; private set; }
  10.     public float cellRadius { get; private set; }
  11.     public Cell destinationCell;
  12.  
  13.     private float cellDiameter;
  14.  
  15.     public FlowField(float _cellRadius, Vector2Int _gridSize)
  16.     {
  17.         cellRadius = _cellRadius;
  18.         cellDiameter = cellRadius * 2f;
  19.         gridSize = _gridSize;
  20.     }
  21.  
  22.     public void CreateGrid()
  23.     {
  24.         grid = new Cell[gridSize.x, gridSize.y];
  25.  
  26.         for (int x = 0; x < gridSize.x; x++)
  27.         {
  28.             for (int y = 0; y < gridSize.y; y++)
  29.             {
  30.                 Vector3 worldPos = new Vector3(cellDiameter * x + cellRadius, 0, cellDiameter * y + cellRadius);
  31.                 grid[x, y] = new Cell(worldPos, new Vector2Int(x, y));
  32.             }
  33.         }
  34.     }
  35.  
  36.     public void CreateCostField()
  37.     {
  38.         Vector3 cellHalfExtents = Vector3.one * cellRadius;
  39.         int terrainMask = LayerMask.GetMask("Impassible", "RoughTerrain");
  40.         foreach (Cell curCell in grid)
  41.         {
  42.             Collider[] obstacles = Physics.OverlapBox(curCell.worldPos, cellHalfExtents, Quaternion.identity, terrainMask);
  43.             bool hasIncreasedCost = false;
  44.             foreach (Collider col in obstacles)
  45.             {
  46.                 if (col.gameObject.layer == 8)
  47.                 {
  48.                     curCell.IncreaseCost(255);
  49.                     continue;
  50.                 }
  51.                 else if (!hasIncreasedCost && col.gameObject.layer == 9)
  52.                 {
  53.                     curCell.IncreaseCost(3);
  54.                     hasIncreasedCost = true;
  55.                 }
  56.             }
  57.         }
  58.     }
  59.  
  60.     public void CreateIntegrationField(Cell _destinationCell)
  61.     {
  62.         destinationCell = _destinationCell;
  63.  
  64.         destinationCell.cost = 0;
  65.         destinationCell.bestCost = 0;
  66.  
  67.         Queue<Cell> cellsToCheck = new Queue<Cell>();
  68.  
  69.         cellsToCheck.Enqueue(destinationCell);
  70.  
  71.         while(cellsToCheck.Count > 0)
  72.         {
  73.             Cell curCell = cellsToCheck.Dequeue();
  74.             List<Cell> curNeighbors = GetNeighborCells(curCell.gridIndex, GridDirection.CardinalDirections);
  75.             foreach (Cell curNeighbor in curNeighbors)
  76.             {
  77.                 if (curNeighbor.cost == byte.MaxValue) { continue; }
  78.                 if (curNeighbor.cost + curCell.bestCost < curNeighbor.bestCost)
  79.                 {
  80.                     curNeighbor.bestCost = (ushort)(curNeighbor.cost + curCell.bestCost);
  81.                     cellsToCheck.Enqueue(curNeighbor);
  82.                 }
  83.             }
  84.         }
  85.     }
  86.  
  87.     public void CreateFlowField()
  88.     {
  89.         foreach(Cell curCell in grid)
  90.         {
  91.             List<Cell> curNeighbors = GetNeighborCells(curCell.gridIndex, GridDirection.AllDirections);
  92.  
  93.             int bestCost = curCell.bestCost;
  94.  
  95.             foreach(Cell curNeighbor in curNeighbors)
  96.             {
  97.                 if(curNeighbor.bestCost < bestCost)
  98.                 {
  99.                     bestCost = curNeighbor.bestCost;
  100.                     curCell.bestDirection = GridDirection.GetDirectionFromV2I(curNeighbor.gridIndex - curCell.gridIndex);
  101.                 }
  102.             }
  103.         }
  104.     }
  105.  
  106.     private List<Cell> GetNeighborCells(Vector2Int nodeIndex, List<GridDirection> directions)
  107.     {
  108.         List<Cell> neighborCells = new List<Cell>();
  109.  
  110.         foreach (Vector2Int curDirection in directions)
  111.         {
  112.             Cell newNeighbor = GetCellAtRelativePos(nodeIndex, curDirection);
  113.             if (newNeighbor != null)
  114.             {
  115.                 neighborCells.Add(newNeighbor);
  116.             }
  117.         }
  118.         return neighborCells;
  119.     }
  120.  
  121.     private Cell GetCellAtRelativePos(Vector2Int orignPos, Vector2Int relativePos)
  122.     {
  123.         Vector2Int finalPos = orignPos + relativePos;
  124.  
  125.         if (finalPos.x < 0 || finalPos.x >= gridSize.x || finalPos.y < 0 || finalPos.y >= gridSize.y)
  126.         {
  127.             return null;
  128.         }
  129.  
  130.         else { return grid[finalPos.x, finalPos.y]; }
  131.     }
  132.  
  133.     public Cell GetCellFromWorldPos(Vector3 worldPos)
  134.     {
  135.         float percentX = worldPos.x / (gridSize.x * cellDiameter);
  136.         float percentY = worldPos.z / (gridSize.y * cellDiameter);
  137.  
  138.         percentX = Mathf.Clamp01(percentX);
  139.         percentY = Mathf.Clamp01(percentY);
  140.  
  141.         int x = Mathf.Clamp(Mathf.FloorToInt((gridSize.x) * percentX), 0, gridSize.x - 1);
  142.         int y = Mathf.Clamp(Mathf.FloorToInt((gridSize.y) * percentY), 0, gridSize.y - 1);
  143.         return grid[x, y];
  144.     }
  145. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement