there is no easy way to do this, as you have to write a custom sorting comparer which can be quite cumbersome.
but there is a hack that you could apply.
if your names always have a space between the word and the number, you can split the two and pad the number so that all numbers are of the same length, but have leading zeroes.
var gos = GameObject.FindGameObjectsWithTag("Person");
const int DIGITS = 4; // how many total digits you'd like
string[] paddedNames = new string[gos.Length];
for(int i = 0; i < gos.Length; i++) {
var name = gos[i].name;
name.SplitOnce(name.IndexOf(" "), out var word, out var num);
paddedNames[i] = $"{word} {num.PadLeft(DIGITS, '0')}";
}
Array.Sort(paddedNames);
// paddedNames are now properly sorted (but have zeroes)
// this is a general purpose extension (should go into a separate static class)
static public void SplitOnce(this string s, int index, out string left, out string right) {
if(index < 0 || index >= s.Length - 1) { left = s; right = string.Empty; }
else { left = s.Substring(0, index); right = s.Substring(index + 1); }
}
you can also do something like this (probably even better, because no zero padding)
var gos = GameObject.FindGameObjectsWithTag("Person");
var sortedList = new SortedList<int, int>();
for(int i = 0; i < gos.Length; i++) {
var name = gos[i].name;
name.SplitOnce(name.IndexOf(" "), out _, out var num);
sortedList.Add(int.Parse(num), i);
// here we use sorted list that is auto-sorted,
// but we store the original index as well
}
var finalList = new List<GameObject>();
foreach(var item in sortedList) {
// because this foreach is in sorted order
// we can use the stored index to fetch the original GO
finalList.Add(gos[item.Value]);
}
// you can do finalList.ToArray() if you need an array
(edit: this has to be modified to work with the words as well, it’s just an idea;
final solution is down, so keep reading)
if this still isn’t good enough for you try to look for alphanumeric (or natural) sorting comparer.
it is easy to run, you just do
GameObject.FindGameObjectsWithTag("Person").OrderBy(go => go.name, new SomeComparer());
or you can use Array.Sort on the result without having to use Linq
var result = GameObject.FindGameObjectsWithTag("Person");
Array.Sort(result, new SomeComparer());
but you have to code the entire class that does this
you may want to check out this (the answer by J.D. with 28 likes)
or this (the answer by VVS with 4 likes)
finally, and personally I think this one is a winner
you can make a very small comparison method, and use List.Sort instead
var gos = GameObject.FindGameObjectsWithTag("Person");
var list = new List<GameObject>(gos);
list.Sort((a, b) => NaturalComparer(a.name, b.name));
// DONE
static int NaturalComparer(string a, string b) {
a.SplitOnce(a.IndexOf(" "), out _, out var num1);
b.SplitOnce(b.IndexOf(" "), out _, out var num2);
int n1 = int.Parse(num1), n2 = int.Parse(num2);
if(n1 < n2) return -1;
if(n1 > n2) return +1;
return 0;
}