Unfortunately the order of elements can vary here… So when I make a WebGL-Build, the order is not like in the Editor.
So how can I sort all arrays by name?
Meaning Waypoint1, Waypoint2…
You can get the proper order, as seen in editor , with a little mucking around.
First, locate the transform in the scene that contains all the waypoints (im assuming for logical and clarity reasons, all the waypoints would be under one root transform gameObject somehwere. GetComponentsInChildren of the root transform… should return them in order as placed, unlike FindObject.
I use this approach often and it hasnt let me down yet.
until you do, you may do things the old-fashioned way, if you feel like that is more in line with your understanding.
the Sort method on lists and arrays relies on a so-called delegate declaration called Comparison
it declares the following
public delegate int Comparison<in T>(T x, T y);
so what this says is basically you would need to supply a function that has the same signature
you obviously replace T with string for example and you get
int MyComparison(string a, string b) {
// something
}
That something is shown by Kurt above
a.name.CompareTo(b.name);
because strings implement IComparable which requires CompareTo method
so you can also do this, and ignore lambdas
myList.Sort(MyComparison); // < obviously this belongs inside some function
int MyComparison(string a, string b) {
return a.CompareTo(b);
}
I really like that you also try to be as specific as possible in the hope that future readers get the most out of the answer.
The fact that lambda expressions are usually used with inferred arguments makes it often harder to read as the type is not necessarily immediately obvious in all cases. Note that you can actually specify the type of the arguments of a lambda expression explicitly: (GameObject a, GameObject b) => ...
Another little quirk about lambdas is, when you only have a single argument (not the case for Sort, but you may encounter it elsewhere), the parentheses can be omitted and it’s just a=>Dosomething(a, 42);. It’s also possible to use the lambda syntax for methods that don’t receive any arguments like that: ()=>....
Since we’re already beating a dead horse, lets continue
A lambda expression is usually meant to return a value. The return type is also inferred from whatever the => points to. So ()=>"Hello World"; is a method without arguments that returns a string.
It’s also possible to use the lambda syntax with a full method body by using curly braces. In that case, if you want to return a value, you have to use the usual return keyword.
System.Func<int> someFunc = ()=>{Debug.Log("I was here"); return 42;};
int val = someFunc(); // returns 42 and prints "I was here"
That’s pretty much all that could be said about lambdas I guess ^^
edit:
I just forgot to mention that lambda expressions, just like ordinary anonymous methods can also become “closures”. That means they can actually get hold of a local variable outside the method scope. Note that closures actually “close over” / capture the actual variable, not just the value it contains. To illustrate that, here’s a total crazy construct:
NEVER DO THIS
public struct Crazy
{
public System.Func<int> myGetter;
public System.Action<int> mySetter;
public System.Action someAction;
public static Crazy Create()
{
int someLocalVariable = 42;
Crazy ret = new Crazy();
ret.myGetter = ()=>someLocalVariable;
ret.mySetter = a=>someLocalVariable = a;
ret.someAction = ()=>someLocalVariable++;
return ret;
}
}
With that struct we can do this:
var s = Crazy.Create();
Debug.Log("val: " + s.myGetter()); // prints "val: 42";
s.mySetter(7);
Debug.Log("val: " + s.myGetter()); // prints "val: 7";
s.someAction();
Debug.Log("val: " + s.myGetter()); // prints "val: 8";
Note that the struct itself does not contain any int variable, only 3 function pointers / delegates. Those 3 lambda expressions are all closures since they use a variable from outside their scope. Usually that local variable would only exist while the “Create” method is still running. However a closure will actually encapsulate the variable in a closure object that outlives the Create method.
Closures can be useful in a lot cases, especially for sorting or search function. For example if you want to sort a gameobject array based on their distance from another object, the lambda can actually capture that other object and use it inside the comparison function.
Though you did forget to say a thing or two about the generic delegates Action and Func. But it’s hard to talk about it, if readers have no context about delegates in general.
Whoever is reading this, maybe you’ll find this bit useful:
Just like classes declare and typify objects and interfaces prescribe public portions of these objects, delegates declare the method signatures to be used as a template for some local implementation. The important part is that delegates are top-level declarations just as class and interfaces are!
(Unless you nest such declarations, then they’re nested, which is usually how delegates are used, but there are cases where this isn’t desirable.)
I’m sure there are people who’re like “duh” but for some reason I never thought of them as top-level, maybe because they’re method-like, idk. It took me some time to confirm this, sadly I forgot the exact situation that prompted me to look it up, but it was totally some kind of chicken-egg problem.
I really should name those last two arguments but perhaps I’m just beating a dead lambda.
At least the lambdas don’t have lambdas inside 'em. That’s really when I reach for good old functions!
But I guess it has a few .Attach() calls within .Attach()… I almost never AddComponent() randomly in code… it always seems worthwhile to wrap it in a static factory method called .Attach() if you already HAVE a GameObject, or .Create() if you want one created. Part of this pattern:
Factory Pattern in lieu of AddComponent (for timing and dependency correctness):