Trending
Opinion: How will Project 2025 impact game developers?
The Heritage Foundation's manifesto for the possible next administration could do great harm to many, including large portions of the game development community.
Welcome back to day 25! Today is going to be relatively short, we’re going to finish our Enemy Spawning system by adding a victory state.
Welcome back to day 25! We’re officially ¼ of our way to the goal!
Today is going to be relatively short, we’re going to:
finish our Enemy Spawning system by adding a victory state
Let’s get started!
The first thing we need to do is create another panel that tells the user that they won the game.
Instead of going through the work of creating another UI and animation for our Victory Panel, we’re going to take the easy approach and make a duplicate of our existing GameOver game object and re-purpose it.
Currently, we can use the same script and animator, because they both do the same thing.
To do that, select GameOver in our hierarchy and then hit Ctrl + D to make a duplicate. Rename the duplicate to Victory. They can both just stay in the canvas.
Now that we have our Victory panel, we need to change our text so that the players will know that they won.
Select Victory > Text (not Button > Text) and change the words from “Game Over” to “You win!”
Now that we have a fully functioning Victory Panel, it’s time to use it!
We’re going to have to change 2 scripts to make this work:
GameManager
SpawnManager
The first thing that we’re going to do is setup GameManager to use our Victory panel.
Here’s our code:
using UnityEngine;
public class GameManager : MonoBehaviour
{
public Animator GameOverAnimator;
public Animator VictoryAnimator;
private GameObject _player;
void Start()
{
_player = GameObject.FindGameObjectWithTag("Player");
}
public void GameOver()
{
GameOverAnimator.SetBool("IsGameOver", true);
DisableGame();
}
public void Victory()
{
VictoryAnimator.SetBool("IsGameOver", true);
DisableGame();
}
private void DisableGame()
{
_player.GetComponent<PlayerController>().enabled = false;
_player.GetComponentInChildren<MouseCameraContoller>().enabled = false;
_player.GetComponentInChildren<PlayerShootingController>().enabled = false;
Cursor.lockState = CursorLockMode.None;
}
}
The only new code was that we added the VictoryAnimator, like GameOverAnimator, this is the animator for our victory panel.
Here’s how our code works:
I created a new public Victory() that our SpawnManager will call to trigger our Victory Panel animation.
To keep our code clean, I moved the code that was previously in GameOver() into DisableGame() that way we don’t have to write the same code twice in both Victory() and GameOver()
Now that our GameManager can play our victory animation, we need to call it when we win the game from our SpawnManager.
Here’s the code for this:
using System.Collections;
using UnityEngine;
[System.Serializable]
public class Wave
{
public int EnemiesPerWave;
public GameObject Enemy;
}
public class SpawnManager : MonoBehaviour
{
public Wave[] Waves; // class to hold information per wave
public Transform[] SpawnPoints;
public float TimeBetweenEnemies = 2f;
private GameManager _gameManager;
private int _totalEnemiesInCurrentWave;
private int _enemiesInWaveLeft;
private int _spawnedEnemies;
private int _currentWave;
private int _totalWaves;
void Start ()
{
_gameManager = GetComponentInParent<GameManager>();
_currentWave = -1; // avoid off by 1
_totalWaves = Waves.Length - 1; // adjust, because we're using 0 index
StartNextWave();
}
void StartNextWave()
{
_currentWave++;
// win
if (_currentWave > _totalWaves)
{
_gameManager.Victory();
return;
}
_totalEnemiesInCurrentWave = Waves[_currentWave].EnemiesPerWave;
_enemiesInWaveLeft = 0;
_spawnedEnemies = 0;
StartCoroutine(SpawnEnemies());
}
// Coroutine to spawn all of our enemies
IEnumerator SpawnEnemies()
{
GameObject enemy = Waves[_currentWave].Enemy;
while (_spawnedEnemies < _totalEnemiesInCurrentWave)
{
_spawnedEnemies++;
_enemiesInWaveLeft++;
int spawnPointIndex = Random.Range(0, SpawnPoints.Length);
// Create an instance of the enemy prefab at the randomly selected spawn point's position and rotation.
Instantiate(enemy, SpawnPoints[spawnPointIndex].position, SpawnPoints[spawnPointIndex].rotation);
yield return new WaitForSeconds(TimeBetweenEnemies);
}
yield return null;
}
// called by an enemy when they're defeated
public void EnemyDefeated()
{
_enemiesInWaveLeft--;
// We start the next wave once we have spawned and defeated them all
if (_enemiesInWaveLeft == 0 && _spawnedEnemies == _totalEnemiesInCurrentWave)
{
StartNextWave();
}
}
}
In our code, we created a new private _gameManager which will be how we access our GameManager.
The code is straightforward:
In Start() we get an instance of our GameManager script by looking for SpawnManager’s parent, which in this case is the GameManager game object. Then we just take the script from there.
We use _gameManager in StartNextWave(), when we have completed all the waves in the game.
We have the script ready, the final thing for us to do is for us to add our new Victory game object to our script.
When selecting our GameManager in our Game Manager script drag our Victory game object into the Victory Animator slot. Unity will automatically pull the animator from the game object for our script.
Now that we have set our victory animation, if we were to play the game and win, we’ll have something happen!
Specifically, this!
This will be the end of our Spawning System (for now).
I’m hoping to introduce at least 2 more enemies into the game, so we’ll have to come back, but for this simple FPS, our spawning system is complete.
Tomorrow, my plan is to go and fix minor parts of the game that we glanced over and then move on to adding more units!
See you then!
Source: Day 25
Visit the 100 Days of Unity VR Development main page.
Visit our Homepage
Read more about:
BlogsYou May Also Like