The Final WaveZ

Image of the original map

This game began as the final assignment for my Simulation and Game Development class. Initially this game was a linear top down zombie shooter in which the player had to traverse through various zones while fighting zombies in order to make it to the end.

Since graduation I have returned to this project completely revamping it into a wave based shooter with an economy and upgrade system. I have been using my work on this game to push myself to learn more about game development with the aim to turn this project into a complete game that I plan to publish for mobile.

Using this game I have learned about object pooling, scriptable objects, animation, lighting, post-processing, optimization for mobile and more.

First build
Pre-Demo build
Current build

From the early build to present

The Game

(Note this game is not targeted for WebGl, It is recommended to play the Windows or Android builds for best performance, or reduce window size)

UnityC#

Controls:

WSAD - Move
Mouse - Aim
Mouse Left Button - Shoot
ESC - Pause

Features

Features in Development

  • Bosses - I am working on a boss that uses a state machine to detemine when to attack and what attacks to use based on distance to the player. The boss is currently functional but needs some tweaking before it is implemented into the levels.
  • Unlockable areas in each level - I am working on adding new areas in each level that will become accesible once bosses are defeated or other criteria is met.
  • More zombie variants - In addition to adding more variety to the zombies apearence, I am working on adding zombies that will have more ranged attacks, poison, and fire attacks.

Custom Enemy Spawner

The game makes use of a custom spawner that utilizes object pooling shared among all the enemy spawners. These spawners are customizable in the editor to cover any area. Enemies will only spawn when the player is in range and despawn after the player has left range for a set period of time.


private void Spawn()
{
    spawnAttempts = 0;

    do
    {
        //Track how many attempts are made to find a valid spawn position
        spawnAttempts++;

        //Create a random spawn point within the spawn zone
        nextSpawnPosition = spawnAreaCenter + new Vector3(Random.Range(-spawnAreaSize.x / 2, spawnAreaSize.x / 2), 0, Random.Range(-spawnAreaSize.z / 2, spawnAreaSize.z / 2));
        //Use a raycast sphere with the zombies radius to check that the spawn point is clear of other objects
        ray = new Ray(transform.position + new Vector3(nextSpawnPosition.x, 10, nextSpawnPosition.z), Vector3.down);
        //Start from Ray pos, radius, output hit, distance, layers to hit
        isSpawnPointInvalid = Physics.SphereCast(ray, 0.5f, 12, nonSpawnableLayers);


        //If there have been too many unsuccesful attempts to find a valid spawn pos return
        if (spawnAttempts > spawnAttemptLimt)
        {
            Debug.Log($"{gameObject.name} had {spawnAttemptLimt} failed spawn attempts");
            return;
        }

    } while (isSpawnPointInvalid);

    //Spawn Zombie
    PoolableObject instance = WaveManager.Instance.zombiePool.GetObject();
    if (instance != null)
    {
	//Assign zombie stats
        instance.GetComponent<ZombieHealth>().stats = stats;
        instance.GetComponent<ZombieHealth>().enabled = true;
        instance.GetComponent<ZombieMovement>().stats = stats;

        //Set zombie as child to spawner
        instance.transform.SetParent(transform, false);

        //Move zombie to spawn point
        instance.transform.localPosition = new Vector3(nextSpawnPosition.x, 0, nextSpawnPosition.z);
        lastSpawnTime = Time.time;
    }
    WaveManager.Instance.EnemySpawned(1);
}
							

Custom Event System

The game makes use of a custom event system that allows events to be created as scriptable objects. This method allows both the broadcaster and any listeners to be compleatly detached from each other.



Upgrade System


The game contains five different resources, cash, wood, scraps, gas & energy. To get the differnt materials the player will have to play each level and survive as long as they can. At the camp the player has access to differnt shops to purchase upgrades ranging from health and defence upgrades to firing speed and damage upgrades with more planned for the future.

As the player purchases more upgrades, their cost will increase and eventually require different resources, thus in order to max out an upgrade the player will have to have unlocked access to each level.