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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Move to object on a grid

Discussion in 'Scripting' started by Corva-Nocta, Oct 11, 2015.

  1. Corva-Nocta

    Corva-Nocta

    Joined:
    Feb 7, 2013
    Posts:
    801
    I've got a grid based movement system set up where you click a grid and the player navigates to that square. My next hurdle that I'm having trouble with is making it so when you click on an object that is not the floor (like a door, or a resource node) the player will navigate to the nearest grid space to it. I'm having some trouble getting the code just right. I'm fairly certain I know the logic of what to do but really having trouble translating that into java.

    Here is the movement script I am currently using:

    var target : Transform;

    var moving : boolean = false;

    var Player : GameObject;


    function OnMouseDown() {
    moving = true;
    }

    function Start()
    {
    target = transform;

    Player = GameObject.Find("Player");
    }

    function Update ()
    {
    var dist : float = Vector3.Distance(Player.transform.position, target.position);

    if(dist < 1.75){
    moving = false;
    }

    NavComponent = this.Player.GetComponent(NavMeshAgent);

    if(moving == true) {
    NavComponent.SetDestination(target.position) ;
    }
    }


    I would like to modify this script to find the nearest empty grid space and move the player to that space. I assume I will need to calculate the distance to the nearest grid spaces, then calculate the distance of those grid spaces to the player and make the player move to the nearest one. Just not sure how to properly implement it. Any help at all would be great!
     
  2. mmk

    mmk

    Joined:
    Aug 2, 2015
    Posts:
    2
  3. Thaao

    Thaao

    Joined:
    Jun 9, 2014
    Posts:
    54
    If you want to see some example code, I have a simple pathfinder in my grid-based game that takes two points on a grid, and returns the nearest empty space next to one point, which seems to be what you're looking for:

    Code (CSharp):
    1. /* FindPath Uses Dijkstra's Algorithm to find the shortest path through the map from an origin point to a goal point.
    2.      * It expands a frontier from the goal point until it finds the origin, making note of the point along the frontier
    3.      * that "found" the origin and then returns that as the first step along the path from the origin to the goal.
    4.      * The parameter nextStepMustBeEmpty can ignore 'first steps' that are occupied; otherwise, it will return the next step
    5.      * along the shortest path whether or not it is occupied. */
    6.     public static Node FindPath(Node origin, Node goal, bool nextStepMustBeEmpty)
    7.     {
    8.         if (origin == goal)
    9.         {
    10.             Debug.Log("Tried to find a path to and from the same point.");
    11.             return null;
    12.         }
    13.         List<Node> frontier = new List<Node>(); // the frontier (nodes that are expanding)
    14.         bool[,] searched = new bool[Dungeon.xSize, Dungeon.ySize]; // whether or not a map node has been searched
    15.         Node nextStep = null; // the direction to the next node in the path (from startP), this is what is returned.
    16.         bool found = false;
    17.  
    18.         searched[goal.x, goal.y] = true;
    19.         frontier.Add(goal);
    20.  
    21.         //Expand the frontier until startP is found or there are no more possible nodes
    22.         while (frontier.Count > 0 && !found)
    23.         {
    24.             Node f = frontier[0]; // the space we're currently checking from
    25.             frontier.RemoveAt(0); // pop!
    26.             for (int i = 0; i <= 8 && !found; i++) //check all 8 squares around it...
    27.             {
    28.                 Node next = DungeonControl.DetermineNextStep(f, 45 * i, false); // find the next node in this direction
    29.                 if (next == null || searched[next.x, next.y]) // If we've already searched here or it's outside of the borders...
    30.                 {
    31.                     continue; // do nothing and continue.
    32.                 }
    33.                 else if (next.x == origin.x && next.y == origin.y) // If this is the goal (origin) and we still haven't found it...
    34.                 {
    35.                     if(!nextStepMustBeEmpty ||  !Dungeon.map[f.x, f.y].occupied) // only use this if the current space is unoc, since we have to walk to it.
    36.                     {
    37.                         found = true;
    38.                         nextStep = f; // set the next step to the space we're checking FROM.
    39.                         frontier.Clear();
    40.                         continue;
    41.                     }
    42.                     continue; // otherwise, keep searching, ignoring this finding of the goal/origin.
    43.                 }
    44.                 else // We haven't searched this spot, it's legit, and it's not the goal
    45.                 {
    46.                     searched[next.x, next.y] = true; // We don't need to search this again.
    47.                     if (Dungeon.map[next.x, next.y].walkable) // only if this space is able to be walked on (not a wall).
    48.                     {
    49.                         frontier.Add(next); // add it to the frontier! hooray!
    50.                     }
    51.                     continue;
    52.                 }
    53.             }
    54.         }
    55.         searched = null;
    56.         frontier = null;
    57.         return nextStep;
    58.     }
    Hopefully the struct Node is self-explanatory. Dungeon.map[,] is an array of Nodes.

    The way this works is that the character seeking a path will use this to find the next step they take -- it's a turn-based game, so for example if the enemy needs to seek the player, FindPath is called with the enemy's location as the 'origin' paramtere, and the player as the 'goal' parameter. Then the algorithm finds the shortest path starting from the goal (player) to the enemy (origin), and returns the empty node closest to the enemy (origin) along that path, so the enemy knows that's the next step to take.

    Though it sounds like the doors and items and stuff in your game are not on the grid at all...? If they are on the grid, just make sure the objects know what node they're on, instead of trying to "find" the node when they're clicked on. So if your door knows which node its on, when you click on it, you can just use that data to give the player a point to seek. If they're not on the grid, you'll have to determine what spaces you considered 'occupied by' or 'surrounding' those things, which will depend on the design of your game/grid.