- Home /
Order Objects Based on Proximity
Hi, all!
I am using Physics.OverlapSphere to get an array of all colliders in a certain range.
Currently in my script, it picks a random object. However, I would like to order these objects in the array based on proximity to the gameObject.
How would I go about this?
Thanks!- YA
You could check my answer here for a bubble-sort technique : http://answers.unity3d.com/questions/246781/sort-transforms-by-distance-to-player.html
Your solution seems to be more practical than $$anonymous$$e, but I just figured it out. Thanks, though! This will be valuable later!
Since .NET has sorting built-in, you don't usually need to write your own sorting code, you just need a function that returns -1, 0, or 1 based on some criteria, so the sort can work based on whatever you need.
Ah. Thank you for the advice. This will be good to look into.
Answer by Eric5h5 · May 06, 2013 at 02:27 AM
You can use an inline function to sort an array:
var possibleTargets = Physics.OverlapSphere (transform.position, 100);
System.Array.Sort (possibleTargets,
function (a : Collider, b : Collider)
(transform.position - a.transform.position).sqrMagnitude.
CompareTo ((transform.position - b.transform.position).sqrMagnitude));
You can also use an external function, which may be more readable, since it's not all on one line:
System.Array.Sort (possibleTargets, DistanceSort);
function DistanceSort (a : Collider, b : Collider) : int {
return (transform.position - a.transform.position).sqrMagnitude.
CompareTo ((transform.position - b.transform.position).sqrMagnitude);
}
But what would be the next step? Add a switch case to populate the array before or after an element?
If you want the array based on some criteria, you'd set it up first (probably using a List), then sort it. You can use List.Sort in pretty much the same way as Array.Sort.
But I am trying to sort transforms by indexing them with their respective distances from the player at a given time.
That makes 1 Transform, float pair per object. Sort by float, retrieve transform.
This looks to me like you are just sorting a list(?)
Oh I see. You are supplying Array.Sort with the parameters of the Transforms and a function to use to decide on where they go, because your external function returns an int.
Answer by Bluk · May 05, 2013 at 05:52 PM
-Construct an array (or two, or associative, or hashtable) of distances between the gameObject and the colliders (http://docs.unity3d.com/Documentation/ScriptReference/Vector3.Distance.html )
-Sort the array
That's pretty much it
To get the distance with @Bluk's method, do the square magnitude distance, rather than the magnitude distance. It won't change the order of the objects in the array, and it's faster ((a-b).sqr$$anonymous$$agnitude)
However, depending on how many objects you have, this method may or may not work. If you have fewer than a thousand objects you should be fine; if not, there are other methods that are faster but harder to implement.
I know how to create the array of distances and sort them. But once that is done, I will have an array of floats. How do I get the array of objects to line up with the array of corresponding floats?
I am not new to using hastables but am new to coding them and making use of them. I am using UnityScript as of right now.
$$anonymous$$y question is about the sorting step. I would be very pleased if you could expound upon what you mean.
So I have dynamically populated a dictionary with the key being the object and the value being the distance from player. How do I sort the dictionary by the value per key?
In case anyone is interested, here is my finished code:
var myRocketCount : int = ship.activeGun.unique.Value;
var myTargets = new Dictionary.<float, Transform>();
var myDistances : float[] = new float[myRocketCount];
var possibleTargets : Collider[] = Physics.OverlapSphere( Vector3( aim.position.x, aim.position.y, GameObject.Find( "EnemyGrid" ).transform.position.z), 30 );
if( possibleTargets.length >= myRocketCount ){
for( var i = 0; i < myRocketCount; i++ ){
if(StaticFunctions.HasProperty( possibleTargets[i].transform, "enemy" )){
myTargets.Add( Vector3.Distance(possibleTargets[i].transform.position, aim.position), possibleTargets[i].transform);
myDistances[i]= Vector3.Distance(possibleTargets[i].transform.position, aim.position);
}
}
System.Array.Sort( myDistances );
for( var w = 0; w < myDistances.length; w ++){
if(myRocketCount > 0 && ship.activeGun.plasma.current >= ship.activeGun.plasmaCost.Value){
var myRocket : Transform = Instantiate( ship.activeGun.bullet, Vector3( GunC.position.x,GunC.position.y-3, GunC.position.z + 2), GunC.rotation);
myRocket.GetComponent( RocketAim ).target = myTargets[ myDistances[w] ];
myRocketCount --;
ship.activeGun.plasma.current -= ship.activeGun.plasmaCost.Value;
}
}
}
Answer by Griffo · May 05, 2013 at 06:12 PM
Place this on an empty game object and it should give you every object in the blastRadius in order of closest first, needs altering to suit your requirements, amount, distance .. ect.
#pragma strict
var myArray : String[] = new String[200];
var blastRadius : float = 100;
private var i : int;
function Start () {
AreaDamageEnemies(transform.position, blastRadius);
}
function Update () {
}
function AreaDamageEnemies(location : Vector3, radius : int){
var objectsInRange : Collider[] = Physics.OverlapSphere(location, radius);
for (var col : Collider in objectsInRange){
while(i < objectsInRange.length){ // Go through the objectsInRange array (objects in the Physics.OverlapSphere radius)
myArray[i] = objectsInRange[i].name; // Add each GameObject.name to myArray
print(objectsInRange[i].name);
i++;
yield;
}
}
}
@Griffo- this would lead me to believe that OverLapSphere already returns an array of closest objects first.
Your answer
![](https://koobas.hobune.stream/wayback/20220613101554im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
Help with Array script 1 Answer
Fading GUI text 2 Answers
Mesh Inertia Tensor? 1 Answer
Learning process 1 Answer
What type of sign do I use for a Scene? 2 Answers