Loading game objects into a generic list in specified order

Greetings all,

I’m using C# and a generic List.

I have a setup where the user chooses a path which may take them through one or more Unity scenes. Because of this, I have created a script “Scene.cs” to hold a list of waypoints for the user to visit. Each waypoint may have a series of two or three objects to click on. Clicking may play an audio clip, a movie texture (video clip), or a static image with an audio clip.

When the scene loads, the “Scene.cs” script creates a list of waypoints (in Start):

foreach(Waypoint wp in GetComponentsInChildren<Waypoint>(true))
		{
			waypointList.Add(wp);
			// Ensure all waypoint scripts disabled, trigger will activate the script
			wp.enabled = false;
		}

I added an additional waypoint, Start, as logical place holder. When I use Start (waypoint), it loads Start, Waypoint 1, Waypoint 2, and Waypoint 3 in the list in the correct order.

I duplicated Start and renamed it to End as another waypoint. In the Unity Hierarchy, End jumps up in front of Start which leads me to believe GameObjects are listed in alphabetical order. When I run my scene the list shows Start then End, and the rest of the waypoints follow. This leads me to believe that the list is not using alphabetical order.

So, I deleted End and created an empty GameObject, attached my waypoint script to it, renamed it to End and expected it to jump to the front. In the Hierarchy, this happened as I expected. In the generated list it jumped to the first element of the list.

When I changed the name to Waypoint 4, it jumped to the end of the Hierarchy but remained the first element in the list.

Next I deleted that, created a new empty Game Object, renamed it to Waypoint 4 and attached the script. This time, it showed up at the end of the Hierarchy and as the last element of the list.

For grins, I changed the name from Waypoint 4 to End. In the Hierarchy, it jumped to the top (alphabetical) but in the List it remained as the last element of the list.

So, does anyone know by what order game objects are inserted into a list?

I want to be able to guarantee the order. It seems that the behavior changes depending on if you duplicate one and rename it. Seems completely bizarre. For organization, I’d like the way it shows up in my Hierarchy to be the same in the generated list.

Can anyone point me in the right direction?

Honestly, if I wanted to be sure I would just declare the list public and manually assign its elements in the correct order in the inspector. However, this is pretty slow and time-consuming, and is the kind of thing that you should really get a computer to do anyway.

So, alternatively, you could use a special case for the beginning and end variables (assign them manually in the inspector), and then use a sorted list to sort them into alphabetical order:

SortedList<string, Waypoint> alphabetList = new SortedList<string, Transform>();
foreach(Waypoint wp in GetComponentsInChildren<Waypoint>())
{
    if(wp == startWaypoint || wp == endWaypoint)
    {
        continue;
    }
    alphabetList.Add(wp.gameObject.name, wp);
}

List<Waypoint> sortedWaypoints = new List<Waypoint>(alphabetList.Values);
sortedWaypoints.Add(endWaypoint);
sortedWaypoints.Insert(0, startWaypoint);

foreach(Waypoint element in sortedWaypoints)
{
    Debug.Log(element.gameObject.name);
}

I think that should do it. Sorry I couldn't answer your actual question, but I have a sneaking suspicion that it works in a way that is fairly opaque and magical, being one of those things that gets completely broken if you mess with the Library folder.

If you'd like to ensure that your list is always alphabetical, just sort the resulting list with a custom IComparer that takes GameObjects as a parameter.

http://msdn.microsoft.com/en-us/library/234b841s.aspx

And just 'cause, here's a quick example with my IComparer:

using System.Collections;
using UnityEngine;
using System.Collections.Generic;

public class GameObjectComparer : IComparer<GameObject>
{
    return string.Compare(x.name, y.name, false);
}

public class YourClass : MonoBehaviour
{
    public List<GameObject> yourList = new List<GameObject>();

    void Start()
    {
        GameObjectComparer gameObjectComparer = new GameObjectComparer();
        yourList.Sort(gameObjectComparer);
    }
}