Hi, I wonder if anyone can suggest a solution to this please?
What would be the best (most efficient) way for me to obtain a list of GameObject-Names, sorted by their relative distances to a target?
My immediate thought was to create a multidimensional array, containing the names and the distances - something like this:
[Object1, 100], [ Object2, 150], [Object3, 50] - etc
…then to use Array.Sort() on the number-side so that I will also retain the name-side list.
But it seems that Array.Sort() is not able to sort multidimensional arrays?
The only other thing I can think of is really convoluted. eg. having two separate arrays, one for the names and one for distances, then
i search through all of the distances for the smallest value,
ii store the ArrayNumber where the smallest value was found
iii remove smallest value from the array
iv find the corresponding name from the name array (based upon the stored number) and push it into a different array
v. repeat from (i) till distances array is empty…
seems a bit long winded to me tho?
Anyone have any better suggestions of how to do this? I’m sure it’s a fairly common operation to want to go in Game Dev?
Thanks for any suggestions!!
You’ll need to create a wrapper class that extends IComparable - this one should work:
class GOWrapper extends System.IComparable {
var gameObject : GameObject;
var distance : float;
function GOWrapper(me : GameObject, target : Transform) {
gameObject = me;
distance = Vector3.Distance(me.transform.position, target.position);
}
function CompareTo(obj: Object) : int {
var other :GOWrapper = obj; // Typecast to own class
return distance.CompareTo(other.distance);
}
}
//create an array of them
var array : Array = new Array();
array.Add(new GOWrapper(obj, target);
You should be able to sort that array.
One of the overloads for System.Array.Sort (see Mono docs) takes two arrays as parameters. It sort the elements of both arrays according to the values in the first array. You could put your names in one 1D array and the corresponding distances in another and this would give you the desired result.
1 Like
Thanks andeeee and StarManta (again!)
@ andeeee, that does sound like a good solution, but I don’t know anything about ‘overloads’ so maybe I should steer clear?
@ StarManta, hmmm, I think I nearly get that. As you can see below I’ve tried to put it into a simple workable example to test, but I’m not sure how to add to the array in the correct format (see the ???'s below). Or how to sort it? I don’t see how the ‘CompareTo’ function will get called?
In this example I’ve attached the script below to a GO called Master, and I could be comparing the distances between the all instances to the Master’s Transform…
// Set up a link to the master prefab (from the inspector)
var myPrefab : Transform;
class GOWrapper extends System.IComparable {
var gameObject : GameObject;
var distance : float;
function GOWrapper(me : GameObject, target : Transform) {
gameObject = me;
distance = Vector3.Distance(me.transform.position, target.position);
}
function CompareTo(obj: Object) : int {
var other :GOWrapper = obj; // Typecast to own class
return distance.CompareTo(other.distance);
}
}
function Start () {
var array : Array = new Array();
for (var i=0;i<10;i++) {
var temp = Instantiate (myPrefab, Vector3(Random.Range(-10, 10), 0, Random.Range(-10, 10)), Quaternion.identity);
temp.name = "Instance"+i;
array.Add(new GOWrapper(???, ???)); // not sure how to put the new instance and the comparing transform into this thing
}
array.Sort();
// this is the kind of outcome I would like to achieve:
print("The GO that is 3rd closest is "+ array[2].name);
}
… any chance of a little more assistance with this please, much appreciated?
There’s nothing to fear. “Overloaded” simply means that there is more than one function with the same name. The version that gets called depends on the parameters you pass. If you just use:-
System.Array.Sort(distances, names);
…then you should get the result you want. Incidentally, if you are using JavaScript then this will only work with built-in arrays (declared with square brackets), not with the JS Array class.
1 Like
Thank you very much andeeee and StarManta,
It only went and worked on me andeeee!
I’m sharing a copyable example of this with the community in case anyone else finds this useful…
// Set up a link to a master prefab (from the inspector)
var myPrefab : Transform;
private var arrayOfNames : Array;
private var arrayOfDists : Array;
function Start () {
arrayOfNames = new Array();
arrayOfDists = new Array();
for (var i=0;i<10;i++) {
var temp : Transform = Instantiate (myPrefab, Vector3(Random.Range(-10, 10), 0, Random.Range(-10, 10)), Quaternion.identity);
temp.name = "Instance"+i;
var dist = (temp.position - transform.position).sqrMagnitude;
arrayOfNames.Add(temp.name);
arrayOfDists.Add(dist);
}
sortByDistance(arrayOfNames, arrayOfDists);
print("GO "+arrayOfNames[0]+" is closest, and GO "+arrayOfNames[arrayOfNames.length-1]+" is the furthest.");
}
function sortByDistance(arrayN : Array, arrayD: Array){
var BuiltinArrayOfNames : String[] = arrayN.ToBuiltin(String);
var BuiltinArrayOfDists : float[] = arrayD.ToBuiltin(float);
BuiltinArrayOfDists.Sort(BuiltinArrayOfDists, BuiltinArrayOfNames);
arrayOfNames = new Array (BuiltinArrayOfNames);
arrayOfDists = new Array (BuiltinArrayOfDists);
}
cheers…
1 Like
Or snag this guy’s priority queue. It should take a second to make it use floats rather than ints.
1 Like
RobbieDingo, I was trying to do something very similar… thank you for posting that snippet - huge help!
Though doing the dual single dimensional array solution works well, is doing the wrapper class approach possible with Unity JS?
Can somebody please help me do the same as above in C#?