THE ROAD RUNNER TUTORIAL 9: CREATING A PAUSE MENU

Check out the gameplay of the finished game below:



It is habitual to get distracted by ourselves(more than something distracting us) while we are studying for the exams. What do we do in such cases? Well, maybe have a Cup of Coffee? Play Games? Watch Television? Sleep? Whatever we do, I bet it is much more enjoyable than studying for the exams.

On the Contrary, seldom we get distracted by ourselves(perhaps, it wont be wrong, if I say never, ever, do we get distracted) while playing games. And what do we do when someone distracts us? Scold them? Punch them? Well, before that we make sure we pause the game. Right, pause the game! This is the feature that has saved many relationships, lives, and what not.

Right, so this is precisely what we will be learning today. To add a Pause Menu to our game.

The first thing that you need to do to add this Pause functionality to our game is to create a C# script named PauseMenuScript in the Scripts folder. Attach this script to the GameController GameObject

To get started with this script we create some variables
public GUISkin myskin;  //custom GUIskin reference
public string levelToLoad;
public bool paused = false;  //flag to check if the game is paused
The Update function will look like
private void Update()
 {
  if (Input.GetKey(KeyCode.Escape) ) //check if Escape key/Back key is pressed
  {
   if (paused)
    paused = false;  //unpause the game if already paused
   else
    paused = true;  //pause the game if not paused
  }

  if(paused)
   Time.timeScale = 0;  //set the timeScale to 0 so that all the procedings are halted
  else
   Time.timeScale = 1;  //set it back to 1 on unpausing the game
 }
Here, we check if the user has pressed the escape/back key. And regardless of what the status of the paused variable is, we are inverting it. We are pausing the game if it's active or resuming the game if it's paused.

The lines,
if (Input.GetKey(KeyCode.Escape) ) //check if Escape key/Back key is pressed
  {
   if (paused)
    paused = false;  //unpause the game if already paused
   else
    paused = true;  //pause the game if not paused
  }
are as good as writing
if (Input.GetKey(KeyCode.Escape) ) //check if Escape key/Back key is pressed
  {
   paused = !paused;   //invert the current status. Pause if active, unpause if paused
  }
In the OnGUI function we will add the Pause Menu options like Resume, Restart the game, go to Main Menu
private void OnGUI()
 {
  GUI.skin=myskin;   //use the custom GUISkin

  if (paused){     
           GUI.Box(new Rect(Screen.width/4, Screen.height/4, Screen.width/2, Screen.height/2), "PAUSED");
   //GUI.Label(new Rect(Screen.width/4+10, Screen.height/4+Screen.height/10+10, Screen.width/2-20, Screen.height/10), "YOUR SCORE: "+ ((int)score));
   
   if (GUI.Button(new Rect(Screen.width/4+10, Screen.height/4+Screen.height/10+10, Screen.width/2-20, Screen.height/10), "RESUME")){
    paused = false;
   }

   if (GUI.Button(new Rect(Screen.width/4+10, Screen.height/4+2*Screen.height/10+10, Screen.width/2-20, Screen.height/10), "RESTART")){
    Application.LoadLevel(Application.loadedLevel);
   }
   
   if GUI.Button(new Rect(Screen.width/4+10, Screen.height/4+3*Screen.height/10+10, Screen.width/2-20, Screen.height/10), "MAIN MENU"){
    Application.LoadLevel(levelToLoad);
   }
  }
 }
The above lines of code are pretty similar to the Game Over menu that we saw in one of the earlier posts.

For the Restart functionality of the Pause Menu to work, we have to set back the Time.timeScale to 1.
This is done by
private void Start()
 {
  Time.timeScale=1; //Set the timeScale back to 1 for Restart option to work  
 }
If you integrate all this into one script and test you will notice that it pauses the game alright, however, the unpause option by hitting the back/escape key again doesn't seem to work normally. That is because the
The complete PauseMenuScript will look like:

using UnityEngine;
using System.Collections;

public class PauseMenuScript : MonoBehaviour 
{
 public GUISkin myskin;  //custom GUIskin reference
 public string levelToLoad;
 public bool paused = false;
 
 private void Start()
 {
  Time.timeScale=1; //Set the timeScale back to 1 for Restart option to work  
 }
 
 private void Update()
 {
  
  if (Input.GetKeyDown(KeyCode.Escape) ) //check if Escape key/Back key is pressed
  {
   if (paused)
    paused = false;  //unpause the game if already paused
   else
    paused = true;  //pause the game if not paused
  }

  if(paused)
   Time.timeScale = 0;  //set the timeScale to 0 so that all the procedings are halted
  else
   Time.timeScale = 1;  //set it back to 1 on unpausing the game
  
 }
 
