Here’s how to make a quick and dirty pause system in Unity. The overall breakdown involves four general steps:
- Make a paused panel pop up on a keypress
- Make that same keypress stop the movement of all game objects
- Pause all visible coroutines
- Pause all particles
Of course, individual results may vary, but this will hopefully get you moving in the right direction. Below are more details on each of these steps.
Make A Paused Panel Pop Up On A Keypress
Start by creating a UI canvas and paused panel that you wish to appear when you press a key. For this purpose, we will use the “P” key. I don’t currently have tutorials on making a pause panel, but there are plenty on the internet. I’ll be using the one below for mine.
Arrange the panel in your scene the way you want it to appear when the player pauses the game. Then, with the paused panel selected, you’ll see a checkbox to the top left of the inspector. Make sure to uncheck that box. That makes sure the panel will be inactive when the scene starts.
Next, to make the paused panel pop up on a keypress, first open the script you use for your Game Controller and add a “public GameObject pausedPanel;” and a “public int pauseSpeed = 1;” . We will discuss pauseSpeed later.
Back in Unity, select your Game Controller object. The Game Controller script should now have a Pause Panel slot in the inspector, where you will want to drag the scene’s instance of your paused panel. Next, add the below code to your Game Controller script, within the Fixed Update function.
void FixedUpdate()
{
//Pause
if (Input.GetKeyDown (KeyCode.P))
{
if (pauseSpeed == 1)
{
pauseSpeed = 0;
pausedPanel.SetActive(true);
}
//Play
else
{
pauseSpeed = 1;
pausedPanel.SetActive(false);
}
}
}
This code basically says “if the user presses “P”, check if pauseSpeed is 1. If it is, set it to 0 and open the pausedPanel. Otherwise, if pauseSpeed, isn’t 1 (which means it should be 0), set it to 1 and close the pausedPanel.
You may wonder why we don’t make pauseSpeed a bool if we are only setting it to 0 or 1. That reason comes next.
Stop the Movement of All Game Objects
There are two ways of doing this one. How you do it decides whether or not you need pauseSpeed to be a public int.
- You can make all your mover scripts – any script that determines the speed or rotation of a game object – access the pauseSpeed of the GameController and multiply it by the speed in the script. This option is a little move complicated and requires that pauseSpeed be public.
- You can have your mover scripts check for a keypress and then toggle their own version of pauseSpeed, which is then multiplied by the speed in the script. We will use this option.
Either way, both of these routes use pauseSpeed to change the speed or rotation of an object’s movement. For example, say an object using your script moves at a speed of 5. Now multiply that speed by pauseSpeed. If we are paused and pauseSpeed is 0, 5 x 0 = 0. If we are in play and pauseSpeed is 1, 5 x 1 = 5.
So now open your mover scripts and, for each one, add the “private int pauseSpeed = 1;”. Then add the below code in FixedUpdate:
void FixedUpdate()
{
//Pause
if (Input.GetKeyDown (KeyCode.P))
{
if (pauseSpeed == 1)
{
pauseSpeed = 0;
}
//Play
else
{
pauseSpeed = 1;
}
}
}
This is almost the same script as the one you added in the Game Controller script, minus the pausedPanel.
Finally, for each piece of your movement scripts that involve speed, add “*pauseSpeed” next to the speed variable.
For example, “rb.velocity = transform.forward * speed * pauseSpeed;”.
Now, back in the Game Controller script, pauseSpeed doesn’t just decide velocity.
Pause All Visible Coroutines
This is where a lot of individual results may vary. I am open to add some color to any questions in the comments, but the primary coroutines I am talking about on here have to do with loops that spawn enemies and others of the like. Coroutines that visibly change the scene.
You’ll have your own coroutines and loops in your game controller, but the gist of this system is that pauseSpeed can be used to make it look like they are paused. Note: they will still be running in the background, so if you want to do some extra work to actually pause them, feel free.
But, in this case, it’s easiest to show where pauseSpeed fits in the loop prompts. So here that is:
for (int i = 0; i < Random.Range(spawnMin,spawnMax)*pauseSpeed; i++)
Basically, this prompt says that i starts at 0 and, for each time i is less than the variable number, do something. Then it repeats over and over. That being said, when you are paused and pauseSpeed equals 0, that variable number will always be 0. So the loop will never run. That is, at least, until you return to play and pauseSpeed returns to 1.
Pause All Particles
The final step is to pause particle systems; and Unity has built-in functions to do so. It is just a matter of having a script attached to your particle systems that listens for a keypress and then runs Unity’s functions to pause or play the particles. That script is below:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ParticleParameters : MonoBehaviour
{
private bool paused = false;
void FixedUpdate()
{
if (Input.GetKeyDown (KeyCode.P))
{
if(paused == true)
{
GetComponent<ParticleSystem>().Play();
paused = false;
}
else
{
GetComponent<ParticleSystem>().Pause();
paused = true;
}
}
}
}
This script checks for when “P” is pressed. Then, if the paused bool is true, it sets it to false and plays the particle system it is attached to. On the other hand, if the paused bool is false, it sets it to true and pauses the particle system.
Simply create this script and attach it as a component of the object containing the particle system you want to pause.
A Note
The first thing that may pop out to you is that pauseSpeed is used so widely throughout this system that it might be better to make it a static variable. That is next on my list of items to research and I will update this post when I finish that.
Hopefully this gives you some ideas for your own pause system in Unity. Like I said, individual results will vary; but I’m happy to help or discuss where able. Drop a comment!
-LVL12