- Home /
Checking for closest gameobject with tag.
Well, I can't figure this out. It may be the easiest thing ever but I'm stuck. I don't know how to Check for the closest gameobject with the tag "Enemy".
Like: if player distance - bot1 distance <= 50
What should I do?
Do you constantly instantiate these objects with the tag "Enemy"? And what kind of game are you trying to create exactly? Do explain more please.
I do only instantiate an enemy when another enemy is dead. I'm trying to make something like an agar.io gane but with bots in$$anonymous$$d of humans playing. I want to see if the distance is less then something, if so it will start chasing it if it's Bigger than the other bot.
I did take a look at the link you provided, and I have another question. Do you want to make one enemy follow the player at a time? or could it be more than one enemy chasing the player at the same time?
Don't use tags. Seriously. Tags leads to ugly solutions where you constantly have to search for objects. There are plenty of better solutions.
Like this one, where Enemy objects maintain list of it's active instances autoamtically (cpu cost is marginal and spread in time here). This gives you always up-to-date list of enemies, without costly and error-prone search operations. Just attach this component to your enemy prefab.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy : $$anonymous$$onoBehaviour
{
public static List<Enemy> instances = new List<Enemy>( 100 );
void OnEnable ()
{
//register instance:
instances.Add( this );
}
void OnDisable ()
{
//unregister instance:
instances.Remove( this );
}
}
Answer by tmalhassan · Oct 25, 2017 at 07:09 PM
Hello @CloudiaNBusiness. If you're planning on having many enemies then it's better to make the enemy object calculate it's distance from the main player, rather than calculating distances from all enemies and moving the closest for the following reasons: 1) it will be better for game performance. 2) you will be able to make multiple enemies follow the player at the same time. I've taken the liberty of writing a simple script that will help achieve your goal. All you have to do is to attach it to the enemies. This is the script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DragDropScript : MonoBehaviour
{
private GameObject playerObject;
private float distance;
private float minimumDistance = 2f;
void Start()
{
playerObject = GameObject.FindWithTag("Player");
}
void Update()
{
distance = Vector3.Distance(playerObject.transform.position, transform.position);
if (distance <= minimumDistance)
{
transform.position = Vector3.MoveTowards(transform.position, playerObject.transform.position, 3f * Time.deltaTime);
}
}
}
Of course, in order for the script to work, you will need to add a "Player" tag to the object you want to be chased. Picture:
I also uploaded the project on the following link, so you'd be able to test it yourself. Link: http://www.mediafire.com/file/28lihaos0p06ug4/Follow_Player_2D.rar
You can test my project by dragging the Ball object (my main player).
You can also add a RotateTowards()
function to make the enemies look at the player. And just as well, you can simply make them move around until they come close to the player and they will start following him.
If you're going to instantiate more enemies after they die, make the enemy as a prefab (make sure that the script is attached to the prefab)
Hope this helps. And don't hesitate to reply if you have any further enquiries :)
First, thanks alot for you great response :). But I've got a question: I want to find ALL the gameobjects that has the same tag. I want the enemies to fight against eachother. Is there somekind of "gameobject.other" or something?
Well, your question doesn't mention anything about enemies attacking each others. But nevertheless, if that is what you're looking for, then finding gameObjects whether by name or tag is just ugly (just as @andrew-lukasik mentioned before), and It will affect your performance. Alternatively thought, you can create a list and add all the enemies to that list. after that you can check for the closest distance with the same code above. And since you have enemies dying and you instantiate new ones constantly, just remove that enemy from the list and add the new one.
Answer by andrew-lukasik · Oct 25, 2017 at 08:02 PM
Tags are the worst. Hitler, Stalin and Tags.
There is a better way:
Enemy closestEnemy = Enemy.FindNearest( transform.position );
Just attach this component to prefab of every enemy and it will just work:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Profiling;
public class Enemy : MonoBehaviour
{
#region FIELDS_&_PROPERTIES
static List<Enemy> _instances = new List<Enemy>( 100 );
public static List<Enemy> instances { get { return _instances; } }
/// <summary> Same as transform, but little less costly to access </summary>
Transform _transform;
/// <summary> return _transform.position </summary>
public Vector3 position { get { return _transform.position; } }
#endregion
#region MONOBEHAVIOUR_METHODS
void Awake ()
{
//cache reference to Transform component:
_transform = transform;
}
void OnEnable ()
{
//register instance:
_instances.Add( this );
}
void OnDisable ()
{
//unregister instance:
_instances.Remove( this );
}
#endregion
#region PUBLIC_METHODS
public static Enemy FindNearest ( Vector3 point )
{
Enemy nearest = null;
#if ENABLE_PROFILER
Profiler.BeginSample( "FindNearest()" );
#endif
{
Vector3 nearestPosition = Vector3.zero;
float nearestDistance = float.PositiveInfinity;
{
int instancesCount = _instances.Count;
int i = 0;
if( instancesCount>0 )
{
nearest = _instances[ 0 ];
nearestPosition = nearest._transform.position;
nearestDistance = Vector3.Distance( point , nearestPosition );
i = 1;
}
for( ; i<instancesCount ; i++ )
{
Enemy next = _instances[ i ];
Vector3 nextPosition = next._transform.position;
float dist = Vector3.Distance( point , nextPosition );
if( dist<nearestDistance )
{
nearest = next;
nearestPosition = next._transform.position;
nearestDistance = dist;
}
}
}
}
#if ENABLE_PROFILER
Profiler.EndSample();
#endif
return nearest;
}
#endregion
}
Answer by Devastadus · Oct 25, 2017 at 06:28 PM
private GameObject findClosestEnemy() {
GameObject[] objs= GameObject.FindGameObjectsWithTag("Enemy");
GameObject closestEnemy = null;
float closestDistance;
bool first = true;
foreach (var obj in objs)
{
float distance = Vector3.Distance(obj.transform.position, transform.position);
if (first)
{
closestDistance = distance;
first = false;
}
else if (distance < closestDistance)
{
closestEnemy = obj;
closestDistance = distance;
}
}
return closestEnemy;
}
It is. But not when you call it once. It would be a problem if you call it in Update()
.
Yes. I consider this bad only because every newbie programmer will put it in some kind of Update sooner or later. Just wait.
Answer by ArthyShow · Oct 25, 2017 at 06:35 PM
If you have a lots of enemies you can adapt the example on Unity Coroutine Doc (this is to get all enemies in dangerDistance
, but it's easy to update
function ProximityCheck() {
for (int i = 0; i < enemies.Length; i++) {
if (Vector3.Distance(transform.position, enemies[i].transform.position) < dangerDistance) {
return true;
}
}
return false;
}
IEnumerator DoCheck() {
for(;;) {
ProximityCheck;
yield return new WaitForSeconds(.1f);
}
}
Creating new WaitForSeconds object 10/s is a memory leak. Create it once.
Answer by shadowpuppet · Oct 25, 2017 at 07:48 PM
This may or may not be helpful and probably not the best solution but it is what I use. I have a robot ally in my FPS game and he calculates the closest enemy and attacks him. However I don't go by tag I go by the actual enemy name. It gets pretty hairy because I need to list all the enemies as well rename them ( sort of). But basically I find all the enemies that are active in hierarchy, calculate their distance ( to the robot not the player,but same principle) and which ever one is closest he becomes the Target. It works, that is all I can say, though looking at it now I don't even understand it anymore
using UnityEngine;
using System.Collections;
public class enemyManager : MonoBehaviour {
public GameObject TARGET;
private NavMeshAgent agent;
public int MaxDist = 45;
public float MinDist;
Animator anim;
public static bool noEnemies;
public Light lite;
public float ro = 100f;
public float rot = 100f;
public float gat = 100f ;
public float shoot = 100f;
public float na = 100f;
public float ne = 100f;
public static Transform badGuy;
public static GameObject badGuyAgain;
public float closestEnemy;
public GameObject BadRobot;
public GameObject BadRobot2;
public GameObject GatlinGun;
public GameObject Shutze;
public GameObject Nazi;
public GameObject NeoNazi;
public GameObject PlayerAgain;
public GameObject rocketSource;
public GameObject player;
public Transform badrobo;
public Transform badrobo2;
public Transform gatgun;
public Transform shoots;
public Transform naz;
public Transform neonaz;
public Transform Player;
private MonoBehaviour friends;
private MonoBehaviour attack1;
private MonoBehaviour bullet;
private MonoBehaviour currentHealth;
private float damping = 6f;
private float TurnDist;
//public GameObject weapon;
private int dist = 21;
private float draw = 1f;
public float off = .1f;
Ray thugRay;
RaycastHit rayHit;
//public float currentDist;
public bool enemy;
void Start () {
badrobo = BadRobot.transform;
badrobo2 = BadRobot2.transform;
gatgun = GatlinGun.transform;
shoots = Shutze.transform;
naz = Nazi.transform;
neonaz = NeoNazi.transform;
bullet = rocketSource.GetComponent<myRobotBullet>();
agent.enabled = true;
}
void Awake(){
anim = GetComponent<Animator>();
agent = GetComponent<NavMeshAgent>();
currentHealth = GetComponent<myRobotHealth>();
friends = GetComponent<myRobotAlly>();
attack1 = GetComponent<myRobotAttack>();
}
void FixedUpdate () {
closestEnemy = (Mathf.Min(ro, rot, gat, shoot, na));
TARGET = badGuyAgain;
if(badGuyAgain != null)
{
if(badGuyAgain .activeInHierarchy == false)
{
friends.enabled = true;
bullet.enabled = false;
}
}
if(badGuyAgain == NeoNazi ||badGuyAgain == BadRobot || badGuyAgain == BadRobot2 || badGuyAgain ==Shutze || badGuyAgain == GatlinGun || badGuyAgain == Nazi)
{
enemy = true;
ATTACK ();
}
}
void LateUpdate()//___________________________________________________________________________________
{
if(BadRobot.activeInHierarchy == true)
{
ro = Vector3.Distance(transform.position,badrobo.position);
}
else if(BadRobot.activeInHierarchy == false)
{
ro = 100f;
}
if(NeoNazi.activeInHierarchy == true)
{
ne = Vector3.Distance(transform.position,badrobo.position);
}
else if(NeoNazi.activeInHierarchy == false)
{
ne = 100f;
}
if(BadRobot2.activeInHierarchy == true)
{
rot = Vector3.Distance(transform.position,badrobo2.position);
}
else if(BadRobot2.activeInHierarchy == false)
{
rot = 100f;
}
if (GatlinGun.activeInHierarchy == true)
{
gat = Vector3.Distance(transform.position,gatgun.position);
}
else if (GatlinGun.activeInHierarchy == false)
{
gat = 100f;
}
if (Shutze.activeInHierarchy == true)
{
shoot = Vector3.Distance(transform.position,shoots.position);
}
else if (Shutze.activeInHierarchy == false)
{
shoot = 100f;
}
if (Nazi.activeInHierarchy == true)
{
na = Vector3.Distance(transform.position,naz.position);
}
else if (Nazi.activeInHierarchy == false)
{
na = 100f;
}
if(BadRobot.activeInHierarchy == true)
{
if(Vector3.Distance(transform.position,badrobo.position) <= MaxDist)
{
if(Vector3.Distance(transform.position,badrobo.position) <= closestEnemy)
{
badGuy = badrobo;
badGuyAgain = BadRobot;
ATTACK ();
friends.enabled = false;
off = .1f;
}
}
}
else if (GatlinGun.activeInHierarchy == true)
{
if(Vector3.Distance(transform.position,gatgun.position) <= MaxDist)
{
if(Vector3.Distance(transform.position,gatgun.position) <= closestEnemy)
{
badGuy = gatgun;
badGuyAgain = GatlinGun;
ATTACK ();
friends.enabled = false;
off = .1f;
}
}
}
else if (NeoNazi.activeInHierarchy == true)
{
if(Vector3.Distance(transform.position,neonaz.position) <= MaxDist)
{
if(Vector3.Distance(transform.position,neonaz.position) <= closestEnemy)
{
badGuy = neonaz;
badGuyAgain = NeoNazi;
ATTACK ();
friends.enabled = false;
// Destroy (friends);
off = .1f;
}
}
}
else if(Nazi.activeInHierarchy == true)
{
if(Vector3.Distance(transform.position,naz.position) <= MaxDist)
{
if(Vector3.Distance(transform.position,naz.position) <= closestEnemy)
{
badGuy = naz;
badGuyAgain = Nazi;
ATTACK ();
friends.enabled = false;
off = .0f;
}
}
}
else if (BadRobot2.activeInHierarchy == true)
{
if(Vector3.Distance(transform.position,badrobo2.position) <= MaxDist)
{
if(Vector3.Distance(transform.position,badrobo2.position) <= closestEnemy)
{
badGuy = badrobo2;
badGuyAgain = BadRobot2;
ATTACK ();
friends.enabled = false;
off = .1f;
}
}
}
else if (Shutze.activeInHierarchy == true)
{
if(Vector3.Distance(transform.position,shoots.position) <= MaxDist)
{
if(Vector3.Distance(transform.position,shoots.position) <= closestEnemy)
{
badGuy = shoots;
badGuyAgain = Shutze;
friends.enabled = false;
off = .0f;
ATTACK ();
}
}
}
else
{
//badGuy = Player;
//Debug.Log ("else");
//friends.enabled = true;
//Debug.Log ("else");
}
}
void ATTACK(){
enemy = true;
MinDist = 14;
var rotation = Quaternion.LookRotation(badGuy.position - transform.position);
transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * damping);
if(badGuyAgain .activeInHierarchy == false)
{
agent.acceleration = 1.5f;
badGuy = null;
badGuyAgain = null;
TARGET = null;
enemy = false;
}
if (badGuy != null)
{
if(badGuyAgain .activeInHierarchy == true)
{
if(Vector3.Distance(transform.position,badGuy .position) <= MaxDist)
{
if(agent.enabled == true)
agent.SetDestination(badGuy .transform.position);
agent.enabled = true;
anim.SetTrigger ("walk");
anim.ResetTrigger ("attack");
anim.ResetTrigger ("idle");
anim.ResetTrigger ("idle2");
agent.acceleration = 1.5f;
lite.color = Color.yellow;
anim.speed = 2.5f;
agent.speed = 2f;
}
else if(Vector3.Distance(transform.position,badGuy.position) > MaxDist)
{
//friends.enabled = true;
}
if (Vector3.Distance (transform.position,badGuy .position) <= MinDist)
{
MaxDist = 45;
//MinDist = 21;
thugRay = new Ray(transform.position + transform.up * draw- transform.right * off, transform.forward*dist);
Debug.DrawRay (transform.position+ transform.up * draw - transform.right * off, transform.forward*dist, Color.blue);
if (Physics.Raycast(transform.position+ transform.up * draw - transform.right * off, transform.forward, out rayHit)){
{
if(rayHit.transform.gameObject.tag == ("wall"))
{
HITWALL();
}
else if (rayHit.transform.gameObject.tag == ("METAL"))
{
lite.color = Color.green;
agent.enabled = false;
anim.ResetTrigger ("walk");
anim.ResetTrigger ("idle");
anim.ResetTrigger ("idle2");
anim.SetTrigger ("aim");
anim.speed = 2.5f;
bullet.enabled = true;
friends.enabled = false;
}
else if (rayHit.transform.gameObject.tag == ("enemy"))
{
lite.color = Color.green;
agent.enabled = false;
anim.ResetTrigger ("walk");
anim.ResetTrigger ("idle");
anim.ResetTrigger ("idle2");
anim.SetTrigger ("aim");
anim.speed = 2.5f;
bullet.enabled = true;
}
}
}
}
}
}
}
void HITWALL(){
bullet.enabled = false;
MinDist = 3f;
anim.SetTrigger ("walk");
anim.ResetTrigger ("aim");
anim.ResetTrigger ("idle");
anim.ResetTrigger ("idle2");
agent.enabled = true;
lite.color = Color.cyan;
agent.SetDestination(badGuyAgain .transform.position);
thugRay = new Ray(transform.position + transform.up * draw- transform.right * off, transform.forward*dist);
Debug.DrawRay (transform.position+ transform.up * draw- transform.right * off, transform.forward*dist, Color.yellow);
if (Physics.Raycast(transform.position+ transform.up * draw- transform.right * off, transform.forward, out rayHit,dist)){
{
if(rayHit.transform.gameObject.tag == ("METAL"))
{
ATTACK ();
}
if(rayHit.transform.gameObject.tag == ("enemy"))
{
ATTACK ();
}
}
}
}
}
and if no enemies are around and/or the robot doesn't have any targets, his attack script becomes inactive and his ally script becomes active where he follows me around until a new enemy appears and is within range
Your answer
Follow this Question
Related Questions
How to calculate Distances 2 Answers
Disabling GameObjects With A Tag That Are More Than A Set Distance From A GameObject? 2 Answers
How can I find the Distance between Two Objects on the X Axis? 3 Answers
Calculate Distance Between two Game objects 1 Answer
How to stop an object of going to far 2 Answers