Create a Pause Menu

In this tutorial, you will create a pause menu with a settings panel for the Bouncy Box game. However this pause menu can be applied to any game you create.

Setup the Project



Let's start by opening up the Bouncy Box project that you created before.

You can do this by opening Unity Hub, and in the Projects section click on your Bouncy Box project.

Demonstration of completing the steps described in the surrounding text.

If you do not see your project in the Projects list, you can add it by clicking ADD in the top right.

In the file explorer, you can go to the directory where you saved your project, click on the project folder, then click select folder.



Pause Menu UI

Let's start by creating a pause menu where we can select different options.



Previously we created our main menu in a completely new Scene. However we want the pause menu to be in our main game scene so that the player does not have to leave the game when they pause. Instead they will just toggle the UI on and off by pressing a button.

Therefore make sure to open Scene01 so we can add the pause menu UI there.



First we will create a Panel that will be the background for our pause menu.

To create the Panel, right click in the Hierarchy and select UI then Panel.



Again you can see that when we created the Panel, it was automatically made a child to a Canvas object.

You might be too zoomed in to see the whole Canvas at the moment. To zoom out and have the whole Canvas in view, double click on the Canvas object to focus it. Then zoom and pan to get the best view.



Rename the panel to PauseMenu so it is easier to identify.

Then change the color of the Panel to black. We will leave the Alpha channel at its default so that the panel is semi-transparent. This way the player will still partially see the game in the background when it is paused, however there will be a dark overlay so the pause menu is easier to see.

You can test what the Panel will look like over the game by going to the game view and setting the Panel as inactive then active to see the difference.

Hint: Click the checkbox in the inspector of an object to enable or disable it.



Now let's add our pause menu buttons.

First create a TextMeshPro Button as a child of the PauseMenu Panel and rename it to ResumeButton.

Then add the text RESUME to the button and style it how you like.



Now create another button named SettingsButton. However, instead of creating a whole new button, we can just duplicate the first button, rename it to SettingsButton, move it down and change the text to SETTINGS.

To duplicate an object you can right click on the object in the hierarchy and click Duplicate. Alternatively, you can select the object in the hierarchy and press CTRL + D on your keyboard.



Finally we will also create a quit button so the player can quit the game from the pause menu.

Duplicate the settings button then rename it to QuitButton, move the button down and change the text to QUIT.



Pausing the Game

Now that we have the UI for our pause menu, we need to create a script that allows us to actually pause the game.



Start by disabling the PauseMenu Panel by clicking the checkbox in the inspector. This is because the PauseMenu will be disabled by default until we pause the game.

Then create a new script, rename it to PauseMenuController and attach it to the Canvas.



Now open the PauseMenuController script. Start by removing the Start() function as this is not needed.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PauseMenuController : MonoBehaviour
{

    // Update is called once per frame
    void Update()
    {
        
    }
}

          

Now let's create a public static bool variable named GameIsPaused that will keep track on whether the game is currently paused or not.

The variable is public so that other scripts can access it and it is static because the variable will not be for a specific instance of the PauseMenuController. The type of the variable is bool as it will either be true or false. By default we will set the variable to false.

Note: It is common in C# to write static variables with each word capitalized. Unlike normal variables where the first word is lowercase and subsequent words are capitalized (camelCase).

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PauseMenuController : MonoBehaviour
{
    public static bool GameIsPaused = false;

    // Update is called once per frame
    void Update()
    {
        
    }
}

          

Now we need a way to pause the game and for this we will use the ESCAPE key.

In the Update() function, create an if statement that checks if the escape key has been pressed. Remember that you can do this using Input.GetKeyDown().

public class PauseMenuController : MonoBehaviour
{
    public static bool GameIsPaused = false;

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Escape))
        {

        }
    }
}
          

Now inside the if statement we need to add another conditional that checks if the game is already paused or not when we have pressed the escape key.

If the game is paused, then we want to resume the game. Otherwise, this means that the game is not already paused, so we want to pause it.

public class PauseMenuController : MonoBehaviour
{
    public static bool GameIsPaused = false;

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Escape))
        {
            if (GameIsPaused)
            {
                Resume();
            }
            else
            {
                Pause();
            }
        }
    }
}
          

