- Home /
The question is answered, right answer was accepted
Finding nearest and with highest health points
I have succeeded in writing a code to find the nearest enemy and it worked but I would like to include another parameter. Here is the code I am using:
GameObject[] enemies;
enemies = GameObject.FindGameObjectsWithTag("Enemy");
GameObject closest = null;
float distance = Mathf.Infinity;
Vector3 position = transform.position;
foreach (GameObject enemy in enemies)
{
Vector3 diff = enemy.transform.position - position;
Target target = enemy.GetComponent<Target>();
float curDistance = diff.sqrMagnitude;
if (curDistance < distance && target.health > 25f)
{
print("worked");
closest = enemy;
distance = curDistance;
}
else if (curDistance < distance)
{
closest = enemy;
distance = curDistance;
}
}
return closest;
Now as you can see, the other condition is basically check the target's health. If both conditions are met which are 1) nearest enemy + 2) health > 25 then choose that one. If not, then just choose the nearest. However, what is happening is that the returned game object is just the nearest even though the print function shows up and the conditions are met. please help.
EDIT: print function does not go through. always "else if" works only.
EDIT2: I have modified my code to this:
foreach (GameObject enemy in enemies)
{
Vector3 diff = enemy.transform.position - position;
Target target = enemy.GetComponent<Target>();
float curDistance = diff.sqrMagnitude;
if (curDistance < distance && target.health >= 25f)
{
print("Yep!");
closest = enemy;
distance = curDistance;
}
}
return closest;
Now, I get the nearest enemy with health greater than 25 followed by the further. Yet when those are destroyed other objects with health lower than 25 are not identified anymore which is not what I want! I want those enemies with health lower than 25 be targeted after those with health more than 25 killed. I tried using "else if" and "else" but the order of identifying get messed up. please help
Answer by Bunny83 · Feb 09, 2020 at 12:04 AM
Your requirement doesn't make much sense. Whenever you have more than one sort criteria you have to deside which one is the first order criteria and which one is secondary.
So if we assume you just want a single splitting value at 25HP so that if there are one or more objects with more than 25HP we would pick the closest object out of those objects. If there is no object with more than 25HP we would simply pick the closest out of all objects regardless of the HP. To do this we would need two seperate "distance" and "closest" variables to track the two different conditions independently. For example in the for loop you would do
if (curDistance < distance)
{
closest = enemy;
distance = curDistance;
}
if (curDistance < hiDistance && target.health > 25f)
{
hiClosest = enemy;
hiDistance = curDistance;
}
After your for loop you can simply check if lowClosest contains any object. Because when all objects are above 25 hp you will never enter the second if statement and lowClosest would stay null. So if lowClosest is null, just use "closest". If it's not null, use "lowClosest".
if (hiClosest != null)
return hiClosest;
return closest;
If you actually want to somehow use a weighted condition so both values (distance and hp) are considered at the same time, you have to define some kind of weighting system for both value types. Imagine this scenario
//You are here| | Enemy at 8 hp
// | |
// \|/ |
// * \|/
// *
// *
// /|\
// |
// | Enemy at 12 hp
As you can see the enemy at 8 hp is closer to you than the enemy at 12hp. Which one do you want to pick? Based on which logic? Since 12 hp is higher than 8 hp, do you want to prefer this one? What if the 12 hp enemy is far to the right instead? Still want to prefer the enemy that is 100 units away over the one that's just 1 unit away? If you want some sort of critical switching point you have to decide how much "weight" each condition gets.
One approach is to unify both values into a single unitless "score". So enemies which are closer gets a higher score than enemies further away. Likewise enemies with a higher health would also get a higher score than those with a low HP value. Though the crucial point is what is the balance between those. So for example if you essentially decide that one unit of distance equals one point of HP you could simply subtract the distance value from the HP value. The highest result is the preferred result
To refer back to my example: If we assume the 8 HP enemy is 5 units away and the 12 HP unit is 7 units away, the 8 HP enemy would get a value of 8-5 == 3 while the 12 HP enemy gets a value of 12-7 == 5. So we would pick the 12 HP enemy. However if the 8 HP enemy moves further away, say to a distance of 11 units its value would decrease to 12 - 11 == 1 so the 8 HP enemy would be the new preferred one. So health and distance would essentially cancel each other out. "8HP at 5units" has the same priority as "12HP at 9units".
Hopefully you get the idea. If you want a different ratio between health and distance you would simply multiply one of them with a weight factor. For example if you choose your value to be "hp - 2*dist" it means 1 unit of distance has the same weight as 2 points of HP.
Keep in mind that while for pure distance sorting it doesn't matter if you use the actual distance or the distance squared. In the weighted case it does make a difference.
my bad. I just updated the topic title. I want to target the nearest with highest hp then if those are dead, I want the order from the nearest to furthest only. Ill check your logic and will give feedback. By the way, your version of the code would only focus the nearest ignoring the health condition since it is in the "if" statement and all objects would be identified which result in ignoring the "else if". Correct me please if im wrong. thanks
Yes, my bad, there should not be any else statement ^^. I will edit my answer. Since you now flipped the condition around I will also adjust my examples to fit your question.
However again you said you want the nearest with highest hp. This just doesn't make sense. Based on your statement that you want "the nearest with highest hp" it would actually be the object with the highest HP, no matter at which distance it is located. So in effect you only sort by HP. When exactly do you want to take the distance into account? Imagine there are these objects:
5HP at 2 units distance
10HP at 5 units distance
20HP at 7 units distance
100HP at 100 units distance
Just tell me how would you order those objects based on your requirements? Which is the one you want to pick first? If that would be gone, what would be the second, third, ... ? Here again the closest object with the highest HP is the one at 100 unit distance. The second closest with the highest HP would be the one at 7 units distance. If you just look at that result you essentially only sorted on the HP value and ignored the distance completely. The only case where it would make sense to use the distance as a second ordering condition is when you have two or more objects with the exact same health value. So if there are 3 objects all with a health value of 100 you could pick the closest one of those 3. But if there's an object with 101 HP that would be preferred over all the 100 HP objects. Is that what you're looking for?
O$$anonymous$$, I tried your logic. It worked in the case of targeting nearest highest hp enemies. But, after that other nearest low hp enemies are not targeted. Also, how to return either closest and lowClosest in your version of code? because I need to return something which in your code it is either closest or lowClosest. thanks
I actually said in my answer what to return when. I have completely reworked all my examples. I also explicitly added the return code logic just as mentioned in the answer.
Follow this Question
Related Questions
How to prevent a script on a disabled object from firing? 0 Answers
How to access a game object from a different scene? 0 Answers
Calculating Scrolling GameObject x position scrolling pass another GameObject x postion (2D Game) 1 Answer
How do I play gameobjects in my scene from one script / Script is not working 0 Answers
How to double spirte/gameobject/prefab and control the result on those items? 0 Answers