Creating an RTS in Unity: Part XVI

Update: This can now also be found at, where the entire tutorial is now being hosted.

Now that we have a basic menu in place it is time to extend that a bit. As you are aware, a game does not typically just start when you open it. The standard starting point is a main menu, from which you actually launch the game. The goal this time is to create a main menu, start a game from this menu, and add the ability to return to the menu from our game.

Generic Menu

The basic layout for our MainMenu is going to be similar to that of the PauseMenu that we created last week. Our interactions with it are going to be different, but the overall structure should at least be familiar. In fact, the structure is so similar that we should actually make a base Menu class which does most of the work for us. Inside the Scripts folder located in the Menu folder create a new C# script and call it Menu.cs. Set the code to be the following.

using UnityEngine;
using System.Collections;
using RTS;

public class Menu : MonoBehaviour {

	public GUISkin mySkin;
	public Texture2D header;

	protected string[] buttons;

	protected virtual void Start () {

	protected virtual void OnGUI() {

	protected virtual void DrawMenu() {
		//default implementation for a menu consisting of a vertical list of buttons = mySkin;
		float menuHeight = GetMenuHeight();

		float groupLeft = Screen.width / 2 - ResourceManager.MenuWidth / 2;
		float groupTop = Screen.height / 2 - menuHeight / 2;
		GUI.BeginGroup(new Rect(groupLeft, groupTop, ResourceManager.MenuWidth, menuHeight));

		//background box
		GUI.Box(new Rect(0, 0, ResourceManager.MenuWidth, menuHeight), "");
		//header image
		GUI.DrawTexture(new Rect(ResourceManager.Padding, ResourceManager.Padding, ResourceManager.HeaderWidth, ResourceManager.HeaderHeight), header);

		//menu buttons
		if(buttons != null) {
			float leftPos = ResourceManager.MenuWidth / 2 - ResourceManager.ButtonWidth / 2;
			float topPos = 2 * ResourceManager.Padding + header.height;
			for(int i=0; i<buttons.Length; i++) { 				if(i > 0) topPos += ResourceManager.ButtonHeight + ResourceManager.Padding;
				if(GUI.Button(new Rect(leftPos, topPos, ResourceManager.ButtonWidth, ResourceManager.ButtonHeight), buttons[i])) {


	protected virtual void SetButtons() {
		//a child class needs to set this for buttons to appear

	protected virtual void HandleButton(string text) {
		//a child class needs to set this to handle button clicks

	protected virtual float GetMenuHeight() {
		float buttonHeight = 0;
		if(buttons != null) buttonHeight = buttons.Length * ResourceManager.ButtonHeight;
		float paddingHeight = 2 * ResourceManager.Padding;
		if(buttons != null) paddingHeight += buttons.Length * ResourceManager.Padding;
		return ResourceManager.HeaderHeight + buttonHeight + paddingHeight;

	protected void ExitGame() {

The core of this code is what we had in PauseMenu.cs last time. A couple of things have been adjusted to allow us to specify different variations easily. By default we will not specify a value for our array of buttons. A specific menu can define this array through the method SetButtons(). The check

buttons != null

is therefore needed in a number of places to make sure that we only use the buttons array if it is specified. This means that by default a menu will actually just have the header image with no buttons underneath it. By using GetMenuHeight() we can define the height of the menu based on the number of buttons that are specified, all nicely padded and looking tidy. The final method that allows variation is HandleButton(). The basic menu has no knowledge of which buttons will be present and therefore it has no idea what to do with a button when it is clicked. A specific menu can use this method to define how to handle the buttons that it has defined. We will also add the method that handles exiting the game to Menu.cs since we want to be able to call this from any menu that wants it.

Before we carry on we should tidy up our PauseMenu from last time, making sure that it extends our newly created Menu. We should also make sure that it still behaves as expected. Update PauseMenu.cs so that it now has the following code in it.

using UnityEngine;
using RTS;

public class PauseMenu : Menu {

	private Player player;

	protected override void Start () {
		player = transform.root.GetComponent();

	void Update () {
		if(Input.GetKeyDown(KeyCode.Escape)) Resume();

	protected override void SetButtons () {
		buttons = new string[] {"Resume", "Exit Game"};

	protected override void HandleButton (string text) {
		switch(text) {
			case "Resume": Resume(); break;
			case "Exit Game": ExitGame(); break;
			default: break;

	private void Resume() {
		Time.timeScale = 1.0f;
		GetComponent().enabled = false;
		if(player) player.GetComponent().enabled = true;
		Screen.showCursor = false;
		ResourceManager.MenuOpen = false;


As you can see, this is a much simpler class now. The methods SetButtons() and HandleButton() define what buttons are present and how to handle the click for each of them. Note that in Start() we need to make sure that we call base.Start() – this makes sure that any initialization specified in the base class is still performed. If you now run your project now you should see that the pause menu still behaves the same as before.

Main menu

Now that we have a base implementation of a menu in place it is time to create our main menu. The first thing we actually want to do is to create a new Scene for our game. We will use this to manage our main menu (which will get more complex over time). Create a new scene (File -> New Scene) and then save it inside the Menu folder. Next, create a new C# script inside the Scripts folder located in the Menu folder and call this MainMenu.cs. Add this script to the camera object so that we can use it shortly. Note: we could create an empty object to attach scripts to, but I do not think that is needed for this scene.

Now it is time to specify the code for our main menu. Set MainMenu.cs to contain the following code.

using UnityEngine;
using System.Collections;
using RTS;

public class MainMenu : Menu {

	protected override void SetButtons () {
		buttons = new string[] {"New Game", "Quit Game"};

	protected override void HandleButton (string text) {
		switch(text) {
			case "New Game": NewGame(); break;
			case "Quit Game": ExitGame(); break;
			default: break;

	private void NewGame() {
		ResourceManager.MenuOpen = false;
		//makes sure that the loaded level runs at normal speed
		Time.timeScale = 1.0f;

Once again we specify the buttons we want to have and how to handle the click on each of them. The only interesting code in this class is found in the NewGame() method. Here we are wanting to start a new game using the map that we have been working on for the majority of this tutorial. Unity provides us the ability to change scenes with the use of Application.LoadLevel(). However, for this to work we need to know a couple of things. First up, we need to know the name of the Scene that we want to change to. This is the parameter that gets passed in to LoadLevel(). It is all well and good knowing the name of the scene that we want to load, but the more important thing is to let Unity know all of the scenes that we have in our game. This is done through the build settings for our project (File -> Build Settings). At the top of the dialog that shows up is a list of scenes that are to be included in our build. Any of the scenes in this list can be loaded by using Application.LoadLevel(). To add a scene to this list find the appropriate scene in your Assets directory (wherever it was saved to) and drag it onto the list. The first scene in the list is the one that is loaded when Unity starts up, so we want to make sure that our MainMenu scene is listed first. Then we need to add our Map scene so that we can load it from the MainMenu. Your Build Settings should look like the screenshot below.

Build Settings

Build Settings

To make sure that the main menu is styled correctly and shows the header image we need to attach MenuSkin to the MySkin field of the MainMenu that we attached to the camera earlier. We also need to add our header to the header field.

With this done you should be able to run your game (starting in the MainMenu scene) and see a menu show up with the options “Start Game” and “Quit Game”. Clicking “Start Game” should load up the familiar map from the rest of the tutorial.

Updated Pause Menu

With this in place we actually want to change the behaviour of our pause menu slightly. At the moment when we click “Exit Game” from the pause menu we are exiting our game. What we actually want to do is to return to the main menu, rather than closing the game. To do this we need to change the case for “Exit Game” in HandleButton() to call


rather than


like it does at the moment. We then need to set the definition of ReturnToMainMenu() as follows.

private void ReturnToMainMenu() {
	Screen.showCursor = true;

This loads the MainMenu scene again and makes sure that the normal cursor is shown for the menu. Ideally, this method should prompt the player for confirmation that they wish to exit their game, along with the option to save it or not. We will add this in once we have added the ability to save games in a couple of posts. Feel free to play round with a confirm prompt if you like though.

And as simple as that we now have our game starting from a menu, the ability to start a new game using the map we have been working on, and the ability to return to the main menu from within our game. The entire project can be found on github with the code for this part under the commit for Part 16.


7 thoughts on “Creating an RTS in Unity: Part XVI

  1. Somebody Anonymous says:

    I know how it feels to create content and not get response. This is the response. On behalf of all lazy readers, too lazy to leave a comment like this i need to say. THANK YOU.


    Few dedicate their time to helping others like this and i know it may be consuming your time but we really need you.

    Please continue πŸ˜₯

    It’s been a long time since you posted. I was hoping you’d even go into networking. Please continue these.

    Please dude…

    • I haven’t stopped. However holidays have kicked in now, so it may be a while before I get the next part up. Networking is not planned at this stage sorry. I may get to it one day, but I cannot guarantee when that might be.

      • Somebody Anonymous says:

        It’s cool. If i can nail a solid Single Player experience, networking can come later.
        I have this blog bookmarked.

        Thank you.

  2. ntman1985 says:

    Thanks a lot! I don’t know how to express my thanks to you! I feel lucky to know you, read your blog, learn from you! You show a new world to me!

  3. Loller says:

    Thank you! You have taught me a lot of my fundamentals to start off my first 3D RTS.
    I have been studying 3Ds Autodesk software with Vray for a few years. Now I can implement that with your great input! You have my gratitude Sir!
    Regards ‘Loller’

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s