Customizable Navigation Bar

Saturday, February 19, 2011

Creating A Game In Unity Part 1: Main Menu

I'm starting an ongoing series about creating games in Unity3D. I will be doing the same for Ogre3D and Unreal, but they will not be happening for a little while. I just need a bit more time to get something prepared.

The first thing that I am going to talk about is the main menu, only because it is by far the easiest thing to start with in Unity. I have two different ways of doing a main menu that I am going to show you:
    -A 3D menu
    -A menu using delegates in C#
Along with the text tutorial there is a video to go along with it that will take you through each method step by step. Now the text tutorial is not as in depth as the video, as I can only do so much with words, so I highly recommend you check out the video.

Also, follow me on twitter at http://twitter.com/#!/purdyjo!




Check out a larger version of this video at http://www.youtube.com/watch?v=PbNGc_uGfRk&list=UU4ZoaV57lCuuzf5-MxAxmCg&index=4&feature=plcp


The first way to create a menu will be with Unity's 3D text mesh. This is by far the easiest way to get a menu up and running.

Basically to start, create a text mesh in GameObject/Create Other/3D Text, and change the text from "Hello World" to "Start Game". Also add a box collider to it; we need this box collider to make our script function properly. Once you get everything set up, duplicate the Start Game and move it downwards a few units. Change the text to "Quit Game". Now position these objects so that they are in front of the camera in a manner that you desire.

Create a new C# script, call it MenuObject and add the following code to it:


using UnityEngine;
using System.Collections;

//extend MonoBehaviour so that we can attach this script to an object
public class MenuObject: MonoBehaviour 
{
        //A public bool so that we can change in the editor whether or not the button will quit the application
        public bool isQuit = false;

        //For the next three functions, the collider is absolutely necessary
        //these functions will not fire off if there is no collider


        //Fires off when the mouse hovers over the collider
        //When the mouse is over the item, change the colour of it to 
        //red so that the player knows that it is interacting with it
        void OnMouseEnter()
        {
                renderer.material.color = Color.red;
        }

        //Fires off when the mouse leaves the object
        //We want to change the colour of the object back to it's original when the mouse 
        //is no longer over it so that is exactly what we do here
        void OnMouseExit()
        {
                renderer.material.color = Color.white;
        }


        //Fires off when the mouse is clicked while hovering over the object
        //Here we check if the bool was set to true or not and we load the level id not
        //or quit the application if true
        void OnMouseDown()
        {
                if(isQuit)
                {
                        Application.Quit();
                }
                else
                {
                        Application.LoadLevel(1);
                }
        }
}


Now just attach the scripts to the object, and make sure you set the isQuit to true on the quit game object. Once this is working, you need to go into the build settings and set the levels up so that they can be loaded properly. Also make sure that the main menu level is before the other levels. This seems obvious, but, you never know. Also, if the level you are loading is not 1 in the build settings, make sure that you change it to whatever it is that you need it to be, you can even change it to a string value that is the name of the actual level if you want to.

If these instructions were missing pieces, or something confused you check out the video at the end of this post, it should clear things up.


The next way of creating a main menu is through delegates in C#. It is very easy, and the code is fairly clean also, so you don't have to worry about it being a jumbled mess.

Basically to get started, create a C# script called DelegateMenu and attach it to the main camera. There is no real set up to this scene unless you are adding some sort of background texture etc. just make sure the build settings are correct before you try and test it. The code that goes inside DelegateMenu.cs is :



using UnityEngine;
using System.Collections;

public class DelegateMenu : MonoBehaviour 
{
        //we have to declare a delegate so that we can use it in the OnGUI function
        private delegate void MenuDelegate();

        //in order to use a delegate we need to create a variable of MenuDelegate type so that it can be used throughout the code.
        private MenuDelegate menuFunction;

        //these variables are only here because it is cheaper to access a value from memory instead of through a static class
        private float screenHeight;
        private float screenWidth;
        private float buttonHeight;
        private float buttonWidth;

        // Use this for initialization
        void Start ()
        {
                screenHeight = Screen.height;
                screenWidth = Screen.width;

                buttonHeight = screenHeight * 0.3f;
                buttonWidth = screenWidth * 0.4f;

                //here we set the menuFunction to point to the anyKey function, which is further down in the code
                menuFunction = anyKey;
        }

        void OnGUI()
        {
        //in order to use a delegate we just call it like a function. Simple!
                menuFunction();
        }

        //in order to change the GUI we just change the function that menuFunction points to. It will basically take care of itself from that point.
        void anyKey()
        {
                //check if the user pressed anything, if it did, change the menuFunction to show the main menu
                if(Input.anyKey)
                {
                        menuFunction = mainMenu;
                }

                //this is just text in the center of the screen telling the user to press any key
                GUI.skin.label.alignment = TextAnchor.MiddleCenter;
                GUI.Label(new Rect(screenWidth * 0.45f, screenHeight * 0.45f, screenWidth * 0.1f, screenHeight * 0.1f), "Press any key to continue");
        }

        //mainMenu only has two buttons in the version, one to play the game, and one to quit the game
        void mainMenu()
        {
                if(GUI.Button(new Rect((screenWidth - buttonWidth) * 0.5f, screenHeight * 0.1f, buttonWidth, buttonHeight), "Start Game"))
                {
                        Application.LoadLevel("Level1");
                }

                if(GUI.Button(new Rect((screenWidth - buttonWidth) * 0.5f, screenHeight * 0.5f, buttonWidth, buttonHeight), "Quit Game"))
                {
                        Application.Quit();
                }
        }
}