Zombies Chase Humans Script

Hello everyone - I’ve been working on a game for a few days. Basically, you are a zombie, and you have to infect every human. You start out with one zombie and yourself. Right now I am experimenting on a Constructor, the model that is provided by unity. I have gotten my zombie to follow me around, and any other zombies that are created. I’ve got my first zombie follower to chase after a human, and then turn him into a zombie. The major problem is when a human comes within range of TWO zombies. One zombie slides to the human, while the other zombie doesn’t slide at all (both zombies indicate that they are chasing). The human turns to face upwards, and then runs into the sky.

Script to make zombies follow me around, located in the Update() function of FPSInputController:

        zombies = GameObject.FindGameObjectsWithTag("zombie");

        for(var zombie : GameObject in zombies){
            var relativePoint = zombie.transform.InverseTransformPoint(FPS.position);
            if (relativePoint.z > 0){
                var aiScript = FPS.GetComponent("Zombie");
                if (!aiScript.chasing){
                    zombie.transform.Translate (speed * Vector3.forward * Time.deltaTime);
                }
            }
        }

Zombie script:

var leader : Transform;
var speed : float = 1;
var zombies : GameObject[];
var humans : GameObject[];
var chasing = false;

function Start () {

}

function Update () {
    var walkTo = Vector3(leader.position.x, 0, leader.position.z + 10);
    zombies = GameObject.FindGameObjectsWithTag("zombie");
    humans = GameObject.FindGameObjectsWithTag("human");

    for (var zombie : GameObject in zombies){
        for (var human : GameObject in humans){
            var range : float = Vector3.Distance (zombie.transform.position, human.transform.position);
            if (range < 10){
                chasing = true;
                var position : Vector3 = Vector3(human.transform.position.x, 0, human.transform.position.z);
                zombie.transform.LookAt(position);
                zombie.transform.Translate(speed * Vector3.forward * Time.deltaTime);
                    if (range < 1){
                        var spawnPosition : Vector3 = Vector3(human.transform.position.x, human.transform.position.y, human.transform.position.z);
                        Destroy(human);
                        var whatToclone = Instantiate(zombie, spawnPosition, Quaternion.identity);
                    }
            } else {
                chasing = false;
                zombie.transform.LookAt(walkTo);
            }
        }
    }
}

This script creates a zombie in the place of any human that I touch:

var player : Transform;
var zombieFollower : Transform;
var humans : GameObject[];

function Start () {

}

function Update () {
    humans = GameObject.FindGameObjectsWithTag("human");
    for (var human : GameObject in humans){
        var range : float = Vector3.Distance (human.transform.position, player.position);
        if (range < 1){
            var position : Vector3 = Vector3(human.transform.position.x, human.transform.position.y, human.transform.position.z);
            Destroy(human);
            var whatToclone = Instantiate(zombieFollower, position, Quaternion.identity);
        }
    }
}

Runaway script:

var player : Transform;
var zombies : GameObject[];
var humans : GameObject[];
var speed : float = 1;

function Start () { 

}

function Update() { 

    humans = GameObject.FindGameObjectsWithTag("human");
    zombies = GameObject.FindGameObjectsWithTag("zombie");
    for (var human : GameObject in humans){
        for (var zombie : GameObject in zombies){
            var range : float = Vector3.Distance (human.transform.position, zombie.transform.position);
            var aiScript = player.GetComponent("Zombie");
            if (range < 10){
                if (aiScript.chasing){
                    human.transform.LookAt(2 * human.transform.position - zombie.transform.position);
                    human.transform.Translate (speed * Vector3.forward * Time.deltaTime);
                    human.animation.Play("run");
                }
            } else {
                human.animation.Play("idle");
                human.transform.LookAt(2 * human.transform.position - zombie.transform.position);
                human.rigidbody.velocity = Vector3.zero;
            }
        }
    }
}

Every script you see here is attached to the First Person Controller.

Any suggestions on how to clean up my code and have it do what I want it to do?

Thanks in advance.

Read your comments and your new example code. Try this for your zombie script (Use the same structure for your other scripts). Further, I know BurgZergArcade for one has good video tutorials on how to do what you are doing. He does C# but he shows the concept what you want done.

Hopefully this will get you going. There is still room for improvement. Like having one global list of all zombies and humans. That is maintained as zombies and humans are added/removed.

Doing FindByTag for each human/zombie in each frame is not gonna do very well if you have many zombies and humans.

#pragma strict

var leader 			: Transform;
var speed 			: float 		= 1;
var chasing 		: boolean 		= false;
var zombieFollower 	: Transform;
var picked 			: boolean 		= false;