Right now the Resume() and Pause() functions do not exist so we need to create these.

Start by creating a Pause() function with a return type of void.

public class PauseMenuController : MonoBehaviour
{
    public static bool GameIsPaused = false;

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Escape))
        {
            if (GameIsPaused)
            {
                Resume();
            }
            else
            {
                Pause();
            }
        }
    }

    void Pause()
    {

    }
}
          

In this function we want to set the GameIsPaused variable to true, we want to freeze time in the game and we want to enable the Pause Menu Panel.

First we have to create a reference to the UI so that we can control it.

At the top of the script create a public GameObject variable named pauseMenuUI. It is public so that we can set this variable in the inspector.

public class PauseMenuController : MonoBehaviour
{
    public static bool GameIsPaused = false;

    public GameObject pauseMenuUI;

    // Update is called once per frame
    void Update()
    {
          

Now in the Pause() function we can enable the UI using the SetActive() method and pass in the argument true to set the object as active.

      void Pause()
      {
          pauseMenuUI.SetActive(true);
      }
          

We then want to freeze time so that the actual gameplay is paused. We can do this by setting Unity's Time.timeScale property to 0.

Time.timeScale sets the scale at which time passes, based on a float value. 0 means no time passes, 1 means time passes at realtime speed, 0.5 means time passes at half speed, 2 means time passes twice as fast, etc... This is very useful for slow motion effects, speed effects or just pausing the game like in our instance.


      void Pause()
      {
          pauseMenuUI.SetActive(true);
          Time.timeScale = 0f;
      }
          

Finally we want to set the GameIsPaused variable to true.

      void Pause()
      {
          pauseMenuUI.SetActive(true);
          Time.timeScale = 0f;
          GameIsPaused = true;
      }
          

Now we just need to create the Resume function which will be the opposite of the Pause function. However we will make this function public so that we can later use it for our ResumeButton too.

So we need to disable the UI by passing in false to the SetActive() method. We also want to set Time.timeScale to 1 so that the game is no longer frozen. Then we want to set the GameIsPaused variable to false.

      void Pause()
      {
          pauseMenuUI.SetActive(true);
          Time.timeScale = 0f;
          GameIsPaused = true;
      }

      public void Resume()
      {
          pauseMenuUI.SetActive(false);
          Time.timeScale = 1f;
          GameIsPaused = false;
      }
          

Now save your script and go back into the Unity Editor. We still need to set the pauseMenuUI variable in the Inspector so that our script can reference it.

Open the Canvas object in the Inspector, then drag the PauseMenu Panel from the hierarchy into the PauseMenuUI variable slot.



Now play your game and test that you can pause and unpause the game by pressing the ESCAPE key.



Scripting Buttons

Now that the game can be paused, let's add functionality to the Buttons in the pause menu.



For the ResumeButton we actually do not need to create another function for it as we already have a function that resumes the game. Therefore we can just hook up the Resume() function that we created, directly to the ResumeButton.

To do this, open the ResumeButton in the Inspector, then click the + button under On Click(). Since the Canvas contains the script with the required function, drag the Canvas object into the Object Selector. Then choose the function to run by first selecting the script PauseMenuController then selecting the function Resume().



Now play your game again and test that you can resume the game by clicking the Resume button.



Now go back into the PauseMenuController script and create a function for the QuitButton just like we did with the main menu.

      void Pause()
      {
          pauseMenuUI.SetActive(true);
          Time.timeScale = 0f;
          GameIsPaused = true;
      }

      public void Resume()
      {
          pauseMenuUI.SetActive(false);
          Time.timeScale = 1f;
          GameIsPaused = false;
      }

      public void Quit()
      {
          print("Quit Game!");
          Application.Quit();
      }
          

Here we use the Application.Quit() function to quit the game. However, remember that we cannot actually quit the game in the Unity Editor so we also add a print statement to make sure that the function works when we click the button.

We will not need a function for the SettingsButton as we will actually be able to open the settings menu without writing code.

Now return to the Unity Editor and hook up the new Quit() function to the QuitButton, just like with the ResumeButton.

Settings Menu

Now we just have to create a settings menu that we can go to when we click the SettingsButton.



Since the settings menu will be very similar to the pause menu, we can just duplicate the PauseMenu Panel and edit the duplicate.

Start by duplicating the PauseMenu Panel in the canvas and rename it to SettingsMenu. Then delete all of the Buttons as they will not be used in this menu.

We will also enable the panel so we can see it while editing.



For the settings menu, we will use a TextMeshPro Text object for a title that says SETTINGS.

We will also create a TextMeshPro Button that will take us back to the main pause menu.



There are many different settings we could change, but for this lesson we will just add a volume slider that can adjust the master volume.

To add the volume slider UI, right click on the SettingsMenu Panel in the hierarchy and click UI > SLIDER. Resize the slider by clicking and dragging on one of the blue corners. (Hold ALT to scale from the center).



Remember that it is important to rename objects so that they can easily be identified.

Rename the settings text to Title, rename the Button to BackButton and rename the Slider to VolumeSlider.



Let's also add some text above the slider that says MASTER VOLUME so players know what the slider is for.

Rename the Text Object to VolumeText and style the text however you like.



Now that we have the UI for the settings menu, let's hook up the SettingsButton and BackButton so we can go between the two menus. This can easily be done without writing any additional functions.

First, select the Pause Menu's SettingsButton in the hierarchy and add another action to the On Click() event by clicking the + button.



Now we can just reference our SettingsMenu directly by dragging it into the object selection box.

From there we can choose the GameObject > SetActive() function which will allow us to activate the SettingsMenu Object. Click the checkbox to signify that we do want to activate the SettingsMenu when the button is clicked.



We will also need to deactivate the PauseMenu when we click the SettingsButton.

So add another action with the PauseMenu as the object, and once again choose the GameObject > SetActive() function. However, this time make sure that the box is unchecked so the PauseMenu will be deactivated.



Now set the SettingsMenu to be disabled by default and test the game to make sure you can go to the SettingsMenu by clicking the SettingsButton.



Now we just need to hook up the back button in the SettingsMenu so that it will deactivate the SettingsMenu and activate the PauseMenu.

Essentially you just need to do the same thing as with the SettingsButton but the checkboxes should be unchecked for the SettingsMenu and checked for the PauseMenu.



However, remember that we can resume the game by pressing the ESCAPE key. Therefore we also need to deactivate the SettingsMenu when we press that key.

Open up the PauseMenuController Script and create a new public GameObject named settingsMenuUI.

public class PauseMenuController : MonoBehaviour
{
    public static bool GameIsPaused = false;

    public GameObject pauseMenuUI;
    public GameObject settingsMenuUI;

    // Update is called once per frame
    void Update()
    {
          

Then in the Resume() method, deactivate the settingsMenuUI using SetActive(false).

public void Resume()
{
    pauseMenuUI.SetActive(false);
    settingsMenuUI.SetActive(false);
    Time.timeScale = 1f;
    GameIsPaused = false;
}
          

Now save the script and go back into the Unity Editor.

In the Pause Menu Controller component on the Canvas you will now see a field for Settings Menu UI. Drag the SettingsMenu Game Object into the that field.



Test the game once again to make sure you can transition from the PauseMenu to the SettingsMenu and then back to the PauseMenu.

Also make sure that you can pause and unpause the game correctly using the ESCAPE key.



Volume Slider

The last thing we need to do is actually add functionality to the volume slider.



Start by creating a new Script named SettingsMenuController and attach it to the Canvas.



Now open up the script and delete the Start() and Update() methods as these are not needed.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SettingsMenuController : MonoBehaviour
{
    
}
          

Create new public void method named SetVolume that takes in float as an argument which we will call volume.

For now we will make it so that the function just prints the volume variable.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SettingsMenuController : MonoBehaviour
{
    public void SetVolume(float volume)
    {
        print(volume);
    }
}
          

We can easily set this up so that the function is called every time that we move the slider.

Save the script, go back into Unity Editor, and select the VolumeSlider.

Then scroll down in the Inspector to where it says On Value Changed (Single). This is an event that will trigger every time the slider changes.



Now click the + button to add an action to the event.

Drag the Canvas into the Object selector, since this is the object which has the SettingsMenuController script. Then choose the function to run by selecting the components drop down, and hovering over SettingsMenuController.

You will see the list of all functions for the script, including the SetVolume(float) function that we created. However, we want to choose the SetVolume function under Dynamic float at the top of the list. This will automatically input the value of the slider as the float for the volume variable in the function.



Now if you play the game and test the volume slider, you will see values printed in the console showing that our volume variable is being updated with the slider.



Now we just need to use the volume value to control the actual volume of the game.

To do this we will create a Audio Mixer which allows us to control different sound settings of the game.

First open a Audio Mixer Window by clicking Window > Audio > Audio Mixer.



Now click the + button to create a new Audio Mixer and name it MainMixer.



In our Audio Mixer we could create different channels for different layers of audio in the game e.g. background music or SFX. However, we will just be changing the master volume for the whole game audio and as you can see, the Master group is created by default with a volume scale and slider.

We could change the volume by moving the slider on the Master scale, however we want to do this with our script function so that our slider can set the volume. This can be done by exposing the volume parameter of the Master volume group which will allow our script to access and set this value.

Click on the Master volume group to bring it up in the Inspector. Then in the Inspector, right click where it says Volume, then select Expose ‘Volume (of Master)’ to script. You will then see an arrow appear next to Volume meaning that the parameter is exposed to scripts.



Now if you look at the top right of the Audio Mixer window, you will see ExposedParameters now has a 1 in the brackets. Click on this to see a drop down with the volume parameter that we just exposed named MyExposedParam.

Now right click on this and select Rename, then rename the parameter to volume.



You may have noticed before that when we moved our slider, the values went from 0 (lowest) to 1 (highest). This is because by default, UI sliders have a minimum value of 0 and a maximum value of 1.

However, if you look at the Master volume slider you will notice that it starts at 0 and the lowest is -80. Therefore we want to set the minimum and maximum of our slider to be the same.

Click on the VolumeSlider in the hierarchy, then in the inspector change the Min Value to -80 and the Max Value to 0.



Now we can go back into the SettingsMenuController script and update our method to access and modify the Master volume parameter.

First, we need a reference to the Audio Mixer. To do this we will need access to the classes in the UnityEngine.Audio namespace. So add this namespace at the top of the script.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Audio;

public class SettingsMenuController : MonoBehaviour
{
    public void SetVolume(float volume)
    {
        print(volume);
    }
}
          

Then we can create a public AudioMixer variable called audioMixer to reference the Audio Mixer we created, which we will set in the Inspector later.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SettingsMenuController : MonoBehaviour
{
    public AudioMixer audioMixer;

    public void SetVolume(float volume)
    {
        print(volume);
    }
}
          

Then inside of the SetVolume() function we can delete the print statement. Instead we will set the volume of the audioMixer using the volume argument from the VolumeSlider.

To do this use the audioMixer.SetFloat() method and pass in the string volume as this is the parameter of the Audio Mixer that we need to set. Note: the name string passed in must be spelled exactly the same way as how you renamed the exposed parameter of the Audio Mixer.

Then pass another argument into the SetFloat() method which is what we want to set the parameter to. In this case, it is our volume variable which refers to the value we set with the VolumeSlider.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SettingsMenuController : MonoBehaviour
{
    public AudioMixer audioMixer;

    public void SetVolume(float volume)
    {
        audioMixer.SetFloat("volume", volume);
    }
}
          

That's all we need! Save the script and go back into the Unity Editor.

Select the Canvas and drag the MainMixer we created from the Projects Window into the AudioMixer field under the SettingsMenuController script in the inspector.



Now with the Audio Mixer Window open, play the game and drag on the volume slider.

If you find that you can't click on your volume slider or other buttons, make sure that your buttons aren't larger than they should be. The text is the only visible part of the button, it may have a larger invisible part covering your slider.

You will see that the value of the Master volume changes as you move the slider.



Perfect! Now you have a pause menu and a settings menu which has a working volume slider.

At the moment there is no sound in the game, but we will add audio in the next lesson so we can see the volume slider in action.