Finding new enemies

I modified the SentryGun.js from the fps tutorial and its working fine except it will only attack one enemy then stop when it is out of range or dead. I need it locate other enemies and fire at them and I dont understand why it isnt doing that.

var attackRange = 20.0;
var target : Transform;

function Update(){
	if ( target == null  GameObject.FindWithTag("Enemy")){
	target = GameObject.FindWithTag("Enemy").transform;
	}
	if (!CanSeeTarget()){
		return;
	}
	//rotate towards target
	var targetPoint = target.position;
	var targetRotation = Quaternion.LookRotation (targetPoint - transform.position, Vector3.up);
	transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.deltaTime * 20);
	
	//if we are almost rotated towards target - fire
	var forward = transform.TransformDirection(Vector3.forward);
	var targetDir = target.position - transform.position;
	if (Vector3.Angle(forward, targetDir) * Mathf.Rad2Deg < 15.0){
		BroadcastMessage("Fire");
	}
	target = null;
}
function CanSeeTarget() : boolean{
	if (Vector3.Distance(transform.position, target.position) > attackRange){
		return false;
	}
	var hit : RaycastHit;
	if (Physics.Linecast (transform.position, target.position, hit)){
		return hit.transform == target;
	}
	return false;
}

I know its probably simple,
any help is appreciated!
Thank you.

The thing is, you never reset your target. Once it has found one, it won’t ever change.
Additionally, you only check the first Enemy found by Unity for visibility. You would have to check every single one.

I was under the impression that GameObject.FindWithTag would update the target because of the if statement but im sure now that is incorrect. How should I reset the target?
Im sorry im being so annoying, any help is appreciated.

My mistake, I didn’t see that you reset target back to null at the end of Update.
Still you only check if you can attack the first Enemy Unity gives you. You need to check against all of them.

You can use GameObject.FindGameObjectsWithTag for this. You might also want to think about caching these GameObjects since finding them with that command is quite a performace hit (or so I’ve read).

See how you fare with these hints. If you need further clues, ask again. But please refrain from using phrases like “Im sorry im being so annoying,”.

I still cant get it to update the enemy any other clues?

You need to get an array of enemies and then iterate through it to check which one is closest and not dead.

from this code:

 if ( target == null  GameObject.FindWithTag("Enemy")){
   target = GameObject.FindWithTag("Enemy").transform;
   }
   if (!CanSeeTarget()){
      return;
   }

To something more like this:

if ( target == null || !CanSeeTarget())
{
	var targets : GameObject[] = GameObject.FindGameObjectsWithTag("Enemy");
	var myPos : Vector3 = transform.position;
	var closeDistance = 0.00;
	for(var target : GameObject in targets)
	{
		var t : Transform = target.transform;
		distance = (t.position - myPos).sqrMagnitude;
		if(closeDistance == 0 || distance < closeDistance)
		{
			target = t;
			if(!CanSeeTarget())
				target = null;
			else
				closeDistance = distance;
		}
	}
}

if (target == null)
	return;

If its slow, you can easily optimize it by avoiding the Find, and doing it not every frame but only every 0.5 seconds or so.

I get an error “cannot convert UnityEngine.Transform to UnityEngine.GameObject” on line 14 (target = t; ) How should i get the transform properties assigned to my target variable?

t is a Transform, target is a GameObject.

Change it to: target = t.gameObject;

-Jeremy

Thanks jeremy that got one bug.
After fiddling with it a bunch I still cant get it to work, I get an error saying that the variable target is not getting assigned to anything.

var attackRange = 20.0;
var target : GameObject;
function Update(){
	
	if (target == null || !CanSeeTarget()){
		var targets : GameObject[] = GameObject.FindGameObjectsWithTag("Enemy");
		var myPos : Vector3 = transform.position;
		var closeDistance = 0.0;
		for ( var enemy : GameObject in targets){
			var t : Transform = target.transform;
			distance = (t.position - myPos).sqrMagnitude;
			if (closeDistance == 0 || distance < closeDistance){
				target = enemy;
				if(!CanSeeTarget()){
					target = null;
				}else{
					closeDistance = distance;
				}
			}
		}
	}
	//rotate towards target
	var targetPoint = target.transform.position;
	var targetRotation = Quaternion.LookRotation (targetPoint - transform.position, Vector3.up);
	transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.deltaTime * 20);
	
	//if we are almost rotated towards target - fire
	var forward = transform.TransformDirection(Vector3.forward);
	var targetDir = target.transform.position - transform.position;
	if (Vector3.Angle(forward, targetDir) * Mathf.Rad2Deg < 15.0){
		BroadcastMessage("Fire");
	}
	target = null;
}
function CanSeeTarget() : boolean{
	if (Vector3.Distance(transform.position, target.transform.position) > attackRange){
		return false;
	}
	var hit : RaycastHit;
	if (Physics.Linecast (transform.position, target.transform.position, hit)){
		return hit.transform == target;
	}
	return false;
}

Any clues?
Luke

Along with that, what would be the best way to avoid the ‘find’?
Also i would like to check for enemies at a variable rate. Would i use time.deltaTime for this?
Thanks

I think this code is causing you trouble:

if(!CanSeeTarget()){
     target = null; // <-- Problem here

I just took a quick look at your code, and it appears that your sentry gun cannot see any enemies, hence cannot target them. :wink: Try commenting out that line and see what happens.