- Home /
finding the closest player
I have an enemy and I want it to attack the closest player (with the tag "Player") within it's sight distance. I made it functional with without an array. But because the enemy will have multiple players. I want it to attack the closest player, if multiple players are within it's sight distance. So I've looked up FindGameObjectsWithTag and tried to combine both elements from the API and my own. But it's not functional as I want, so here's what I have:
GameObject[] players;
players = GameObject.FindGameObjectsWithTag("Player");
void FindClosestPlayer()
{
if(IsAlive())
{
GameObject closestPlayer;
float distance = Mathf.Infinity;
foreach(GameObject player in players)
{
//float distanceBetween = Vector3.Distance(transform.position, player.transform.position);
Vector3 difference = transform.position - player.transform.position;
float distanceBetween = difference.sqrMagnitude;
if(distanceBetween < distance)
{
closestPlayer = player;
distance = distanceBetween;
Debug.Log(distance);
//chase player if within range
if(distance < sightDistance && distance > attackRange)
{
transform.LookAt(closestPlayer.transform);
controller.SimpleMove(transform.forward * movementSpeed);
animation.CrossFade("Run");
}
else
{
animation.CrossFade("Idle");
}
Attack();
}
}
}
}
And in my debug statement, the distance is randomly generating numbers between the enemy and the player even though none of the two gameobjects are moving. The ranges I'm getting are anywhere from 6000+, 150+, 700+. Prior to doing this, my distance is calculating to be 15.
I suspect you need to run though all the players FIRST, to find the closest. THEN attack whichever is closest.
The way you have it, if the player is closer than the previously checked player, it will attack that one (or go IDLE!). Constantly changing it's target, until it gets through the list.
using this difference.sqr$$anonymous$$agnitude;
is fine (and fast) for comparing ditaances, but your debug statemtn is NOT showing the distance between the two objects, it's showing the Square of the distance, thats why they are so large.(eg, rather than 15, you see 15*15=225)
Not sure what you mean by this though: "But it's not functional as I want"
Ah ok I was wondering why the values were so large. So I've changed my debug to:
Debug.Log(Vector3.Distance(transform.position, closestPlayer.transform.position));
The issue I'm seeing in the debug is that despite the two gameobjects not moving the values that are being outputted are different each frame. And for now, I only have one object tagged "player". I know I need to added in a boolean so it only checks once.
This is what I meant in my first paragraph-(in psudo code)- note: attack is after the loopend.
closest=null
loop()
if(this one is closer than closest)
closest=this one
endloop
attack(closest)
regarding those position values always changing- if they are parented to another object that DOES move, that could explain this. Debug.Log($$anonymous$$athf.Sqrt(distancesqrd).ToString())
- should give you the actual distance.
Did you try to print out the position of corresponding gameObjects and see if you are getting the correct data?
It's not clear how often this is called, but if it's frequent you should create a cache $$anonymous$$yTransform variable (or whatever) so that, behind the scenes, it doesn't have to do resolve 'transform' each pass (see many posts on cache transform for more info).
Another alternative might be SphereCast or OverlapSphere executed in a coroutine so that it's not doing all this every pass
Your answer

Follow this Question
Related Questions
Find gameobject furthest from player along z axis 0 Answers
Calculate Distance Between two Game objects 1 Answer
HELP Find gameObject With tag in another array 1 Answer
Creating an array of prefabs? 4 Answers
Enabled all gameobjects in array 1 Answer