- Home /
geting the closest object from a array
hi i am making a tower defense game and i am working on the towers and i have a script that fills a array with all the enemies in the scene. but i want to know how to find the closest object in the array can anyone mod my script to work like that? here it is:
var target : Transform; var enemies : GameObject[]; function Update () { enemies = GameObject.FindGameObjectsWithTag("enemy"); transform.LookAt(target);
}
Answer by Michael La Voie · Apr 16, 2010 at 12:57 AM
You'll need to use Vector3.Distance:
var target : Transform; var enemies : GameObject[];
function Update () { enemies = GameObject.FindGameObjectsWithTag("enemy"); transform.LookAt(target);
if(enemies.length > 0) {
var closestEnemy = enemies[0];
var dist = Vector3.Distance(transform.position, enemies[0].transform.position);
for(var i=0;i<enemies;i++) {
var tempDist = Vector3.Distance(transform.position, enemies[i].transform.position);
if(tempDist < dist) {
closestEnemy = enemies[i];
}
}
//do something with the closestEnemy
}
}
i got this error Assets/Scripts/dartTower.js(12,22): BCE0051: Operator '
never $$anonymous$$d i fixed the problem :) anyway it works great thanks!
for anybody else who gets that error... use for(var i=0; i < enemies.Length; i++) {
Answer by Eric5h5 · Apr 16, 2010 at 02:00 AM
It's not a good idea to use FindGameObjectsWithTag every frame, because it's slow. It's also a better idea to have enemies be a Transform array instead of a GameObject array, because that way you don't have to get the transform component every time you check the distance of one of them. The enemies array should only be rebuilt when necessary; it may be better to add and remove from an array instead of using Find at all, but that's a little more complicated.
Also, Vector3.Distance is a bit slow because it involves a square root; it's better to use (a-b).sqrMagnitude instead. Since a tower isn't going to move, it's better to store transform.position in a variable so you aren't constantly getting the transform component. As well, it's almost certainly not necessary to get the closest enemy every frame, so try to do that only as often as needed.
var target : Transform; var myPosition : Vector3; var enemies : Transform[];
function Start () { GetEnemies(); myPosition = transform.position; target = FindClosest(enemies); }
function GetEnemies () { var enemyObjects = GameObject.FindGameObjectsWithTag("enemy"); enemies = new Transform[enemyObjects.Length]; for (i = 0; i < enemyObjects.Length; i++) { enemies[i] = enemyObjects[i].transform; } }
function FindClosest (targets : Transform[]) : Transform { var closestDistance = (enemies[0].position - myPosition).sqrMagnitude; var targetNumber = 0; for (i = 1; i < targets.Length; i++) { var thisDistance = (enemies[i].position - myPosition).sqrMagnitude; if (thisDistance < closestDistance) { closestDistance = thisDistance; targetNumber = i; } } return enemies[targetNumber]; }
This way you can call the GetEnemies function only when needed, and the FindClosest function when appropriate (which depends on your game). Since the function takes a Transform array as a parameter, it would be simple to have it check some enemy types but not others, as long as the different enemy types are in different Transform arrays.
in FindCloseset you pass targets : Transform[] but use enemies : Transform[], what is the deal with that?
@Pretender: what is the deal with what? I don't understand the question.
@Eric5h5 he meant that you declare a Transform[] parameter "targets", but it is not used inside the function. Ins$$anonymous$$d you use the existing "enemies" array which is not wrong, but in terms you want to call the function to check the distance from another Transform-array (let's say friendlySoldiers[]) it will still give the nearest enemy from enemies[], although you called FindClosest(friendlySoldiers)