Turret Only Looks At Initiated Enemy - Not Current - HELP

I know I've asked many questions but this is really frustrating me. I would appreciate any support or help.

Please watch my video to get a better understanding (leave a comment if the video does not load) - There Is Sound (me talking)

http://www.olliejones.com/TurretSpawn.mov

YouTube Video: http://www.youtube.com/watch?v=fQLetF46tTI

I have an enemy(prefab) which initiates every so often. And I would like my turret to 'LookAt' when it is in range. At first, I was having a problem with the 'target' of my 'LookAt' because I needed to cache the reference to the newly created (clone) of the prefab, then assign the target to it, by doing this:

//---Script Called 'Spawn'---This is placed within the EnemyPrefab\\

static var newEnemy : Transform;

function Start()
{
newEnemy = (Instantiate( Enemy, transform.position, Quaternion.identity )).transform;
}

//---Snippet Script Called 'SmoothLookAt'--- This is on my turret\\

function Update()
{    
transform.LookAt(Spawn.newEnemy);
}

Now, what I would like to achieve with the help of you, is for the turret to only LookAt one EnemyPrefab until it dies, then LookAt another EnemyPrefab until that one dies too ... (right now, enemies only die when they get to the end of there waypoint system -- Destroy)

But when the turret has its target assigned, it is reset every time a new enemy is initiated and then begins to track that one (It tracks every new initiated enemy).

What I would like: Have turret LookAt an enemy that comes into range until it either dies, or goes out of range, if either are true, then LookAt next enemy that is in range.

Please Help :)

YouTube Video: http://www.youtube.com/watch?v=fQLetF46tTI

-----Scripts-----

---Spawn---

var Enemy : GameObject;
static var timeDelay : float = 0.5;
static var RandomSpawnTime : boolean = false;
static var newEnemy : Transform;
static var currentEnemy : Transform;

static var EnemyHasUniqueID = false;
private var prefebIndex = 0;

//private var prefebIndex : int = 0;

function Start() 
{
    if(EnemyHasUniqueID == true)
    {
        prefebIndex = 0;
        Enemy.transform.name = "Enemy" + prefebIndex;
        prefebIndex++;
    }

    while (true) 
    {
        if(Controller.EnemyRemaining > 0)
        {
            if(RandomSpawnTime == true)
            {
                yield WaitForSeconds(Random.Range(1,4));
            }

            else if(RandomSpawnTime == false)
            {
                yield WaitForSeconds(timeDelay);
            }
            newEnemy = (Instantiate( Enemy, transform.position, Quaternion.identity )).transform;
            Controller.EnemyRemaining --;

            // Unique ID function
            if(EnemyHasUniqueID == true)
            {
                Enemy.transform.name = "Enemy" + prefebIndex;
                prefebIndex++;
            }
        }
        else if(Controller.EnemyRemaining <= 0)
        {

            return;
        }
    }
}

//newEnemy = (Instantiate(Enemy, transform.position, transform.rotation)).transform;
//transform.LookAt(newEnemy);
//origin = newEnemy = Instantiate( Enemy, transform.position, Quaternion.identity );

---OneWaypoint---

var waypoint : Transform[];
static var speed : float = 5;
private var currentWaypoint : int;
/*
var prefebIndex = 0; 

function Start ()
{
    //transform.name = ("EnemySpawned");
    //var Enemy:GameObject  = Instantiate(myPrefab);
    transform.name = "EnemySpawned" + prefebIndex;
    prefebIndex++;

}
*/
function Update () 
{
    if(currentWaypoint < waypoint.length)
    {
        var target : Vector3 = waypoint[currentWaypoint].position;
        var moveDirection : Vector3 = target - transform.position;
        var velocity = rigidbody.velocity;

        if(moveDirection.magnitude < 1)
        {
            currentWaypoint++;
        }
        else
        {
            velocity = moveDirection.normalized*speed;
        }
    }

    rigidbody.velocity = velocity;
}

---SmoothLookAt---

var target : Transform;
static var damping = 6.0;
static var smooth = true;
//static var attackRange = 8;

static var ActivateScorpionRange = false;
static var ScorpionRange : float = 8;

