Learning GUI Menus in Unity

Finally, it’s time to add a GUI to your unity game! We’ll go over the Unity GUI system, how to load different levels, more script connections, and the super useful “PlayerPrefs” which allows you to store game info between games. If that’s not enough, you will even learn how to control time- check it out!

What is covered in this video tutorial

  • Unity GUI Buttons
  • Unity GUI “States”
  • Stopping and Starting Time
  • Storing and retrieving variables in PlayerPrefs
Lunar Lander<>

You must be logged in to upload images. Register

Discussion

43 Responses to “Lunar Lander 05: GUI Menus”
  1. Posts: 1

    Just wanted to say, great videos, I’m really learning a great deal!

    Thanks for putting this all together Gabriel :D

    #
    1
    Mar 30, 2012 at 1:45 pm
  2. Posts: 32

    Why is the video about 6 minutes longer at the end from when you signed off?

    #
    2
    Mar 30, 2012 at 2:14 pm
    • Posts: 268

      Oops, thats just a mistake on my part. Use the extra time to relax to the soothing sounds of…whatever is going on around you at the moment ;)

      #
      2.1
      Mar 30, 2012 at 8:39 pm
  3. Posts: 35

    Gabriel, as usual another great and interesting tutorial – and as usual I learned something – in this case the “saving” through “PlayerPrefs”. I am bothered though that it might be saving to the registry on a PC. Play a lot of games like this and the registry might get a little bloated as I gather the “PlayerPrefs” data/file can be as large as 1MB. Any way of clearing them out?

    Two other minor comments.

    1. In the past when in a script checking mode using “Input.GetKeyDown” and getting a message printed out, I found it resulted in multiple messages. However when I use “Input.GetKeyUp”, I got only one message. Is that because of being too hamfisted with my keyboard, or is one cleaner than the other?

    If instead of printing messages it was calling another function would that mean the function got called multiple times ?

    2. You define a variable “guiMode” as a string and use it as a system status variable. Now, as far as I can count it can have at least four values (“win, lose, ingame, paused”) so you cannot use a boolean. So, in a number of situations you are using “if” statements with string comparisons to check the value of “guiMode”. It is my understanding that such comparisons are not the most efficient, so could you not use integer values 0-3 and define the meaning for yourself in a remark statement at the top of the script? (This would also eliminate spelling problems ;-) )

    Although I have not been through the whole script, it might also be possible to use two booleans – guiMode(ingame, paused) and gameStatus (win, lose) for example. It might only be a small gain, but remember, you started me on looking for efficiences ;-)

    Great stuff – always gets me thinking!

    gryff :)

    #
    3
    Mar 30, 2012 at 8:06 pm
    • Tenkei
      Posts: 5

      You sure you are using Input.GetKeyDown and not Input.GetKey?

      #
      3.1
      Mar 30, 2012 at 8:28 pm
      • Posts: 268

        Hi Gryffdd-

        You can find the Registry directory it saves to here:
        http://unity3d.com/support/documentation/ScriptReference/PlayerPrefs.html, plus other useful info :)

        I’m not sure why “GetKeyDown” would give you multiple messages. The difference is, GetKeyDown is called when the key goes down, GetKeyUp is called when it comes back up, and GetKey is called every single frame that the key is down.

        For “guiMode”, yes, you caught me being a little lazy ;) However, using the Profiler in Unity Pro, I can say for certain the difference is pretty much zilch, at least on such a small scale as this game. For me, it’s more important that I can remember what the heck value I’m setting, and be able to keep track of the guiMode easily. If I were to use an integer system or a case switcher, etc, I would lose track fairly soon, and (again, in this situation) not see any discernible difference in performance.

        Using two variables could open some nasty can-o-worms- because then you have 8 intermingled cases (2^2), vs 4 distinct ones.

        You are totally correct to be looking up these things, don’t get me wrong! Efficiency is a big deal, and important to get right. But at times, I find it works out better to make “human readable” code than machine-readable, just for the savings in time/frustration/messups. But that’s totally subjective, for others with properly function short term memory, I’m sure it’s different ;)

        Thanks for the in-depth questions!

        #
        Mar 30, 2012 at 8:51 pm
  4. Posts: 35

    I won’t reply directly to Gabriel and Tenkei’s replies to me – the columns are getting a bit narrow!!!

    However, I will start a new comment on the “Input.GetKeyDown” issue.

    Go to 14.10 of the tutorial – Gabriel has hit the “esc” key. Note there are *3* printings of “pause game”. This was what triggered my memories of past experiences.

    Now I am a two-fingered typist – hunt and peck – long hard down and probably quick off the key. Also the keyboard is a wireless KB that has a few driver problems (no company names ;-) ). So is it me, the KB or is “GetKeyUp” a better option?

    And what happens if there are multiple calls because of that “GetKeyDown” – any kind of incrementing of a variable might produce odd effects ;-)

    I always use “GetKeyUp” now – as you probably gather ;-)

    gryff :)

    #
    4
    Mar 30, 2012 at 11:39 pm
    • Posts: 8

      GetButtonDown() might be a better option. This is definitely only called once; even if you hold down the button, whatever code you have to be executed will do so once. ;)

      #
      4.1
      Mar 31, 2012 at 8:24 pm
    • Posts: 268

      I think the reason there are 3 prints, is because I had hit the key 3 times, actually. GetKeyDown should, technically speaking, always register just once. The only issue with “GetKeyUp” is that it will wait until the key has returned to register, which can be a problem in some cases.

      Really, it’s odd that GKD is giving you multiple hits…maybe it is a funky keyboard? Strange indeed.

      #
      4.2
      Apr 1, 2012 at 2:37 am
      • Posts: 6

        hi Gabriel,

        great tutorial :) Just a few remarks:

        at 17:39 i think it should work if you just put Time.timeScale into OnDestroy(), that way you wont forget it if you extend your if-else/switch-case tree :)

        not sure if you solve that problem later in the vid, but you can apply a force to the ship while in pause-mode

        at 21:42 not sure if you can do that in javaScript, but in c# you could just add a public static int to the LandingPad-script/class and call that from the GUI-script, that way there is no searching involved at all and no extra function.

        #
        Dec 8, 2012 at 7:41 pm
  5. Posts: 32

    Gabriel,
    I noticed a problem with the LZ actiated. If I have already activated a landing pad and then hit it again it counts it twice. I am going to see if it is just me or if it is the code and will tell you when I find out.

    Great tutorial by the way I’ve learned a lot.

    #
    5
    Mar 31, 2012 at 9:03 am
    • Posts: 268

      Hi Beast-

      Ah, you caught a bug, indeed! Some things like this, I intend to leave open-ended with hints for how to make them better, but, well, this is one I didn’t intend to be that way, lol. So, until I address that directly, here’s the hint:

      In the first stage of LZ activation, simply check if it’s already activated, and if so, do nothing. :)

      #
      5.1
      Apr 1, 2012 at 2:34 am
      • Posts: 32

        yeah I was working on something like that.

        Thanks for the response though.

        #
        Apr 1, 2012 at 11:58 am
  6. Posts: 5

    Why invest in this aging, bloated, slow and featureless GUI system? Probably next Unity release GUI will be a complete new system. Didn’t make it in v3.5, in late beta it was kicked out and moved the 3.5+ release.
    But for now Asset Store has already better GUI systems. The best one is nGUI. Unfortunately not free.
    Oh well for this beginners tutorial its probably best to just use Unity GUI.

    #
    6
    Apr 1, 2012 at 1:38 am
    • Posts: 268

      That seems a bit harsh ;) The Unity GUI system has it’s caveats, but it’s a fast and easy way to set up fairly complex GUI, with nearly zero learning curve. I’m sure something better and free will come along eventually, and as you say there are definitely paid alternatives, but until then- Unity GUI is a great way to get at least function GUI controls up and running, in almost no time :)

      #
      6.1
      Apr 1, 2012 at 2:31 am
  7. Posts: 32

    Ok I fixed the problem intirley(my spelling sucks :) )here is the fix

    function OnCollisionEnter(hitinfo:Collision)// death on collision or light turn on
    {
    if(hitinfo.relativeVelocity.magnitude >=3)
    {
    Explode();
    }
    else if(hitinfo.gameObject.tag== “landingPad”)
    {

    if(landedOnAlready)
    {
    }
    else
    {
    var LandingPad : landingPad;
    LandingPad=hitinfo.gameObject.GetComponent(“landingPad”);
    LandingPad.Activate();
    landedOnAlready=true;
    }
    }
    }

    #
    7
    Apr 1, 2012 at 1:41 pm
  8. Posts: 32

    O wait i just noticed a problem that I,m working on :(

    #
    8
    Apr 1, 2012 at 1:42 pm
    • Posts: 32

      ok now it should work. I put it in the wrong script ;)

      function Activate ()
      {
      renderer.material=onMaterial;
      stationLight1.color=onColor;
      stationLight2.color=onColor;
      if(landedOnAlready)
      {
      }
      else
      {
      GUI.LZactivated();
      landedOnAlready=true;
      }
      }

      #
      8.1
      Apr 1, 2012 at 1:52 pm
      • Posts: 268

        Nice work Beast! You can simplify that a bit by using the “does not equal” comparision, which is “!”. For example:

        if(3 != 4) print(“I can do math!”)

        or you could say:

        var someCondition : boolean = false;
        if(!someCondition) print (“I’m false!”)

        This is really hand for situations like this, where instead of that first empty if clause, you could just do:

        if(!landedOnAlready) //if NOT landedOnAlready…
        {
        GUI.LZActivated();
        landedOnAlready = true;
        }

        Nice work figuring it out yourself, hopefully this tip helps too! :)

        #
        Apr 1, 2012 at 3:17 pm
  9. hyper minipot
    Posts: 1

    would it be possible to do a tut about setting up mobile controls (like touch joysticks) as unity mobile basic was free on a special offer so I thought I might give it a whirl

    #
    9
    Apr 1, 2012 at 1:53 pm
    • Posts: 268

      Hi Hyper- definitely, now that Android and iOS are free to use (hooray!), we should have some tutorials on those soon!

      Naturally, those add a whole ‘nother layer of complexity though, so make sure the basics like this tutorial are all learned up first though :)

      #
      9.1
      Apr 1, 2012 at 3:21 pm
  10. Posts: 1

    I would also recommend using GetButtonDown (or GetAxis) (“input string here”).

    GetButtonDown comes from the input manager and will allow you to have both controller and keyboard (or any other input device you set up) with a single script. It is also a lot easier to understand code that says (“Jump”) then “Space”. input manager is found in Edit : Project Properties : input.

    I have also has problems using GetKeyDown – strangely using GetKey would only register once on my keyboard unless I mashed the button. I expect that different keyboard drivers can effect that function so it might be computer specific.

    #
    10
    Apr 1, 2012 at 2:31 pm
    • Posts: 268

      GetButtonDown is great, I agree, especially since it can make code easier to read, like you said. Personally though, I like being able to directly get any button at all, without having to setup the input via the input manager. GetButtonDown requires that “Jump” is set up correctly beforehand, and also for every other input you need to use later. For me, this is just a hassle, so I stick with GetKeyDown. But that’s totally subjective, and thanks for the tip!

      About your GetKey issue- it does sound like a hardware/driver specific issue. Odd. You and gryff must be buying from the same crazy keyboard supplier, haha ;)

      #
      10.1
      Apr 1, 2012 at 3:27 pm
  11. Posts: 32

    I have a question Gabriel(again:))

    In the first tutorial you had some kind of light pole that light up when you landed on the landing pad. So how did you do that exactly?

    #
    11
    Apr 1, 2012 at 3:35 pm
    • Posts: 268

      Hi Beast, that was a just the same as the light and texture on the Landing Pad, I simply had swapped in a different texture, and turned on a light, when the Landing Pad was activated :)

      #
      11.1
      Apr 11, 2012 at 12:05 pm
      • Posts: 32

        Ty :)

        #
        Apr 11, 2012 at 2:45 pm
  12. Posts: 13

    Hey man Can you do a tutorial on shaders? I’ve been on unity for about 3 months now and I still don’t know how to write a shader and its bugging me.
    If not can you send me a link to the API page that overviews shaders because I cannot find that either.

    #
    12
    Apr 5, 2012 at 9:10 pm
    • Posts: 268

      Hi Sarkhamy- unfortunately I’m not a shader coder :( Luckily, Unity has just about everything you could possibly need, built right in, give ‘em each a try to see what they do, maybe one will fit your needs?

      #
      12.1
      Apr 11, 2012 at 12:06 pm
  13. Posts: 4

    Hello My name is Jonah and its always been my dream to make a jrpg styled game can I use the GUI to make a turn based battle system?

    #
    13
    Apr 9, 2012 at 6:39 pm
    • Posts: 268

      Hi Jonah- you could use the GUI for absolutly anything, of course :) However, there is a lot (a LOT) involved in making something so complex as an RPG- just look at how many tutorials it’s taken to make this super-simple game! My advice is to start small, learn up all the basics and then move on to the big stuff like an RPG system. There are also some really nice “starter kits” on the Asset Store, check ‘em out!

      #
      13.1
      Apr 11, 2012 at 12:08 pm
  14. Posts: 4

    As always, fantastic tutorial set. Am getting hungry for more now :-)

    As I watched the tutorial, a thought struck me about loading new levels. Assuming I have defined 3 levels, won’t the code (as currently shown in the tutorial fail) as we are using a concept such as next level = current level + 1. Surely we will try and load a level that doesn’t exist? Sounds like there is an opportunity for a game completion.

    #
    14
    Apr 22, 2012 at 9:55 pm
    • Posts: 268

      Shhh! ;) Ha, yes, you are very correct! In the “real” game that these tutorials are based on, I haven’t actually finished that part yet…ironically, making the actual game has fallen behind the tutorials/other projects.

      However, if you want to get a jump on it, it would be fairly simple to check “if(!moreLevels) –> YouWinTheWholeGame()”. At that point you could do all sorts of fun things…perhaps even “upping” the Gravity a notch and starting the player over at level 1. Of course, you’d have to reset that to standard gravity if they started a totally new game.

      Thanks for the compliments, great to hear :)

      #
      14.1
      Apr 22, 2012 at 11:41 pm
  15. Posts: 2

    A little tip to make your game run faster; On the “OnGUI()” function, multiply the screen height and screen width by 0.5 (not divide by 2). Divisions are costly and avoiding them when possible will improve your performance.

    #
    15
    May 26, 2012 at 6:49 pm
  16. Posts: 2

    When you made that variable called GUI (at 19:35 in the video) on the LandingPad script, did it need to be called GUI or is that just a name?

    #
    16
    Jun 30, 2012 at 2:42 pm
  17. Jake
    Posts: 3

    It might be because we’re up to unity 4.1, but I’m getting this error with your script now

    “The name ‘InGameGUI’ does not denote a valid type (‘not found’). ”

    It seems to me like InGameGUI was removed as a type for variables, and I have no idea how to continue.
    Any suggestions?

    Here is the full script I’m using in case I’m missing something obvious.

    #pragma strict

    var stationLight:Light;
    var onMaterial:Material;
    var onColor:Color;

    var GUI:InGameGUI;

    function Start () {
    GUI = GameObject.FindWithTag(“GUI”).GetComponent(InGameGUI);
    }

    function Update () {

    }

    function Activate () {
    renderer.material = onMaterial;
    stationLight.color = onColor;
    }

    #
    17
    Apr 25, 2013 at 3:03 pm
    • Jake
      Posts: 3

      NVM, Was missing a capital G in the script name.

      #
      17.1
      Apr 25, 2013 at 3:33 pm
  18. Posts: 2

    I am trying to run this project on Unity 4, but the yield call in Lose() is not returning. The Lose menu never comes up. I put in a print before and after the yield and I get the message “before yield” but I never get the message “after yield”.

    If I remove the Destroy() from the player controller. It works as expected. But that isn’t what I want to do because then the ship is not removed/destroyed from the scene.

    #
    18
    Apr 29, 2013 at 8:49 am
    • Jake
      Posts: 3

      I have the same issue.

      #
      18.1
      Apr 29, 2013 at 1:17 pm
      • Posts: 2

        Not sure if this is correct, but this is what I did:

        In PlayerController.js, before the Destroy(gameObject) line, I added the following:

        renderer.enabled = false;
        yield GUI.Lose();

        So my this is my final Explode function:

        function Explode()
        {
        var randomNumber : int = Random.Range(0,shipExplosions.length);
        Instantiate(shipExplosions[randomNumber], transform.position, transform.rotation);

        renderer.enabled = false;
        yield GUI.Lose();

        Destroy(gameObject);
        }

        #
        Apr 30, 2013 at 11:41 am

Leave a Comment

You must be logged in to post a comment.