Tower Defense Script not working properly

Can someone take a look at my script for targeting in my Tower Defense game? The script tends to start failing after a while and I can’t figure out why.

What I want it to do:

Get a list of enemies in the tower’s range from Physics.SphereOverlap, find the closest enemy and then lock onto that target. When the target leaves the towers attack range, find a new one. I’m using InvokeRepeating to fire a bullet at a regular frequency but that same call also sets the interval to search for a new target. I don’t want to use unnecessary processor power trying to find a new target when I can’t even shoot it yet so it’s set for the same interval as the attack.

What it actually does:

I have a spawn script that simply spawns an enemy frequently and sends them in range of the tower. The first target goes through exactly as intended. The tower targets it, locks on and breaks the lock when he leaves the tower range. Every subsequent enemy seems to lag on targeting and breaks the lock significantly quicker. Rather than 3-5 seconds being a target, it’s less than a second (well before leaving the tower range). Also the tower spends several “attack intervals” with no target rather than reacquiring a new target. This behavior tends to fluctuate. Sometimes it gets worse and has no target for quite a while and other times appearing like it’s going to fix itself.

Here’s my script:

// *****Public variables to be changed per tower*****

//How far from the tower it can attack
var detectionRange : float;

//How often we can attack a target
//Also is the frequency of checking for new targets if we don't have one
var attackRate : float = 0.5;


//*****Private variables only used in this script*****

//Checks to see if tower has a target
private var hasTarget : boolean;

//This is the transform of the current target
private var closestEnemy : Transform;

//This is used to check distance from tower
private var currentEnemyDist : float;

//Used to help the tower rotate towards the target
private var currentEnemyRot : Vector3;

//Array of enemies within the "detectionRange"
private var enemiesInRange : Collider[];

//Placeholder when cycling through enemies to find closest
private var colDistance : float;

//Another placeholder for cycling through enemies to find closest
private var enemyDistance : float = Mathf.Infinity;




function Start() {
	//Run the script to find new targets and attack them at the "attackRate" interval
	InvokeRepeating("AttackRate", attackRate, attackRate);
	hasTarget = false;
}



function Update () {
	//Checks to see if the target went out of range
	if(hasTarget == true){
		//Checks the distance between the tower and target
		currentEnemyDist = Vector3.Distance(closestEnemy.position, transform.position);
		//If the target is further than the detectionRange, signal no target
		if (detectionRange < currentEnemyDist) {
			hasTarget = false;
		}
	}

	//If we have a target, we want to rotate towards it
	if (hasTarget == true) {
		//Find the difference between tower and target
		currentEnemyRot = closestEnemy.position - transform.position;
		//Reset Y axis so we don't rotate up and down, just left and right
		currentEnemyRot.y = 0;
		//Set Rotation based on above information
		var rotation = Quaternion.LookRotation(currentEnemyRot);
		//Rotate the tower
		transform.rotation = Quaternion.Slerp(transform.rotation, rotation, 100);
	}
}



function AttackRate() {
		//If we have a target, attack it.
		if(hasTarget == true) {
			TowerAttack();
		}
		//If we don't have a target, try to find a new one
		else {
			GetTarget();
			//Check if we found a new one and shoot it if we do
			if(hasTarget == true) {
				TowerAttack();
			}
		}
}



function GetTarget() {
	//Create a sphere with radius of detectionRange and return targets in range
	enemiesInRange = Physics.OverlapSphere(transform.position, detectionRange);
	//Reset enemyDistance variable
	enemyDistance = Mathf.Infinity;
	
	//Cycle through each target in the sphere
	for (var col : Collider in enemiesInRange) {
		//Targets must have the tag "Enemy"
		if (col.gameObject.tag == "Enemy") {
			//Check the distance from the tower to the target
			colDistance = Vector3.Distance(col.transform.position, transform.position);
			//Finds the closest enemy
			//Checks each target to see if the next one is closer than the previous
			if(colDistance < enemyDistance) {
				//If it's closer, set the target
				closestEnemy = col.transform;
				//Set the distance to check against subsequent potential targets
				enemyDistance = colDistance;
				//Set the tower to know it has a target
				hasTarget = true;
			}
		}
	}
}



function TowerAttack() {
	//Eventually put some stuff here to attack
}



function OnDrawGizmos () {
	Gizmos.color = Color.blue;
    if(hasTarget == true) {
        // Draws a blue line from the tower to the target
        Gizmos.DrawLine (transform.position, closestEnemy.position);
    }
    //Draws a sphere to see the detectionRange
    Gizmos.DrawWireSphere (transform.position, detectionRange);
}

So I did a lot more testing and rebuilt the script one piece at a time and it seems like this is the offending script:

//Checks to see if the target went out of range
if(hasTarget == true){
   //Checks the distance between the tower and target
   currentEnemyDist = Vector3.Distance(closestEnemy.position, transform.position);
   //If the target is further than the detectionRange, signal no target
   if (detectionRange < currentEnemyDist) {
     hasTarget = false;
   }

When I take this out, I can run the Physics.SphereOverlap portion under update or InvokeRepeating with no degradation. Unfortunately I can’t NOT have this code in because I don’t want my towers to fire on an enemy who is outside it’s targeting range. How could I rewrite this code to make it work?