ZombieController script

This script will be attached to the ZombiePrefab so that the behavior is applied each time an animated corpse is spawned. Take the following steps to set it up:

  1. Select the ZombiePrefab from the Project/Prefab folder and add a script component in the Inspector panel. Rename the script ZombieController.
  2. Move the script to the Scripts folder.
  3. Open the script in your editor and remove the Start () function. Since this script is a little longer, we'll break the description into parts:
 using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ZombieController : MonoBehaviour { private Animator _animator; private Rigidbody _rigidbody; private CapsuleCollider _collider;
private GameObject _target;

public float moveSpeed = 1.5f;
private bool _isDead, _isAttacking;

The ZombieController script will primarily handle the prefab's movement, attack, and death. This first bit of code is used to create and assign values to the local variables:

private void Awake () { 
// Awake occurs when a zombie is spawned. At that time we capture
prefab components
// for use in movement, collision, attack and death _animator = GetComponent<Animator> (); _rigidbody = GetComponent<Rigidbody> (); _collider = GetComponent<CapsuleCollider> ();
_target = GameObject.FindGameObjectWithTag("Player"); } private void Update () {
// During each frame we rotate the zombie toward the player. This
allows for player
// movement during runtime
Vector3 targetPostition = new Vector3(
_target.transform.position.x,
0f, _target.transform.position.z );
transform.LookAt (targetPostition); } private void FixedUpdate () {
// In FixedUpdate we move the prefab, if it is alive and not
attacking if (!_isDead && !_isAttacking) {
_rigidbody.velocity = (_target.transform.position -
transform.position).normalized * moveSpeed; } }

Here, we call three methods, Awake, Update, and FixedUpdate, to access different components of the prefab. In Awake, we assign component values to the four private variables.

After being spawned, our zombies are going to move in a straight line toward the player. However, since the left and right lane are at an angle, this could produce an unwanted situation where the zombies are moving in one direction, but facing another. To fix this, we add a LookAt. This command rotates the prefab's transform so that the forward vector points to a specific object or location. In this case, we are pointing them toward the player's location within the scene.

Where Update rotates the prefab toward the player GameObject, FixedUpdate moves our zombie. The if statement is used to determine if the creature should be moving. When this statement is true, the Zombie prefab moves toward the origin (the player's starting position) based on the provided Move Speed. Note that the z-value of the spawn points if either 17 or 23, and to move towards the player we need a negative velocity.

We use FixedUpdate here because it is called in regular interval where Update runs after all calculations are completed. Because of this. Time.deltaTime for Update is varied, where as, Time.deltaTime for FixedUpdate is consistent.

FixedUpdate should be used instead of Update when dealing with Rigidbody: https://docs.unity3d.com/ScriptReference/Rigidbody.html. For example, when adding a force to a Rigidbody, you have to apply the force to every fixed frame inside FixedUpdate instead of every frame inside Update.

The next two functions will determine what happens when a zombie is killed:

public void Die () {
// Once we have decided to kill off a zombie, we must set its local
// variables to their default values.
_rigidbody.velocity = Vector3.zero;
_collider.enabled = false; _isDead = true; _animator.SetBool ("Death", true); _animator.SetInteger ("DeathAnimationIndex", Random.Range (0, 3));
StartCoroutine (DestroyThis ()); } IEnumerator DestroyThis () {
// Before destroying the prefab, we will wait until it's animation
is complete
// the value listed here is the length of the walk cycle yield return new WaitForSeconds (1.5f); Destroy (GameObject); }

Let's look at the individual statements in void Die to get a better understanding of what is going on in this script.

The first statement sets the prefab's velocity to zero, stopping the zombie's forward motion. Then, we turn off the collider. By turning off the collider, we are assured the prefab can no longer trigger actions associated with the raycaster or the player.

Next, we set the _isDead variable to true signifying that the zombie should no longer be treated as a threat, that is capable of attacking the player. The following two lines set the Animator's Death parameter to true and plays a random death animation. Once the animation begins, we call another coroutine called DestoryThis. This coroutine then waits for 1.5 seconds (the length of the death animations) before removing the GameObject from the scene.

Make sure the script has a closing } bracket:

  1. Save the script, return to Unity.
  2. Run the scene.

We now have the base structure for our zombie controller, but we still need to add a few more functions. As the scene runs, the zombies will spawn as indicated by the frequency setting and move toward the player using the Move Speed value.

However, since we do not have a method for triggering the Die() function, our scene will continually spawn zombies, overrunning the player and filling the space:

Figure 6.1: Zombies on the march