Reputation: 307
I'm making a tower defense game on unity. I'm pretty new and pretty bad to be honest haha. Anyway I want my enemies to walk through a waypoint system. I made an array this is the code.
public GameObject[] wpoints;
public int currentindex;
// Start is called before the first frame update
void Start()
{
wpoints = GameObject.FindGameObjectsWithTag("wpoints");
}
After a bunch of silly mistakes, I got them to move! But they moved in a very weird pattern. It turns out unity stored all my waypoints out of order in the array. Instead of point1,point2,point3... its point 8,point15,point2. Help?
Upvotes: 0
Views: 636
Reputation: 6266
The issue is FindGameObjectsWithTag
does not return any useful ordering of objects. It is undocumented as far as I know as to how a lot of Unity's FindAll
methods sort data it finds. If you want to sort the data after finding your waypoints, you can do that.
public class WaypointSorter : IComparer
{
int IComparer.Compare( System.Object x, System.Object y)
{
return((new CaseInsensitiveComparer()).Compare(((GameObject)x).name, ((GameObject)y).name));
}
}
private void Start()
{
IComparer newComparer = new WaypointSorter();
wpoints[] gameobjects = GameObject.FindGameObjectsWithTag("wpoints");
Array.Sort(wpoints, myComparer);
}
Edit: I will leave my answer just as an alternative, but using Linq
or GetComponentsInChildren
as mentioned by derHugo is an easier/cleaner solution.
Upvotes: 0
Reputation: 90659
FindGameObjectsWithTag
is not guaranteed to order the result in any meaningful way.
If you want them e.g. in the order they appear in the Hierarchy I would rather give them all a dedicated component like e.g.
// Doesn't have to do anything, just used to identify waypoints
public class Waypoint : MonoBehaviour { }
place them all under a certain object and use e.g. GetComponentsInChildren
this one is guaranteed to return the objects in the hierarchy order top to bottom.
If they are spread in your scene under multiple different parent objects without a common root you could also go through all the root objects using Scene.GetRootGameObjects
and do
var waypoints = new List<Waypoint>();
foreach(var root in SceneManager.GetActiveScene().GetRootGameObjects())
{
waypoints.AddRange(root.GetComponentsInChildren<Waypoint>(true));
}
wpoints = waypoints.ToArray();
Or alternatively sort them by name no matter what using Linq OrderBy
using System.Linq;
...
wpoints = GameObject.FindGameObjectsWithTag("wpoints").OrderBy(wp => wp.name).ToArray();
Upvotes: 3