Search Unity

A* Navigation in 2D - Random Waypoint Problem

Discussion in 'Scripting' started by masterpug13, Apr 21, 2019.

  1. masterpug13

    masterpug13

    Joined:
    Mar 31, 2019
    Posts:
    19
    Greetings again!

    This is likely a noob question, and I apologize (but I am a noob). TLDR: I've implemented A* Navigation for my enemies. However, I don't want them all navigating to a singular point. In fact, I want them to randomly select a point, then when they reach it (or at some point in between) they select a new one (or the same one) at random.

    What I can't seem to wrap my brain around is how to get the waypoints into some sort of form I can randomize. In my head it should look like:
    1. Get GameObjects
    2. Somehow get the transform of the GameObjects
    3. Somehow assign numbers to those transforms (0 to X, X being the highest count)
    4. Use a random int generator to select a path from 0 to X
    What I don't know is how to actually get all of that data into some format where I can call it numerically. Apparently I can't use "GetChildren", or at least I don't think so. That would have been easiest.

    So far I have created an array of waypoint objects, then extracted their transforms. But there is no way to tell which order those transforms are in. Also, they likely aren't assigned to any particular order, right? Just a pool of numbers. Or am I crazy?
    Code (CSharp):
    1.     public GameObject[] waypointSpots;
    2.  
    3.     public void Start()
    4.     {
    5.         touched = false;
    6.         foreach (GameObject waypoint in waypointSpots)
    7.         {
    8.             transform.position = new Vector3();
    9. }
    EDIT - The A* Navigation I am using refers to this - https://www.youtube.com/playlist?list=PLFt_AvWsXl0cq5Umv3pMC9SPnKjfp9eGW. If you haven't seen it, seems like a very solid system. That is until Unity gets some form of 2D Navi Mesh.
     
  2. masterpug13

    masterpug13

    Joined:
    Mar 31, 2019
    Posts:
    19
    I am trying to do this a slightly different way, but it seems like it takes two arrays. One for the game objects, one for the transforms. It seems odd to have to shift these between lists like that. But for the life of me, I couldn't get transform.position to work with the GameObject array. Still have to figure out how to get a random pull from the list.

    Code (CSharp):
    1.     public List<GameObject> WayPointSpots;
    2.     public List<Vector3> WayPointLocations;
    3.  
    4.     public void Start()
    5.     {
    6.         touched = false;
    7.         WayPointSpots = new List<GameObject>(GameObject.FindGameObjectsWithTag("waypoint"));
    8.         foreach (GameObject aWayPoint in WayPointSpots)
    9.         {
    10.             Vector3 myWayPoint = aWayPoint.transform.position;
    11.             WayPointLocations.Add(myWayPoint);
    12.         }
    13.  
    14.  
    15.        
    16.     }
     
  3. masterpug13

    masterpug13

    Joined:
    Mar 31, 2019
    Posts:
    19
    More tinkering, but I am still lost as to getting the random vector3 out of this code and into my other class.

    Far as I can tell, I am pulling a random vector3, but it isn't in a static field so I can't have another class access it. In my mind, the enemies should be talking to this waypoint system, looking for what waypoint they should progress to next. But so far, the system is just setting the waypoint with no way for them to talk to it.

    Code (CSharp):
    1. {
    2.     public List <GameObject> WaypointList;
    3.     public List <Vector3> Points;
    4.  
    5.     public void Start()
    6.     {
    7.         foreach (GameObject waypoint in WaypointList)
    8.         {
    9.             Vector3 thiswaypoint = waypoint.transform.position;
    10.             Points.Add(thiswaypoint);
    11.         }
    12.     }
    13.  
    14.     Vector3 FoundWaypoint()
    15.     {
    16.         int indexNumber = Random.Range(0, Points.Count - 1);
    17.         Vector3 wayChosen = Points[indexNumber];
    18.         return wayChosen;
    19.     }
    20. }
     
  4. masterpug13

    masterpug13

    Joined:
    Mar 31, 2019
    Posts:
    19
    Turns out I need a Transform, not a vector3. So I went back, did some coding. Now it is looking like I am not producing a valid transform for the 'unit' to take on moving.

    Waypoint code -
    Code (CSharp):
    1. public class Waypoints : MonoBehaviour
    2. {
    3.     public static List <Transform> Points;
    4.     private GameObject[] myWaypoints;
    5.  
    6.     public void Start()
    7.     {
    8.         myWaypoints = GameObject.FindGameObjectsWithTag("Waypoint");
    9.          
    10.         foreach (GameObject waypoint in myWaypoints)
    11.         {
    12.             Transform thiswaypoint = waypoint.transform;
    13.             Points.Add(thiswaypoint);
    14.         }
    15.     }
    16.  
    17.     public static Transform FoundWaypoint()
    18.     {
    19.         int indexNumber = Random.Range(0, Points.Count - 1);
    20.         Transform wayChosen = Points[indexNumber];
    21.         Debug.Log("New Path Found");
    22.         return wayChosen;
    23.     }
    24. }
    Unit code (that pertains to the target, which the waypoint code is supposed to be handing off) -
    Code (CSharp):
    1. public class Unit : MonoBehaviour
    2. {
    3.     protected Transform target;
    4.  
    5.     private void Start()
    6.     {
    7.         Transform target = Waypoints.FoundWaypoint();
    8.         PathRequestManager.RequestPath(transform.position, target.position, OnPathFound);
    9.  
    10.     }
    11. }
    I feel like the answer is staring at me in the face, but maybe this is more complicated than I think it is. Any ideas?

    EDIT - not sure if having the error helps but -
    NullReferenceException: Object reference not set to an instance of an object
    Unit+<FollowPath>c__Iterator0.MoveNext () (at Assets/Scripts/Unit.cs:78)
     
  5. lordconstant

    lordconstant

    Joined:
    Jul 4, 2013
    Posts:
    389
    The error you posted is in a part of the code we cant see. Line 78 of Unit.cs.

    The error suggests something isnt set in your follow function & could cause your unit toto not follow its path.
     
    masterpug13 likes this.
  6. masterpug13

    masterpug13

    Joined:
    Mar 31, 2019
    Posts:
    19
    Right you are! Appologies. That is the IEnumerator for FollowPath().

    Code (CSharp):
    1. IEnumerator FollowPath()
    2.     {
    3.         if (isWalking == true)
    4.         {
    5.             steps ++;
    6.             Vector3 currentWaypoint = path[0]; //This is line 78.
    7.  
    8.             while (true)
    9.             {
    10.                 if (transform.position == currentWaypoint)
    11.                 {
    12.                     targetIndex++;
    13.                     if (targetIndex >= path.Length)
    14.                     {
    15.                         yield break;
    16.                     }
    17.                     currentWaypoint = path[targetIndex];
    18.                 }
    19.                 transform.position = Vector3.MoveTowards(transform.position, currentWaypoint, speed * Time.deltaTime);
    20.                 yield return null;
    21.             }
    22.          
    23.         }
    24.     }
    EDIT, did more tinkering. Moved both the GameObjects and Transforms to an array.

    I moved all of the Start script into the static void, and that got the unit object to move (and removed an object null error). However, it doesn't look like it is selecting new random waypoints. Seems to just be picking the same one over and over. I see Random.Next referenced in other c# scripts, but mine tells me .Next isn't valid for Random.
     
    Last edited: Apr 24, 2019