- Home /
How can I get my missile script to target the nearest tagged enemy?
Hey,
I've made a script in which I basically get the missile to target the gameobject tagged enemy and move towards it and destroy it. However I found that if you have multiple enemies in the scene it will not work. This is the code:
using UnityEngine;
using System.Collections;
public class Turret : MonoBehaviour {
public Transform Enemy;
void Start ()
{
Enemy = GameObject.FindGameObjectWithTag("Enemy");
}
void Update ()
{
float dist = Vector3.Distance(Enemy.transform.position,transform.position);
if(dist <150)
{
transform.position = Vector3.MoveTowards(transform.position, Enemy.position, 60 * Time.deltaTime);
}
}
}
I understand that this will not work because there is more than one GameObject tagged "Enemy" But I don't understand how to get around this? How can i tweek this so it fires towards the nearest tagged enemy within 150 units.
Many thanks in advance
I take it enemies are prefabs that are instantiated at some point? inside this script I would create a public static enemy list, everytime an enemy is spawned push it onto the list, then in this missile script access the list and sort it into distance order (moving the closest to element zero), then move towards myEnemyList[0].transform.position
No the missiles are instantiated, the enemies are set up normally. These have their own waypoint pathing in the game, but since it's a space fighter, most of the enemies are in groups. IE mothership and 5 fighterjets.
fighterjets in space?I don't know the specific code - I'm pretty much a unity noob myself, but something like this?
(pseudocode)
Find all elements with tag 'enemy'
for all the enemies;
Get enemy position
Get a vector from the player position to the enemy position (position.enemy - position.player)
Get that vectors magnitude
keep a track of all the enemy magnitudes (say, in an array or some kind of list structure)
find the enemy that has the $$anonymous$$imum magnitude
target missile at that enemy
Hmm I have an idea on how to do this using lists, i thought there might me a 2 line of code easy fix for this. I'll work on this now and if I solve it I'll post and an answer for other people to use as learning resources. But what you said alienbaby is what I had originally thought to do, i was hoping there was an easier way ha
If the enemies are not instantiated then thats fine, you can just create a static list on startup and from there go on to sort it in distance order.
Answer by Ambro · Dec 04, 2013 at 08:43 PM
There is an article on unity gems that has an elegant solution for this problem, but it's using Linq :
The advantage is that it takes a very few lines to do it, just add at the top of your script :
//C#
using System.Collections.Generic; //Always a good idea
using System.Linq;
//JavaScript
import System.Linq;
And where you want to make your detection :
//C#
var closestGameObject = GameObject.FindGameObjectsWithTag("MyTag")
.OrderBy(go => Vector3.Distance(go.transform.position, transform.position)
.FirstOrDefault();
//Javascript
var closestGameObject = GameObject.FindGameObjectsWithTag("MyTag")
.OrderBy(function (go) Vector3.Distance(go.transform.position, transform.position))
.FirstOrDefault();
The only downside is that the code above doesn't take maximal distance of 150 units into account, but if you look at their article, there is some exemples that use this kind of distance limitation.
If you don't want to learn Linq, just add a distance check on the closestGameObject that it returns. Something like :
float dist = Vector3.Distance(closestGameObject.transform.position,transform.position);
if(dist <= 150)
// Do Something
Thanks, I've done a solution myself which i posted here, but I've never used ling before I'm going to research it now. Thanks for the tips.
For anyone who's still interested in this, a working link is here
Answer by Iceblitzyt · Dec 04, 2013 at 08:35 PM
Okay Guys I fixed this with my own script, I'm adding this to the post so people can use this as a learning resource.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Turret : MonoBehaviour {
public List <Transform> Enemies;
public Transform SelectedTarget;
void Start ()
{
SelectedTarget = null;
Enemies = new List<Transform>();
AddEnemiesToList();
}
public void AddEnemiesToList()
{
GameObject[] ItemsInList = GameObject.FindGameObjectsWithTag("Enemy");
foreach(GameObject _Enemy in ItemsInList)
{
AddTarget(_Enemy.transform);
}
}
public void AddTarget(Transform enemy)
{
Enemies.Add(enemy);
}
public void DistanceToTarget()
{
Enemies.Sort(delegate( Transform t1, Transform t2){
return Vector3.Distance(t1.transform.position,transform.position).CompareTo(Vector3.Distance(t2.transform.position,transform.position));
});
}
public void TargetedEnemy()
{
if(SelectedTarget == null)
{
DistanceToTarget();
SelectedTarget = Enemies[0];
}
}
void Update ()
{
TargetedEnemy();
float dist = Vector3.Distance(SelectedTarget.transform.position,transform.position);
//if(dist <150)
//{
transform.position = Vector3.MoveTowards(transform.position, SelectedTarget.position, 60 * Time.deltaTime);
//}
}
}
How can I add the target once it enters a collider that is on trigger?
Nice. this does exactly what I want except it's a little advanced for me. How would I get the the target out of the list after it's been collided with.
Hi, I know this is a little to late but I was wondering if you can help me fix this problem I ran into using your code. You see I get this error:
ArgumentOutOfRangeException: Argument is out of range.
Parameter name: index
when there isn't a target for the bullets to shoot at, is there a way of making the bullets wait until it detects if there's an enemy on sight? Thank you for your answer by the way, it was really helpful! :)
Answer by Shindy117 · Apr 16, 2017 at 10:23 PM
This script works for me however the only problem comes when the object is destroyed. Since it has nothing to destroy. It errors out.
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
My enemies merge when they come towards me 4 Answers
Is there an opposite of GameObject.FindGameObjectsWithTag() ? 2 Answers