Thanks in advance for the help, When I pull the help file for the Sort command for unityScript it only shows a basic use. Can someone post a detailed use of Sort? I would like to sort a Gameobject array without splitting the name and vector3 into two arrays which seems like a bigger can of worms. I have read about dictionary My goal is to create an array of the nearest 4 GameObjects by sorting the array by the vector3 like.., go.Sort(vector3) This seems do able but I dont know the correct operation. Thanks, Beansly Jones
What you are looking is an implementation if IComparar. http://support.microsoft.com/kb/320727 That's one way doing it, by creating IComparar helper classes and pass them to sort. The other way is to use Linq or Lambda expressions Lambda Code (csharp): GameObject[] array = ...; array.Sort( (a, b) => { // Do compare code here. a and b are two objects being compared to // the result must be // 1, if a > b // 0, if a == b // -1, if a < b Vector3 distanceA = ((GameObject)a).transform.position - transform.position; Vector3 distanceB = ((GameObject)b).transform.position - transform.position; if(distanceA.sqrMagnitude > distanceB.sqrMagnitude) { return 1; } else if(distanceA.sqrMagnitude < distanceB.sqrMagnitude) { return -1; } return 0; } ); Linq Code (csharp): using System.Linq; ... array.OrderBy( x => x.name); // sorts by name. though, I think Linq only works with objects which implement IComparable interface and I think Vector3 doesn't do it.
Here's an actual sorting algorithm. I believe its just selection sort. So if you have less then 1000 elements it should be pretty fast. (Example from my project) Code (csharp): public void SortArmorList() { GameObject holder; for(int i = 1; i < armorItems.Count; i++) { int j = i; while(j > 1) { if(GetItem(armorItems[j-1]).itemScore < GetItem(armorItems[j]).itemScore) { holder = armorItems[j-1]; armorItems[j-1] = armorItems[j]; armorItems[j] = holder; j--; } else break; } } You can use the distance calculation up above and then sort them in the area based on that. Then all you would need to do is return the top four positions.
Code (csharp): GameObject[] array = ...; array.Sort( (a, b) => { // Do compare code here. a and b are two objects being compared to // the result must be // 1, if a > b // 0, if a == b // -1, if a < b Vector3 distanceA = ((GameObject)a).transform.position - transform.position; Vector3 distanceB = ((GameObject)b).transform.position - transform.position; if(distanceA.sqrMagnitude > distanceB.sqrMagnitude) { return 1; } else if(distanceA.sqrMagnitude < distanceB.sqrMagnitude) { return -1; } return 0; } ); This is UnityScript right? I copied it in and am getting errors. Do I need to send an array with only 2 variables to be sorted? Currently I am sending a GameObject which has many. This part of the code I do not understand... ((GameObject)a). does there need to be a variable named "a" inside the Array passed to it?
a and b defined are in this line : Code (csharp): array.Sort( (a, b) => { (a, b) => { .. } is actual lambda for anonymous methods/delegates. it's same as Code (csharp): array.Sort( delegate(object a, object b) { ... } ); This anonymous function is called every time, when the Sort method compares to objects. In UnityScript you can write delegates as (as far as i know): Code (csharp): array.Sort( function(a, b) { // compare code here } ); But do not use UnityScript Arrays (var blah : Array = new Array()), they are slow. Use .NET built-in arrays (the one with []) Normally, the IComparer.Compare interface defines takes two "objects" Code (csharp): int IComparer.Compare(object a, object b) so you must cast them up to GameObject. Dunno anymore if this is necessary when using lambda. It's the same as GameObject gameObjectA = (GameObject)a; or GameObject gameObjectA = a as GameObject;
This should work in UnityScript: Code (csharp): import System.Collections.Generic; class DistanceSort implements IComparer.<GameObject>{ var transformPos : Vector3; function DistanceSort(pos : Vector3){ transformPos = pos; } function Compare(go1 : GameObject, go2 : GameObject){ if (go1==null go2==null) return 0; if (go1==null) return -1; if (go2==null) return 1; var distance1 = Vector3.Distance(go1.transform.position, transformPos); var distance2 = Vector3.Distance(go2.transform.position, transformPos); if (distance1 < distance2) return -1; if (distance1 > distance2) return 1; return 0; } } function Start(){ var allObjects = GameObject.FindObjectsOfType(GameObject); System.Array.Sort(allObjects, new DistanceSort(transform.position)); for (obj in allObjects) Debug.Log(String.Format("Name:{0} Position:{1}", obj.name, obj.transform.position)); } Note that I had to pass transform.position as an argument, the IComparer class couldn't access it otherwise. Not sure if this is expected behavior or a bug in the UnityScript implementation.
Tony thank you for converting this to unityScript. And thanks to everyon else posting also. I am trying to get to know sorting arrays intimently since they seem so integeral to scripting. Where I was/am getting lost was with "implements IComparer" I have searched the manual and there are no refrences internal to unity. So I was thinking they were for another launguage. Are these functions being enabled via the import.collections.generic;?
I wouldn't say it is integral to scripting (I don't think I used Sort at all in my last 2 games), but it's quite useful when scripting certain things (such as inventories and databases). Honestly, I'm not sure why it uses implements rather than extends. And import simply imports the namespace, otherwise you would have to type System.Collections.Generic.IComparer rather than IComparer each time you used it.
It says implements because IComparer is an interface, not a class. Classes get extended, interfaces get implemented. In C# the colon is both implement and extend so it doesn't matter as much.
Keyword 'extends' once did double duty as well: http://forum.unity3d.com/threads/10329-Implementing-interfaces-(IComparable)-in-Unity-Javascript
Ok I am completely lost. Can anyone help me please? I have just made the switch from GameSalad to Unity. I am almost finished my first game but I am stuck. Im not sure how this sorting works. I would like to create an onscreen list of 8 cars (Car 1, Car 2, etc). Each car has a script attached to it called Script 1, Script 2, etc. I would like to sort the list of names by variables (Variable 1, Variable 2, etc) from highest to lowest (ascending) during the game. Im looking at all these codes and what you guys are suggesting but its still looks Chinese lol PS. Car 1 has a script called Script 1 in it which contains a variable called Variable 1 in it. Car 2 has a script called Script 2 in it which contains a variable called Variable 2 in it. etc, etc Hope I provided enough info. Please & Thank You!
It looks that Array.Sort from Unity, is not stable, probably the underlying algorithm is quicksort, despite in the C# documentation it states, that for small arrays, Insertion Sorting should be used, which is stable. Probably someone from Unity should explain more.
1) you revived a thread that hasn't been posted in for over 3 years 2) Unity did not implement Array.Sort, nor does C#. It's up to the .net runtime used, and the one used by Unity comes from mono (well technically there's some gotchas to that even more in recent years), so it's really the mono implementation of Array.Sort you'd want to be looking into 3) Usually mono tries to follow the defined functionality of .Net... and with that, the documentation does say that it uses insertion for small array (under 16), heapsort for special case arrays, and quick sort in all others. But not only does it say that, it also explicitly states that the sort is considered 'unstable': https://docs.microsoft.com/en-us/do...amework-4.7.2#System_Array_Sort_System_Array_
Thanks for answer, but insertion sort algorithm is stable, while the sort in Unity is not stable,even if I've got an array with only 3 elements which are all equals, they are re-ordered, the "compare" delegate is called even to compare an element with itself. Something's very weird. Eventually I implemented the "insert sorting" myself to assure a stable sorting.
While insertion sort may be considered stable. The documentation explicitly states that the Array.Sort method (not just quicksort) is to be considered unstable. So by definition, it's unstable. Which means that whatever implementation mono went with, it is allowed to be unstable, since the Microsoft definition of Array.Sort allows it to be unstable. Note, Unity uses mono. Not .Net. And mono doesn't need to use the same implementation as .Net (actually they technically aren't allowed to use the same exact implementation). All they have to do is successfully meet the definition of the API. Array.Sort defines itself as unstable, so whatever mono does for its implementation, it's allowed to be unstable. And at the end of the day... has nothing to do with Unity. Unity didn't create mono. Yes, it's called mono. If you need a stable sort, you'll need to implement it yourself. Since by definition Array.Sort is not stable.