var thisZombie : Transform;

//By setting that here you can see in the inspector what the closest human is.
var closestHuman : Transform;
var closestDistance : float;

var walkTo : Vector3;

function Start () {
	thisZombie = transform; // thisZombie is now the transform of the current GameObject
}

function Update () {
    walkTo  = Vector3(leader.position.x, 0, leader.position.z + 10);


//Moved this to outside of update, I also changed it to be a transform. So that it does not need to be set every frame.
// I made it a Transform type since that is the most used component of the GameObject. 	
//	var thisZombie : GameObject = this.gameObject;
	


	closestHuman 	= Core.GetClosestObjectTransform(thisZombie.position, "human"); 
	closestDistance = Core.GetDistance(thisZombie.position, closestHuman.transform.position); 
	
	if( closestDistance < 10.0){
		 chasing = true;
		
         
          thisZombie.LookAt( closestHuman.transform.position );
          thisZombie.Translate(speed * Vector3.forward * Time.deltaTime);		

		
		if(closestDistance < 2.0){
               
			var whatToclone : GameObject = Instantiate(zombieFollower, closestHuman.transform.position, Quaternion.identity);

			Destroy(closestHuman);
            chasing = false;
            picked = false;		
		
		}		
	} else {
             chasing = false;
             thisZombie.LookAt(walkTo);		
	}
	
	
}

/* 
Add this class to your game manager script, or make a new script for this class.
By having it static you can access it from any script through the name of the class. in this case Core
*/

static class Core{

	
	function  GetClosestObjectTransform(fromVector3 : Vector3, tag: String){
    	var objectsWithTag : GameObject[] = GameObject.FindGameObjectsWithTag(tag);
    	var closestObject : GameObject;
    	for (var obj : GameObject in objectsWithTag){
    		if(!closestObject){
				 closestObject = obj;
    		}
    		//compares distances
    		if(Vector3.Distance(fromVector3, obj.transform.position) <= Vector3.Distance(fromVector3, closestObject.transform.position)){
    			closestObject = obj;
    		}
    	}
    	return closestObject.transform;
    }
	
    function GetDistance(from : Vector3, to : Vector3){
         		return Vector3.Distance(from, to);
    			
    }	
    
 
	
}

Sorry everybody, this answer is REALLY late. I finished the script a few weeks ago. Here it is:

Zombie.js:

var leader : Transform;
var speed : float = 1;
var humans : GameObject[];
var chasing = false;
var zombieFollower : Transform;
var humansInrange = new Array();

function Start () {
	
}

function Update () {
    humans = GameObject.FindGameObjectsWithTag("human");
    var walkTo = Vector3(leader.position.x, 0, leader.position.z + 10);
	var thisZombie : GameObject = this.gameObject;
    var closestDistance : float = Mathf.Infinity;
    for (var human : GameObject in humans){
    	var distance : float = Vector3.Distance (thisZombie.transform.position, human.transform.position);
    	if (distance <= 10){
    		humansInrange.Add(human);
    	}
    }
    
    var closestHuman : GameObject = GetClosestHuman(thisZombie.transform.position, humansInrange);
    
    if (closestHuman){
    	var range : float = Vector3.Distance (thisZombie.transform.position, closestHuman.transform.position);
   		if (range < 10){
   			thisZombie.rigidbody.constraints = RigidbodyConstraints.FreezeRotation;
			chasing = true;
			var position : Vector3 = Vector3(closestHuman.transform.position.x, 0, closestHuman.transform.position.z);
			thisZombie.transform.LookAt(position);
			thisZombie.transform.Translate(speed * Vector3.forward * Time.deltaTime);
			if (range < 1.5){
	   			var spawnPosition : Vector3 = Vector3(closestHuman.transform.position.x, 0, closestHuman.transform.position.z);
    			humansInrange.Remove(closestHuman);
    			Destroy(closestHuman);
				var whatToclone = Instantiate(zombieFollower, spawnPosition, Quaternion.identity);
			}
	   	} else if (range > 10){
	   		chasing = false;
			thisZombie.transform.LookAt(walkTo);
			thisZombie.rigidbody.constraints = RigidbodyConstraints.FreezeRotation;
		}
	} else {
		chasing = false;
	}
}

function GetClosestHuman(fromVector3 : Vector3, humanArray : Array){
	var closestObject : GameObject;
	for (var obj : GameObject in humanArray){
		if (obj){
			if(!closestObject){
				closestObject = obj;
			}
			if(Vector3.Distance(fromVector3, obj.transform.position) <= Vector3.Distance(fromVector3, closestObject.transform.position) && Vector3.Distance(fromVector3, obj.transform.position) <= 10){
				closestObject = obj;
			}
		}
	}
	return closestObject;
}