static var Scorpion : boolean = true;

@script AddComponentMenu("Camera-Control/Smooth Look At")

function Update () 
{

    if(ActivateScorpionRange == true)
    {
        if (Spawn.newEnemy == null)
        return;

        if(!CanSeeTarget())
        return;
    }

    if(Scorpion == true)
    {
        if (smooth)
        {
            // Look at and dampen the rotation
            var rotation = Quaternion.LookRotation(Spawn.newEnemy.position - transform.position);
            transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * damping);
        }
        else
        {
            transform.LookAt(Spawn.newEnemy);
        }
    }       
}

function CanSeeTarget() : boolean
{
    if(Vector3.Distance(transform.position, Spawn.newEnemy.position) > ScorpionRange)
        return false;

    var hit : RaycastHit;
    if(Physics.Linecast (transform.position, Spawn.newEnemy.position, hit))
        return hit.transform == Spawn.newEnemy;

    return false;
}

/*
function Start () {
    // Make the rigid body not change rotation
    if (rigidbody)
        rigidbody.freezeRotation = true;
}

    if (target) 
    {

        if (smooth)
        {
            // Look at and dampen the rotation
            var rotation = Quaternion.LookRotation(Spawn.newEnemy.position - transform.position);
            transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * damping);
        }
        else
        {
            // Just lookat
            //transform.LookAt(target);
            transform.LookAt(Spawn.newEnemy);
        }
    }*/

Not enough code for me to know for sure, but it looks like your Update function is specifically selecting the last spawned enemy (because newEnemy becomes the last enemy created each time you call the "Spawn" script).

What I would do is the following:

First- enemyList[maxNumEnemies] = GameObject.FindGameObjectsWithTag("Enemy") [you need to tag each new enemy with "Enemy" tag.]

Then- if enemyList.length == 0 then [either wait for new spawn or spawn new enemy... your choice]

Next- Test each enemy in enemyList[] for its distance (try Pythagorean Theorem: SqrRoot[(x1-x2)^2 + (y1-y2)^2 + (z1-z2)^2]...). The closest one under the minimum distance gets put in your target variable. If none qualify, wait.

From then on- only check the distance or existence of the target. When it is destroyed or out of range, go back to Step One.

That way, you'll only change targets to the new one after the old one is out of range, and then you'll pick the closest enemy to the turret.

Hope that helps...

Your code only has 2 problems that I can obviously, but unfortunately they are major problems. Let me explain.

  1. newEnemy (referred to as target henceforth) should not be a `static variable`. You won't notice with 1 turret, but with more than one they would all look at the same target no matter what. You want them looking at the closest.

  2. You are setting the target to be the enemy that just spawned. So your turret will stop shooting at the closest target and wait for that enemy to get in range, unless another spawns before that in which case it will never shoot at anything.

The simplest way would be to create a trigger around you turret and set the target to whatever enemy is in your trigger. A generic list sounds very useful here, so I am going to use that.

private var target : Transform;
private var closeObjects = new System.Collections.Generic.List.<Transform>();

//When an enemy enters the trigger, add them to the list.    
function OnTriggerEnter (enemy : Collider) {
     closeObjects.Add(enemy.transform);
}

//When they leave, take them off of the list.
function OnTriggerExit (enemy : Collider) {
    closeObjects.Remove(enemy.transform);
}

function Update () {
    //Make sure there is an enemy.
    if(closeObjects.Count == 0)
        return;

    //Look at the the first enemy in our list. 
    // That will be the one that has been in the trigger the longest.
    target = closeObjects[0];
    transform.LookAt(target);
}

Lists are new to js in Unity 3 (they've been in C# for several versions now) and they work like standard js arrays, but they are type safe which gives better performance and in this case work better than .Net arrays because they are easier to resize.

I hope that this finally solves your problem.

I would make a gameobject array where you keep trace off all the enemy's that are in the scene and then use this array to check if they are in range of your turret. Then ask the posistion from the first enemy in the list thats comes in range of your turret. You need to make sure that the list of enemy's in sequence in witch they span and make sure you remove them form the list when they are destroyed.