Homing Missile targetting the nearest Enemy
Hello,
I made a script, with a Homing Missile in Unity2D. Game is a Sidescrolling Platformer Contrastyle.
The missile, which is fired from a gun muzzle is doing it´s job. However.. It doesn´t recognize, which enemy is currently the nearest Target. I tried to google that. I also found an answer in the forums, but it is using Linq. Since I have absolutely no clue about Linq, is there another solution I could use?
Currently I am using "FindGameObjectWithTag to find the target for the missile. I also know, that I somehow have to make it work that, so that the missile recognizes a certain distance to the nearest enemy, but I don´t get, how to properly set it up.
Do I have to use an Array for that?
Another solution could be, to make the missile just allow to search for a target, if it is visible on the screen? However, my recent trys with this were a desaster.
Help or a hint would be much appreciated, since at the moment if I am direclty in front of the enemy the missile is flying on to the next target like 2 screens away.
Thanks a lot.
Here´s the script.
public GameObject target;
Rigidbody2D rb;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void FixedUpdate () {
rb = GetComponent<Rigidbody2D>();
if(target = GameObject.FindGameObjectWithTag ("Enemy"))
{
Vector2 pointToTarget = (Vector2)transform.position-(Vector2)target.transform.position;
pointToTarget.Normalize ();
float value = Vector3.Cross(pointToTarget, transform.right).z;
if(value >0)
{
rb.angularVelocity = rotatingSpeed;
}
else if (value < 0)
rb.angularVelocity = -rotatingSpeed;
else
rb.angularVelocity = 0;
}
}
Answer by OutOfRam · Oct 18, 2016 at 11:16 PM
There is no builtin method for finding the closest enemy, but there is a pretty simple way to code it. add this function to your script and it will return the nearest GameObject with the tag.
GameObject FindClosestByTag(string tag)
{
GameObject[] gos;
gos = GameObject.FindGameObjectsWithTag(tag);
GameObject closest = null;
float distance = Mathf.Infinity;
Vector3 position = transform.position;
foreach (GameObject go in gos)
{
Vector3 diff = go.transform.position - position;
float curDistance = diff.sqrMagnitude;
if (curDistance < distance)
{
closest = go;
distance = curDistance;
}
}
return closest;
}
Essentially the function grabs all objects with the tag 'tag' and individually compares the distance between them returning the closest one.
I hope this helps!
Thanks for your answer and help!
I feel like I´m on the right way. I get an error though. It made the most sense to me, to put the function into void Start.
As soon as I hit the $$anonymous$$ey to Instantiate the "missile" I get an error stating:
The variable target (or whatever I´d call it) has not been assigned.
Tried a lot at the moment. How do I assign the variable correctly? and sorry, if this is something really noobish. I just don´t get, why the target is not found.
This is, how it is currently looking. I had to change tag to Enemy after string didn´t I?
public GameObject gos; //target before
Rigidbody2D rb;
// Use this for initialization
void Start () {
}
GameObject FindClosestByTag(string Enemy) // changed from former tag to Enemy
{
GameObject[] gos;
gos = GameObject.FindGameObjectsWithTag("Enemy");
GameObject closest = null;
float distance = $$anonymous$$athf.Infinity;
Vector3 position = transform.position;
foreach(GameObject go in gos)
{
Vector3 diff = go.transform.position - position;
float curDistance = diff.sqr$$anonymous$$agnitude;
if(curDistance < distance)
{
closest = go;
distance = curDistance;
}
}
return closest;
}
// Update is called once per frame
void FixedUpdate () {
rb = GetComponent<Rigidbody2D>();
Vector2 pointToTarget = (Vector2)transform.position-(Vector2)gos.transform.position; //target before
pointToTarget.Normalize ();
float value = Vector3.Cross(pointToTarget, transform.right).z;
if(value >0)
{
rb.angularVelocity = rotatingSpeed;
}
else if (value < 0)
rb.angularVelocity = -rotatingSpeed;
else
rb.angularVelocity = 0;
}