John
John

Reputation: 307

Unity is storing the gameobjects in my arrays out of order

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

Answers (2)

TEEBQNE
TEEBQNE

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

derHugo
derHugo

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

Related Questions