 private void OnGUI()
 {
  GUI.skin=myskin;   //use the custom GUISkin

  if (paused){    
    
          GUI.Box(new Rect(Screen.width/4, Screen.height/4, Screen.width/2, Screen.height/2), "PAUSED");
   //GUI.Label(new Rect(Screen.width/4+10, Screen.height/4+Screen.height/10+10, Screen.width/2-20, Screen.height/10), "YOUR SCORE: "+ ((int)score));
   
   if (GUI.Button(new Rect(Screen.width/4+10, Screen.height/4+Screen.height/10+10, Screen.width/2-20, Screen.height/10), "RESUME")){
    paused = false;
   }

   if (GUI.Button(new Rect(Screen.width/4+10, Screen.height/4+2*Screen.height/10+10, Screen.width/2-20, Screen.height/10), "RESTART")){
    Application.LoadLevel(Application.loadedLevel);
   }
   
   if (GUI.Button(new Rect(Screen.width/4+10, Screen.height/4+3*Screen.height/10+10, Screen.width/2-20, Screen.height/10), "MAIN MENU")){
    Application.LoadLevel(levelToLoad);
   } 
  }
 }
}
Now select the GameController game object in the Hierarchy so that we can see it's components in the Inspector. You will notice that the PauseMenuScript script is expecting a GUI skin, drag and drop the custom GUIskin that we created in the previous post.
Also, there is one more field named levelToLoad which is expecting some value. Type MainMenuScene in it. Though we have not created the MainMenuScene yet, we will be doing so in the next post.


If you test this by pressing the Play button or simply hitting the ctrl+P in Windows or cmd+P in Mac., on pressing the escape key you will notice that the Pause Menu pops up and your player halts as well, however, the spawned snags and the powerups doesn't seem to stop. This is because we are translating the spawned objects, and this translation is frame rate dependent. This can be fixed in Three ways:
1) Check if the Time.timeScale is 1 before translating the object.
2) Multiply Time.timeScale to the transfrom.Translate
3) Make the translation frame rate independent by multiplying the transform.Translate with Time.deltaTime (Of course, you need to change the objectSpeed)

So, the PowerupScript and ObstacleScript for the first case will look like
using UnityEngine;
using System.Collections;

public class PowerupScript : MonoBehaviour {

//public GameControlScript control;
public float objectSpeed = -0.5f;


void Update () {
if(Time.timeScale==1){
transform.Translate(0, 0, objectSpeed);
}
}
}

using UnityEngine;
using System.Collections;

public class ObstacleScript : MonoBehaviour {

//public GameControlScript control;
public float objectSpeed = -0.5f;


void Update () {
if(Time.timeScale==1){
transform.Translate(0, objectSpeed, 0);
}
}
}
The second case is pretty self explanatory and I believe you should be able to modify it if you want to use that method. However, I would prefer the third case, whose changes will look like

using UnityEngine;
using System.Collections;

public class PowerupScript : MonoBehaviour {

//public GameControlScript control;
public float objectSpeed = -20f;


void Update () {

transform.Translate(new Vector3(0, 0, objectSpeed)*Time.deltaTime);

}
}

using UnityEngine;
using System.Collections;

public class ObstacleScript : MonoBehaviour {

//public GameControlScript control;
public float objectSpeed = -20f;


void Update () {

transform.Translate(new Vector3(0, objectSpeed, 0)*Time.deltaTime);

}
}

(Note: The change in the objectSpeed might not reflect as it is a public variable and you need to change it from the Inspector itself to see any notable changes.)



If you save the scripts and try testing the game now, you will find that we have successfully completed adding the Pause functionality to our game.



Download the completed version of this game from the Resources page.

The Road Runner Tutorial 1: Setting Up The World
The Road Runner Tutorial 2: Setting Up The World Continued
The Road Runner Tutorial 3: Adding A Character To Our Game
The Road Runner Tutorial 4: Set The Ground Moving
The Road Runner Tutorial 5: Adding Snags and Powerups to Our Game
The Road Runner Tutorial 6: Collecting The Snags and Powerups
The Road Runner Tutorial 7: Adding Gameplay Logic
The Road Runner Tutorial 8: Creating a Custom GUI Skin
The Road Runner Tutorial 10: Adding Countdown and Main Menu
The Road Runner Tutorial 11: Adding Sound Effects To Our Game
The Road Runner Tutorial 12: Porting The Game To Android
Share on Google+

About Sujit Horakeri

Sujit Horakeri is a game freak just like any other next door guy you would come across. He is a Web Developer by Profession, Game Developer by Choice.
Connect with him on:
    Blogger
    Facebook

8 comments:

  1. With the Script "PowerupScript" and "ObstacleScript" done like you said

    The Bananas will not move, well at least in my project, i know that dont make sense, can you help me?

    ReplyDelete
    Replies
    1. That should work alright. I'm not sure why it ain't working for you. Are you getting any errors?

      Delete
    2. No, i dont get any error, what happens is that in game and in the pause mode all the "obstacle" and "powerups" they just dont move at all

      Sorry about my english.

      Delete
    3. Try the 3rd case of the post instead of the first case...read post again n update the scripts

      Delete
  2. Where are all the codes. As the project discount.

    ReplyDelete
  3. when click on resume after pausing the game, one more menu displayed which we priviously created without GUIskin...hence again we required to resume....please tell me what can i do...and sorry about my English..

    ReplyDelete
  4. hi SUJIT HORAKERI...im new in unity i just followed your tutorial for running game....but i have a little problem ... unlike subway surf ...character is just moving left and right... but i want to switch lane .....could you plz help me ..in switching lane smoothly on touch input......
    waiting for your response...
    thanx in advance

    ReplyDelete