Issue with using ESC to open and close a button/window

Ok I have been working on this for a few hours now. I have played around with my code and got the GUI window and the Yes button to not show while I play game. Is this the best code setup for what I am trying to do? Will the window and button always be there taking up cpu with this code set up?

using UnityEngine;
using System.Collections;

public class ExitGame : MonoBehaviour {

	 // this is the window for the exit yes button

	public bool ExitGameWindow = false;

	// This is the Exit Yes button 

	public bool ButtonYes = false;




	
	// Use this for initialization
	void Start () {

		Screen.showCursor = false;
	}
	
	// Update is called once per frame
	void Update () {


		// This will show the mouse cursor when you hit Escape key and open the ExitGameWindow.

		if (Input.GetKey (KeyCode.Escape)) {
			ExitGameWindow = true;
			ButtonYes = true;
			Screen.showCursor = true;
				}
	}



	// Void OnGUI() is the function for your Graphic user Interface (GUI)
	void OnGUI() {
		
		// Make a backgroud for the button.
		// This type of code will never allow the box with the buttons in it to change postion on screen no matter what screen size.
		// As of now the if(ExitGameWindow) makes it so when you start game this window does not show.


		if (ExitGameWindow) {

						GUI.Box (new Rect (Screen.width / 2 - 150, Screen.height / 2 - 150, 300, 200), "Exit To Main Menu?"); 
				}

		
		// Make a button that can be clicked on.
		// Debug.Log() creates text in your console.
		// Application.LoadLevel(); Takes you to what ever scene that you tell it to. scene number goes in () after LoadLevel.
		// if(ButtonYes) This will make it to where the yes button will not show when game is played.
		
		if (ButtonYes) {

			if (GUI.Button (new Rect (Screen.width / 2 -70, Screen.height / 2 -120, 150, 50), "Yes")) 
		
		
			// Takes you back to the Main Menu.
			Application.LoadLevel(0);
			Debug.Log ("Going Back To Main Menu");

		}
		
		
		
	}
}

Next thing I want to learn how to do is when this code happens I want the player to not move when I try and click the button that shows up and I want the game to pause. These two functions might do the same, but I have not started reading the Time.timescale scripts yet.

