Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

A* Pathfinding help

Discussion in 'Scripting' started by suctioncup, Sep 21, 2014.

  1. suctioncup

    suctioncup

    Joined:
    May 19, 2012
    Posts:
    273
    Hello, I am trying to implement some very basic pathfinding.

    Here is the main excerpt from my code;

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5.  
    6. //Tile class
    7. public class Tile
    8. {
    9.     public TileState tileState;                //The state of the tile - empty, wall, floor etc
    10.    
    11.     public int x;                            //x position (Normalized)
    12.     public int y;                            //y position (Normalized)
    13.    
    14.     public int g;                          //Cost
    15.     public int h;                          //Manhattan Distance
    16.     public int f;                          //Total cost
    17.    
    18.     public Tile parent_tile;
    19. }
    20.  
    21. public class TileValues
    22. {
    23.     public int empty = 0;
    24.     public int wall_persp = 0;
    25.     public int floor = 1;
    26.     public int edge = 1;
    27. }
    28.  
    29. public class pathfinding_test : MonoBehaviour {
    30.  
    31.     //A* corridor pathfinding
    32.     void DigCorridors()
    33.     {
    34.         Debug.Log("Starting DigCorridors()...");
    35.        
    36.         Debug.Log("Calling build_path()...");
    37.         List<Tile> corridor = build_path(grid_list[5], grid_list[15]);
    38.         Debug.Log("Called build_path().");
    39.        
    40.         for(int i = 0; i < corridor.Count; i++)
    41.         {
    42.             grid_list[grid_list.IndexOf(corridor[i])].tileState = TileState.Floor;
    43.         }
    44.  
    45.         Debug.Log("Calling Fill()...");
    46.         Fill();
    47.     }
    48.    
    49.     //City block distance - used in pathfinding
    50.     int manhattanDistance(Tile from, Tile to)
    51.     {
    52.         return Mathf.Abs(from.x - to.x) + Mathf.Abs(from.y - to.y);
    53.     }
    54.    
    55.     List<Tile> DigPath(Tile from, Tile to)
    56.     {
    57.         Debug.Log("Starting DigPath()...");
    58.         //Define the lists of tiles we can reach, and tiles we have explored
    59.         List<Tile> open = new List<Tile>();  
    60.         List<Tile> closed = new List<Tile>();
    61.        
    62.         //Add the from tile to the reachable list
    63.         open.Add(from);
    64.        
    65.         Debug.Log("Starting A* loop at: " + Time.timeSinceLevelLoad    );
    66.        
    67.         while(open.Count > 0)
    68.         {
    69.             Debug.Log("while loop");
    70.             Tile node_current = new Tile();
    71.            
    72.             Debug.Log("Getting lowest F score");
    73.             node_current = GetLowestFScore(open, to);
    74.            
    75.             Debug.Log("Got lowest F score");
    76.            
    77.             if(node_current == to)
    78.             {
    79.                 break;  
    80.             }
    81.            
    82.             Debug.Log("Getting adjacent nodes");
    83.             List<Tile> adjacent_tiles = new List<Tile>();
    84.             adjacent_tiles = get_adjacent_nodes(node_current);
    85.            
    86.             Debug.Log("For loop");
    87.             for(int i = 0; i < adjacent_tiles.Count; i++)
    88.             {
    89.                 if(adjacent_tiles[i] == to)
    90.                 {
    91.                     break;    
    92.                 }
    93.                
    94.                 Tile adjacent_node = new Tile();
    95.                 adjacent_node = adjacent_tiles[i];
    96.                
    97.                 adjacent_node.g = node_current.g + 1;
    98.                 adjacent_node.h = manhattanDistance(adjacent_node, to);
    99.                 adjacent_node.f = adjacent_node.g + adjacent_node.h;
    100.                
    101.                 if(open.Contains(adjacent_node) && node_current.f < adjacent_node.f)
    102.                 {
    103.                     //Discard and continue
    104.                     continue;
    105.                 }
    106.                
    107.                 if(closed.Contains(adjacent_node) && node_current.f < adjacent_node.f)
    108.                 {
    109.                     //Discard and continue
    110.                     continue;
    111.                 }
    112.              
    113.                 adjacent_node.parent_tile = node_current;
    114.                 open.Add(adjacent_node);
    115.             }
    116.                 closed.Add(node_current);
    117.         }
    118.         Debug.Log("Finished A* loop at: " + Time.timeSinceLevelLoad    );
    119.        
    120.         return closed;
    121.        
    122.         Debug.Log("Finished DigPath().");
    123.     }
    124.    
    125.     Tile GetLowestFScore(List<Tile> open_list, Tile to)
    126.     {
    127.         Debug.Log("Starting GetLowestFScore()...");
    128.         int lowest_f = 1000000;
    129.        
    130.         Tile lowest_f_tile = new Tile();
    131.        
    132.         Debug.Log("GetLowestFScore() if statement");
    133.         if(open_list.Count == 1)
    134.         {
    135.             lowest_f_tile = open_list[0];
    136.             Debug.Log("Got lowest f");
    137.         } else {
    138.             Debug.Log("GetLowestFScore() for loop");
    139.             for(int i = 0; i < open_list.Count; i++)
    140.             {
    141.                 if(open_list[i].f < lowest_f)
    142.                 {
    143.                     lowest_f_tile = open_list[i];
    144.                     lowest_f = open_list[i].f;
    145.                 }
    146.             }
    147.         }
    148.        
    149.         Debug.Log("Returning lowest F tile");
    150.        
    151.         return lowest_f_tile;
    152.     }
    153.    
    154.     List<Tile> get_adjacent_nodes(Tile node)
    155.     {
    156.         List<Tile> adjacent = new List<Tile>();
    157.        
    158.         //Add N tile
    159.         if(grid_list.IndexOf(node) - gridSettings.Width > 0)
    160.         {
    161.             adjacent.Add(grid_list[grid_list.IndexOf(node) - gridSettings.Width]);
    162.         }
    163.        
    164.         //Add S tile
    165.         if(grid_list.IndexOf(node) + gridSettings.Width < grid_list.Count)
    166.         {
    167.             adjacent.Add(grid_list[grid_list.IndexOf(node) + gridSettings.Width]);
    168.         }
    169.        
    170.         //Add E tile
    171.         if(grid_list.IndexOf(node) + 1 < grid_list.Count)
    172.         {
    173.             adjacent.Add(grid_list[grid_list.IndexOf(node) + 1]);
    174.         }
    175.        
    176.         //Add W tile
    177.         if(grid_list.IndexOf(node) - 1 > 0)
    178.         {
    179.             adjacent.Add(grid_list[grid_list.IndexOf(node) - 1]);
    180.         }
    181.        
    182.         return adjacent;
    183.     }
    184.    
    185.     List<Tile> build_path(Tile from, Tile to)
    186.     {
    187.         Debug.Log("Starting build_path()...");
    188.        
    189.         List<Tile> path = new List<Tile>();
    190.         path = DigPath(from, to);
    191.        
    192.         while(to != null)
    193.         {
    194.             path.Add(to);
    195.             to = to.parent_tile;
    196.         }
    197.        
    198.         return path;
    199.        
    200.         Debug.Log("Finished build_path().");
    201.     }
    202.    
    203. }
    Currently, when I run this, unity crashes. What am I doing wrong?
     
  2. suctioncup

    suctioncup

    Joined:
    May 19, 2012
    Posts:
    273
    Forgot to say, I should be able to run build_path(), which should return a List of 'tiles' (that list is the path)
     
  3. AustinRichards

    AustinRichards

    Joined:
    Apr 4, 2013
    Posts:
    321
  4. suctioncup

    suctioncup

    Joined:
    May 19, 2012
    Posts:
    273
    I tried this, but it doesn't seem to be logging anything before the editor freezes. I do have to relaunch unity though, which is probably why.