Runaway.js:

var player : GameObject;
var zombies : GameObject[];
var speed : float = 1;
var beingChased = false;
var zombiesInrange = new Array();

function Start () { 
	
}

function Update() { 
    zombies = GameObject.FindGameObjectsWithTag("zombie");
    var thisHuman : GameObject = this.gameObject;
    
	for (var zombie : GameObject in zombies){
		var distance : float = Vector3.Distance (thisHuman.transform.position, zombie.transform.position);
    	if (distance <= 10){
    		zombiesInrange.Add(zombie);
    	} else {
    		zombiesInrange.Remove(zombie);
    	}
    }
    
    var range : float = Vector3.Distance (thisHuman.transform.position, player.transform.position);
    var lookat : Vector3 = Vector3(thisHuman.transform.position.x, 0, thisHuman.transform.position.z);
    
    if (range <= 10){
    	zombiesInrange.Add(player);
    } else {
    	zombiesInrange.Remove(player);
    }
    
    var closestZombie : GameObject = GetClosestZombie(thisHuman.transform.position, zombiesInrange);
    var center : Vector3 = new Vector3(0, 0, 0);
	var count : float = 0;
	
	for (var zombieInrange : GameObject in zombiesInrange){
		if (closestZombie){
   			center += zombieInrange.transform.position;
   			count++;
   		}
   	}
   	
   	var theCenter = center / count;
   	center.y = 100;
   	
   	if (closestZombie){
   		thisHuman.GetComponent(Runaway).beingChased = true;
   	} else {
   		thisHuman.GetComponent(Runaway).beingChased = false;
   	}
    
   	if (beingChased){
   		thisHuman.transform.LookAt(2 * lookat - theCenter);
    	thisHuman.transform.Translate (speed * Vector3.forward * Time.deltaTime);
    	thisHuman.animation.Play("run");
       	thisHuman.transform.position.y = 1;
       	thisHuman.rigidbody.velocity = Vector3.forward;
	} else {
    	thisHuman.animation.Play("idle");
       	thisHuman.rigidbody.velocity = Vector3.zero;
       	thisHuman.rigidbody.constraints = RigidbodyConstraints.FreezePosition | RigidbodyConstraints.FreezeRotation;
	}
}

function GetClosestZombie(fromVector3 : Vector3, humanArray : Array){
	var closestObject : GameObject = null;
	var thisHuman : GameObject = this.gameObject;
	for (var obj : GameObject in humanArray){
		if (obj){
			if(!closestObject){
				closestObject = obj;
			}
			if(Vector3.Distance(fromVector3, obj.transform.position) <= Vector3.Distance(fromVector3, closestObject.transform.position)){// && Vector3.Distance(fromVector3, obj.transform.position) <= 10){
				closestObject = obj;
				thisHuman.GetComponent(Runaway).beingChased = false;
			}
		}
	}
	return closestObject;
}

ZombieTransform.js:

var player : Transform;
var zombieFollower : Transform;
var once = false;
var humans : GameObject[];

function Start () {
	
}

function Update () {

    if (!once){
    	humans = GameObject.FindGameObjectsWithTag("human");
    	for (var human : GameObject in humans){
    		var range : float = Vector3.Distance (human.transform.position, player.position);
    		if (range < 1.5){
      			var position : Vector3 = Vector3(human.transform.position.x, 0, human.transform.position.z);
       			Destroy(human);
				var whatToclone = Instantiate(zombieFollower, position, Quaternion.identity);
			}
		}
    }
}

Code put into the Update() function of the FPSInputController script:

zombies = GameObject.FindGameObjectsWithTag("zombie");
		
		for(var zombie : GameObject in zombies){
			var relativePoint = zombie.transform.InverseTransformPoint(FPS.position);
			if (relativePoint.z > 0){
				var aiScript = zombie.GetComponent("Zombie4");
				if (!aiScript.chasing){
					//var lookat : Vector3 = Vector3(FPS.position.x, FPS.position.y, FPS.position.z + 10);
					zombie.transform.Translate (speed * Vector3.forward * Time.deltaTime);
					//zombie.transform.LookAt(lookat);
				}
			}
		}

Again, really sorry about getting this out late. But, here it is. It works perfectly!

Thanks to these people, they gave me the code/ideas I needed to complete this script:

I used tw1st3d’s suggestion in my other post, “How do I single out one object amongst a group of objects with the same tag?”

I also used Linus’ GetClosestObjectTransform() function from his answer.