按名称对GameObject数组进行排序

时间:2017-07-24 20:44:52

标签: c# arrays unity3d

我创建了一个脚本,用于生成当前场景中所有立方体的数组:

public GameObject[] allCubes; 

void Awake()
{
    allCubes = GameObject.FindGameObjectsWithTag("cube");
}

问题是数组在检查器中看起来像这样:

https://i.gyazo.com/69f2f844183fe6e592e61c1517267da1.png

我已经尝试过这样做了:

public GameObject[] allCubes; 

void Awake()
{
    allCubes = GameObject.FindGameObjectsWithTag("cube");
    Array.Sort (allCubes);
}

然而,这给了我一个错误:

InvalidOperationException: No IComparable or IComparable<UnityEngine.GameObject> interface found.
System.Array.compare[GameObject] (UnityEngine.GameObject value1, UnityEngine.GameObject value2, IComparer`1 comparer) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System/Array.cs:1756)
System.Array.qsort[GameObject,GameObject] (UnityEngine.GameObject[] keys, UnityEngine.GameObject[] items, Int32 low0, Int32 high0, IComparer`1 comparer) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System/Array.cs:1722)
System.Array.Sort[GameObject,GameObject] (UnityEngine.GameObject[] keys, UnityEngine.GameObject[] items, Int32 index, Int32 length, IComparer`1 comparer) (at

我该怎么办?

2 个答案:

答案 0 :(得分:0)

您不会说要用于对多维数据集进行排序的参数

这是使用Array.Sort按名称进行比较的代码:

class GameObjectComparerByName : IComparer<GameObject> {
 int IComparer<GameObject>.Compare(GameObject x, GameObject y)
{
     return string.Compare(x.name, y.name);  
} 

随处使用:

Array.Sort(allCubes,new GameObjectComparer ());

说明:

对于Array.Sort方法,它必须实现IComparable<UnityEngine.GameObject>接口 C#编译器不知道如何比较作为GameObject实例的两个cube对象并抛出异常。

示例:

   class Testy {
    private int bla;        
    public int Bla
    {
        get { return bla; }
        set { bla = value; }
    }
    public Testy(int bla )
    {
        this.bla = bla;
    }
}

编译器不知道如何解释x>yx<=y等... 当x,y是示例类Testy的两个对象时,您实现了IComparer的接口

class TestyComparer : IComparer<Testy> {


    int IComparer<Testy>.Compare(Testy x, Testy y)
    {
        if (x.Bla == y.Bla)
        {
            return 0;
        }
        else if (x.Bla > y.Bla)
        {
            return 1;
        }
        else // (x.Bla < y.Bla)
        {
            return -1;
        }
        //all lines works equals than:
        //return x.Bla < y.Bla
    }
}

现在你可以使用了    Array.Sort(testyArray, new TestyComparer());

在你的情况下实现

 class GameObjectComparer : IComparer<GameObject> {
     int IComparer<GameObject>.Compare(GameObject x, GameObject y)
    {
       //Compare the two cubes here
       //By the parameter you want to use to sor them (volume, proximity etc..)
         /*
            return <=-1;//Less
            return 0;//Equals
            return >=1;//Greather
         */        
    }

并做

Array.Sort(allCubes,new GameObjectComparer ());

如果你使用.Net 4.5或添加额外的类,你可以使用lambda作为Comparer接口,请参阅这篇文章Using lambda expression in place of IComparer argument

答案 1 :(得分:0)

根据您提供的屏幕截图,该字符串也包含int个值。您需要字母数字排序。我使用并推荐dotnetperls AlphanumComparatorFast {。}}。请参阅下文,了解可用于此的略微修改版本。

public GameObject[] allCubes;

void Awake()
{
    allCubes = GameObject.FindGameObjectsWithTag("cube");
    allCubes = allCubes.OrderBy(obj => obj.name, new AlphanumComparatorFast()).ToArray();
}

以下是AlphanumComparatorFast类的修改版本:

public class AlphanumComparatorFast : IComparer<string>
{
    public int Compare(string x, string y)
    {
        string s1 = x as string;
        if (s1 == null)
        {
            return 0;
        }
        string s2 = y as string;
        if (s2 == null)
        {
            return 0;
        }

        int len1 = s1.Length;
        int len2 = s2.Length;
        int marker1 = 0;
        int marker2 = 0;

        // Walk through two the strings with two markers.
        while (marker1 < len1 && marker2 < len2)
        {
            char ch1 = s1[marker1];
            char ch2 = s2[marker2];

            // Some buffers we can build up characters in for each chunk.
            char[] space1 = new char[len1];
            int loc1 = 0;
            char[] space2 = new char[len2];
            int loc2 = 0;

            // Walk through all following characters that are digits or
            // characters in BOTH strings starting at the appropriate marker.
            // Collect char arrays.
            do
            {
                space1[loc1++] = ch1;
                marker1++;

                if (marker1 < len1)
                {
                    ch1 = s1[marker1];
                }
                else
                {
                    break;
                }
            } while (char.IsDigit(ch1) == char.IsDigit(space1[0]));

            do
            {
                space2[loc2++] = ch2;
                marker2++;

                if (marker2 < len2)
                {
                    ch2 = s2[marker2];
                }
                else
                {
                    break;
                }
            } while (char.IsDigit(ch2) == char.IsDigit(space2[0]));

            // If we have collected numbers, compare them numerically.
            // Otherwise, if we have strings, compare them alphabetically.
            string str1 = new string(space1);
            string str2 = new string(space2);

            int result;

            if (char.IsDigit(space1[0]) && char.IsDigit(space2[0]))
            {
                int thisNumericChunk = int.Parse(str1);
                int thatNumericChunk = int.Parse(str2);
                result = thisNumericChunk.CompareTo(thatNumericChunk);
            }
            else
            {
                result = str1.CompareTo(str2);
            }

            if (result != 0)
            {
                return result;
            }
        }
        return len1 - len2;
    }
}

请勿忘记使用System.Linq;

导入using System.Linq;

对于没有数字的字符串排序,您只需使用:

public GameObject[] allCubes;

void Awake()
{
    allCubes = GameObject.FindGameObjectsWithTag("cube").OrderBy(go => go.name).ToArray();
}