A few suggestions:

    using UnityEngine;
    using System.Collections;
     
    public class ExitGame : MonoBehaviour {
     
         // this is the window for the exit yes button
        public bool ExitGameWindow = false;
     
        // XXX(remove)XXX This is the Exit Yes button
        // XXX(remove)XXX public bool ButtonYes = false;
     
       
        // Use this for initialization
        void Start () {
            Screen.showCursor = false;
        }
       
        // Update is called once per frame
        void Update () {
     
            // This will show the mouse cursor when you hit Escape key and open the ExitGameWindow.
     
            if (Input.GetKeyDown(KeyCode.Escape)) { // <--- Use GetKeyDown.
                ExitGameWindow = !ExitGameWindow;
                // XXX(remove)XXX ButtonYes = true;
                Screen.showCursor = ExitGameWindow;
                Time.timeScale = ExitGameWindow ? 0 : 1;
            }
        }
     
     
        // Void OnGUI() is the function for your Graphic user Interface (GUI)
        void OnGUI() {
           
            // Make a backgroud for the button.
            // This type of code will never allow the box with the buttons in it to change postion on screen no matter what screen size.
            // As of now the if(ExitGameWindow) makes it so when you start game this window does not show.
     
     
            if (ExitGameWindow) {
     
                GUI.Box (new Rect (Screen.width / 2 - 150, Screen.height / 2 - 150, 300, 200), "Exit To Main Menu?");

                // Inside the window, make a button that can be clicked on.
                // Debug.Log() creates text in your console.
                // Application.LoadLevel(); Takes you to what ever scene that you tell it to. scene number goes in () after LoadLevel.
                // XXX(remove)XXX if(ButtonYes) This will make it to where the yes button will not show when game is played.
           
                if (GUI.Button (new Rect (Screen.width / 2 -70, Screen.height / 2 -120, 150, 50), "Yes")) {
           
                    // Takes you back to the Main Menu.
                    ExitGameWindow = false;
                    Time.timeScale = 1;
                    Application.LoadLevel(0);
                    Debug.Log ("Going Back To Main Menu");
     
            }
        }
    }
  • Use Input.GetKeyDown(), not Input.GetKey(). GetKeyDown() is only true when the player first presses Escape. GetKey() is down every single frame that Escape is held down.
  • In Update(), the changes above allow you to toggle the menu on and off by pressing the Escape key again.
  • Setting Time.timeScale to zero is a good way to pause the game. In Update(), the code sets timeScale to 0 if the exit window is up and 1 if the exit window is hidden.
  • You don’t need ButtonYes. Just nest the button inside the if (ExitGameWindow) {…} block.
  • When you click the “Yes” button, it closes the window and sets timeScale back to 1.
  • Since you’re only drawing the window if ExitGameMenu is true, it won’t take up much CPU time at other times. It will take a little, however, since even an empty call to OnGUI() has a little overhead.
using UnityEngine;
using System.Collections;

public class ExitGame : MonoBehaviour {

	//This is the Variable for the ExitGameWindow.

	public bool ExitGameWindow = false;


	//This defines a Variable for the MouseLook Script on the player.
	MouseLook  playerLook;

	//This defines a Variable for the MouseLook Script on the playerCamera.
	MouseLook playerCameraLook;




	
	// Use this for initialization
	void Start () {

		//This will make it to where the mouse cursor will not show on start of game scene.

		Screen.showCursor = false;

		//This finds the MouseLook script and the First Person Controller for the player.

		playerLook = (MouseLook)GameObject.Find ("First Person Controller").GetComponent ("MouseLook");

		//This finds the MouseLook script and the First Person Controller for the playerCamera.

		playerCameraLook = (MouseLook)GameObject.Find ("Main Camera").GetComponent ("MouseLook");
	}
	
	// Update is called once per frame
	void Update () {


		//This will show the mouse cursor when you hit Escape key and open the ExitGameWindow and the Yes Button.

		if (Input.GetKeyDown (KeyCode.Escape)) { //Hit ESC to Open Window
			ExitGameWindow = !ExitGameWindow; //This code toggles the ExitGameWindow on/off
			Screen.showCursor = !ExitGameWindow; //This code allows the mouse cursor to show up while the exit window is up.
			Time.timeScale = ExitGameWindow ? 0 : 1; //This code sets timeScale to 0 if the exit window is up and 1 if the exit window is hidden.
			playerLook.enabled = !playerLook.enabled; //This code makes it to where if you move the mouse nothing happens.
			playerCameraLook.enabled = !playerCameraLook.enabled; //This code makes it to where if you move the mouse nothing happens.
				}

	}



	// Void OnGUI() is the function for your Graphic user Interface (GUI)
	void OnGUI() {
		
		// Make a backgroud for the button.
		// This type of code will never allow the box with the buttons in it to change postion on screen no matter what screen size.
		// As of now the if(ExitGameWindow) makes it so when you start game this window does not show.


		if (ExitGameWindow) { 

						GUI.Box (new Rect (Screen.width / 2 - 150, Screen.height / 2 - 150, 300, 200), "Exit To Main Menu?"); //Creates the Main Menu Box.
				}

		
		// Make a button that can be clicked on.

			if (GUI.Button (new Rect (Screen.width / 2 - 70, Screen.height / 2 - 120, 150, 50), "Yes")) { //Creates my Yes Button in the Window.

			ExitGameWindow = false; //Closes the ExitGameWindow.
			Time.timeScale = 1; //Un pause the game
			Application.LoadLevel (0); //Takes you back to Main Menu
			Debug.Log ("Going Back To Main Menu"); //Types msg out in the console.
				}

		
		
		
	}
}

I have added in your suggestions and also added more code in.

Issue # 1: the Yes button is always active on the Screen. I Know it cause I had taken out the var ButtonYes.
You made this comment: “You don’t need ButtonYes. Just nest the button inside the if (ExitGameWindow) {…} block”. I think your saying I need to combine the two somehow, correct?

Fixed** I just was not reading you right. I went ahead and nested the Yes button in side the if{ExitGameWindow) {} code blocks lol Thanks for your suggestions!

Issue # 2: My mouse is not active on screen after hitting esc.
Fixed** Changed Screen.showCursor = !ExitGameWindow; to Screen.showCursor = ExitGameWindow;

Also I have made heavy comments on my code. Please read through it and tell me if it all makes since to someone who did not write it.

It’s coming along!

Issue #1: Yes, combine the two by moving the “}” from line 66 above to line 78.

Issue #2: Line 45 above should be Screen.showCursor = ExitGameWindow; (No “!”. Was there a reason why you added it?)

On lines 30 and 34, I suggest using the typed version of GetComponent:

playerLook = GameObject.Find(“First Person Controller”).GetComponent();

Better yet, always check for null. What if GameObject.Find() doesn’t find the object?

GameObject player = GameObject.Find(“First Person Controller”);
playerLook = (player != null) ? player.GetComponent() : null;

Change lines 47-48 to:

playerLook.enabled = !ExitGameWindow;
playerCameraLook.enabled = !ExitGameWindow;

This will ensure that they’re always in sync with the state of the exit window.

(Pardon my omission of [code … /code] tags. I don’t want it to add line numbers that might be confusing.)

Issue # 2 It was a error on my part that I did not catch till after I posted that.

On lines 30 and 34, I have to research this as I have only been studying C# for about 3 weeks. I understand what you said. If the game object is not found there would be a issue and the code would not work. But the way you wrote I need to understand it in code terms. I don’t like to just copy and paste code without understanding it first.

Change lines 47-48 to: I understand this and will change that as it goes with the rest of the code and it makes sense.

My next task is to combine my 3 different scrips for each scene to 1 big one. IE Options, Credits, Main Menu.

Thanks a ton, I have learned quite a bit today.

Happy to help!

using UnityEngine;
using System.Collections;

public class GUI_Menu : MonoBehaviour {

	//Variable Start

	public GUISkin customSkin;
	private string CurrentMenu;
	public float gSliderValue = 0.0f;
	public float mSliderValue = 0.0f;





	//Variable End

	// Use this for initialization
	void Start () 
	{
		CurrentMenu = "MainMenu";

		Screen.showCursor = true;
	
	}
	
	// Update is called once per frame
	void Update () 
	{
	
	}

	void ToMenu(string menu) 
	{
		CurrentMenu = menu;
	}

	void Awake() 
	{
		DontDestroyOnLoad (transform.gameObject);
	}


	void OnGUI() 
	{
		GUI.skin = customSkin;

		if (CurrentMenu == "MainMenu")
						MainMenu ();
		if (CurrentMenu == "Options")
						Options ();
		if (CurrentMenu == "Credits")
						Credits ();
		//if (CurrentMenu == "GraphOptions")
						//GraphOptions ();

	}
	private void MainMenu() 
	{
		GUI.Box (new Rect(Screen.width / 2 -50, Screen.height / 2 -200, 100, 200), "Main Menu"); 

		if (GUI.Button (new Rect (Screen.width / 2 - 40, Screen.height / 2 - 170, 80, 20), "New Game")) 
		{
			Debug.Log ("Loading New Game");
			Application.LoadLevel (1);
		}

		if (GUI.Button (new Rect (Screen.width / 2 -40, Screen.height /2 -150, 80, 20), "Options")) 
		{
			Debug.Log ("Options");
			ToMenu("Options");
		
		}

		if (GUI.Button (new Rect (Screen.width / 2 -40, Screen.height /2 -130, 80, 20), "Credits")) 
		{
			Debug.Log ("Credits");
			ToMenu("Credits");
		}

		if (GUI.Button (new Rect (Screen.width / 2 -40, Screen.height /2 -110, 80, 20), "Exit")) 
		{
			Debug.Log ("Exit");
			Application.Quit();
		}


	}

	private void Options() 
	{
		GUI.Box (new Rect(Screen.width / 2 -150, Screen.height / 2 -150, 300, 200), "Options Menu");

		if (GUI.Button (new Rect (Screen.width / 2 -150, Screen.height / 2 -150, 80, 40), "Go Back")) 
		{
			Application.LoadLevel(0);
			Debug.Log ("Going Back To Main Menu");
		}

		GUI.Box (new Rect (Screen.width / 2 + 75, Screen.height / 2 - 100, 60, 20), gSliderValue.ToString ());
		gSliderValue = GUI.HorizontalSlider(new Rect(Screen.width / 2 -50, Screen.height / 2 -95, 100, 30), gSliderValue, 0.0F, 10.0F);

		if (GUI.Button (new Rect (Screen.width / 2 - 145, Screen.height / 2 - 100, 90, 20), "Game Sound")) 
		{
			
		}

		GUI.Box (new Rect (Screen.width / 2 + 75, Screen.height / 2 - 55, 60, 20), mSliderValue.ToString ());
		mSliderValue = GUI.HorizontalSlider(new Rect(Screen.width / 2 -50, Screen.height / 2 -50, 100, 30), mSliderValue, 0.0F, 10.0F);

		if (GUI.Button (new Rect (Screen.width / 2 - 145, Screen.height / 2 - 55, 90, 20), "Music Sound")) 
		{
			
		}


	}

	private void Credits() 
	{
		GUI.Box (new Rect(Screen.width / 2 -150, Screen.height / 2 -150, 300, 200), "Credits");

		if (GUI.Button (new Rect (Screen.width / 2 -150, Screen.height / 2 -150, 80, 40), "Go Back")) 
		{
			Application.LoadLevel(0);
			Debug.Log ("Going Back To Main Menu");
		}

		GUI.Label(new Rect(Screen.width / 2 -140, Screen.height / 2 -100, 100, 20),"MegaTarre Dev");

	}



}

When I change menus they start to over lap when I try to go back to the previous menu.

I think it has to do with DontDestroyOnLoad (transform.gameObject); I may be missing something. I like to figure it out myself but a hint would be nice :slight_smile:

This maybe

** If the object is a component or game object then its entire transform hierarchy will not be destroyed either.**

Thanks!

You’re right. Since it’s set to DontDestroyOnLoad, you’ll just keep accumulating more copies of it. You don’t need to reload the level. Just call ToMenu(“MainMenu”). For example:

    private void Options() 
    {
        GUI.Box (new Rect(Screen.width / 2 -150, Screen.height / 2 -150, 300, 200), "Options Menu");

        if (GUI.Button (new Rect (Screen.width / 2 -150, Screen.height / 2 -150, 80, 40), "Go Back")) 
        {
            ToMenu("MainMenu");
            Debug.Log ("Going Back To Main Menu");
        }
    ...

Also, read up on enum. Strings are dangerous because it’s easy to have a typo. Enums are safer. For example:

using UnityEngine;
using System.Collections;

public class GUI_Menu : MonoBehaviour {

    //Variable Start

    public GUISkin customSkin;
    public float gSliderValue = 0.0f;
    public float mSliderValue = 0.0f;

    private enum Menus { Main, Options, Credits }  // <--- !!! USING ENUM INSTEAD OF STRING !!!
    private Menus currentMenu = Menus.Main;
 
    //Variable End

     // Use this for initialization

    void Start () 
   {
        // Don't need this since we initialized it above:
        // --- CurrentMenu = "MainMenu";

        Screen.showCursor = true;
    }

    // Update is called once per frame

    ...

    void ToMenu(Menus menu)
    {
        currentMenu = menu;
    }

    ...

    void OnGUI() 
    {
        GUI.skin = customSkin;
        switch (currentMenu) {
            case Menus.Main:
                MainMenu();
                break;
            case Menus.Options:
                Options();
                break;
            case Menus.Options:
                Credits();
                break;
        }
    }
...

Yep I thought I needed to add DontDestroyOnLoad (transform.gameObject); but I was wrong. I deleted that 1 line of code and it works perfect now.

I feel like every time I write a lot of code, there always a better way to do it. I just taught myself the string way lol. I guess I will look up ENUM now.

thanks.

Ok a new possible issue has come up. I have a logo on my Main menu scene. My options credits etc… don’t have this logo. But with the above code when I click a button that logo stays there. It’s like it deleting the draw calls and just drawing the GUI for the scene I click on in the same scene. IE Options etc… This has me thinking my code is not working right.

PS: I am still using the String setup.

If I use Application.LoadLevel (1); It changes scenes but no gui shows up.

It’ll help to trace through it in your head (or on paper) first to identify what’s going to happen at each step.

Application.LoadLevel() destroys all the objects in the current scene and loads the objects in the new scene. The exception is if you’ve marked an object with DontDestroyOnLoad; these objects will not be destroyed when you load a new scene.

So if you mark your menu script object DontDestroyOnLoad and reload that same level, you’ll get two copies of the object. So never reload that level. Or, alternatively, use the singleton pattern.

You can take another approach by putting each menu in its own level and not marking them DontDestroyOnLoad. In this case, just load each level to show its menu.

using UnityEngine;
using System.Collections;

public class GUI_Menu : MonoBehaviour {

	//Variable Start

	public GUISkin customSkin;
	private string CurrentMenu;
	public float gSliderValue = 0.0f;
	public float mSliderValue = 0.0f;

	//Variable End

	// Use this for initialization
	void Start () 
	{
		CurrentMenu = "MainMenu";

		Screen.showCursor = true;
	
	}
	
	// Update is called once per frame
	void Update () 
	{
	
	}

	void ToMenu(string menu) 
	{
		CurrentMenu = menu;
	}

	void Awake() 
	{


	}


	void OnGUI() 
	{
		GUI.skin = customSkin;

		if (CurrentMenu == "MainMenu")
						MainMenu ();
		if (CurrentMenu == "Options")
						Options ();
		if (CurrentMenu == "Credits")
						Credits ();
		if (CurrentMenu == "GraphOptions")
						GraphOptions ();
		if (CurrentMenu == "LoadGameMenu")
						LoadGameMenu ();

	}
	private void MainMenu() 
	{
		GUI.Box (new Rect(Screen.width / 2 -50, Screen.height / 2 -200, 100, 200), "Main Menu"); 

		if (GUI.Button (new Rect (Screen.width / 2 - 40, Screen.height / 2 - 170, 80, 20), "New Game")) 
		{
			Debug.Log ("Loading New Game");
			Application.LoadLevel (1);
		}

		if (GUI.Button (new Rect (Screen.width / 2 - 40, Screen.height / 2 - 150, 80, 20), "Load Game")) 
		{
			Debug.Log("Loading Game");
			ToMenu("LoadGameMenu");
			

		}

		if (GUI.Button (new Rect (Screen.width / 2 -40, Screen.height /2 -130, 80, 20), "Options")) 
		{
			Debug.Log ("Options");
			ToMenu("Options");
		
		}

		if (GUI.Button (new Rect (Screen.width / 2 -40, Screen.height /2 -110, 80, 20), "Credits")) 
		{
			Debug.Log ("Credits");
			ToMenu("Credits");
		}

		if (GUI.Button (new Rect (Screen.width / 2 -40, Screen.height /2 -90, 80, 20), "Exit")) 
		{
			Debug.Log ("Exit");
			Application.Quit();
		}


	}

	private void LoadGameMenu() 
	{
		GUI.Box (new Rect(Screen.width / 2 -150, Screen.height / 2 -150, 300, 200), "Saves");
	}

	private void Options() 
	{
		GUI.Box (new Rect(Screen.width / 2 -150, Screen.height / 2 -150, 300, 200), "Options Menu");

		if (GUI.Button (new Rect (Screen.width / 2 -150, Screen.height / 2 -150, 80, 40), "Go Back")) 
		{
			ToMenu("MainMenu");
			Debug.Log ("Going Back To Main Menu");
		}

		GUI.Box (new Rect (Screen.width / 2 + 75, Screen.height / 2 - 100, 60, 20), gSliderValue.ToString ());
		gSliderValue = GUI.HorizontalSlider(new Rect(Screen.width / 2 -50, Screen.height / 2 -95, 100, 30), gSliderValue, 0.0F, 10.0F);

		if (GUI.Button (new Rect (Screen.width / 2 - 145, Screen.height / 2 - 100, 90, 20), "Game Sound")) 
		{
			
		}

		GUI.Box (new Rect (Screen.width / 2 + 75, Screen.height / 2 - 55, 60, 20), mSliderValue.ToString ());
		mSliderValue = GUI.HorizontalSlider(new Rect(Screen.width / 2 -50, Screen.height / 2 -50, 100, 30), mSliderValue, 0.0F, 10.0F);

		if (GUI.Button (new Rect (Screen.width / 2 - 145, Screen.height / 2 - 55, 90, 20), "Music Sound")) 
		{
			
		}


	}

	private void GraphOptions() 
	{
	}

	private void Credits() 
	{
		GUI.Box (new Rect(Screen.width / 2 -150, Screen.height / 2 -150, 300, 200), "Credits");

		if (GUI.Button (new Rect (Screen.width / 2 -150, Screen.height / 2 -150, 80, 40), "Go Back")) 
		{
			ToMenu("MainMenu");
			Debug.Log ("Going Back To Main Menu");
		}

		GUI.Label(new Rect(Screen.width / 2 -140, Screen.height / 2 -100, 100, 20),"MegaTarre Dev");

	}



}

With the code that I have everything is done in just 1 scene correct? I am not loading a new scene. Every time options, credits, etc… is clicked it just deletes what GUI is there and draws the GUI code that is attached to that button. I think this is the reason why my Logo that is a GUI texture atm and my GUI text is showing up not matter what button is clicked. I think I need to add code to make it only show up when the main menu GUI code is called. Please correct me if I am wrong. Also is it ok if I do it this way? Later when I added functions to the options. GUI will I be able to save what options is changed if I keep going the way I am?

Yes, it’s okay to do it that way, and you’ll be able to save options. To show the logo only in the main menu, use GUI.DrawTexture() instead of a GUI texture. Put the GUI.DrawTexture() call in your MainMenu() method.

If this script gets too big or complicated, you could redesign it with one scene per menu. When you load the Credits scene, it shows only the Credits menu. If you click Main Menu in the Credits scene, is loads the Main Menu scene, which shows only the Main Menu. You’ll have more scenes this way, but the script attached to each scene is much smaller.

Yep I went ahead and just added the code for the texture It now only shows up in the MainMenu method. Thank alot for all the help,

Happy to help!