Chapter 7. 3D User Interface

In this chapter, you will learn how to create 3D widgets, both in the user interface and within the environment. We'll work at the following aspects:

  • The 3D score counter
  • The 3D pause button
  • The 3D pause menu with a perspective 3D effect
  • Interaction override to ensure a player cannot play while a game is paused
  • The current level name displayed in 3D on the ground
  • Lighting effects on UI elements
  • Key bindings

By the end of this chapter, you'll know how to create 3D user interfaces and integrate in-game 3D elements in the environment with lighting effects.

Introduction to 3D user interface

Until now, we've created 2D user interface elements and flat widgets viewed with an orthographic camera, on which the z axis has no influence.

3D user interface elements are viewed with perspectives taken into account, which means that the z axis makes widgets feel "farther away" or "closer to" the camera. Rotation can also be applied, which will make them look like they are a part of the 3D environment.

In this section, we will create 3D user interface elements. First, we need to explain what the 3D UI Root is, and then create one.

The 3D UI Root

It's interesting to separate our 2D and 3D layers in order to make sure you can easily hide or show one of them by simply enabling/disabling the camera that renders them.

Indeed, consider we have UI Root to hold the 2D UI and another to hold the 3D UI exclusively. If we need to hide the 2D UI and show a 3D pause menu, we can simply perform the following steps:

  1. Disable the 2D UI Root that holds and renders the in-game 2D UI.
  2. Enable the 3D UI Root that holds and renders the 3D pause menu.

Since UI Root handles widget scaling depending on the screen, we should only have one UI Root instance running in the same scene. The NGUI plugin won't let us create a new 3D UI Root within a scene that already has a 2D UI Root. This is why we need to disable the InGame2DUI root for now:

  1. Select InGame2DUI and disable it.
  2. Create a new 3D UI by navigating to NGUI | Create | 3D UI.
  3. Select a new UI Root (3D) GameObject.
  4. Rename it to InGame3DUI.
  5. For its attached UI Root component, perform the following steps:
    1. Set its Scaling Style to Constrained.
    2. Set its Content Width to 1920.
    3. Set its Content Height to 1080.
    4. Check its height Fit option.

Now, let's create a new layer to hold all 3D UI elements:

  1. Access Edit | Project Settings | Tags and Layers.
  2. Next to User Layer 10, enter 3DUI in the field.
  3. Select the InGame3DUI GameObject.
  4. Switch its layer to 3DUI.

Unity will prompt you with a popup, asking if you desire to change the layer for all child objects. Click on the Yes, change children button.

Now that we've set our InGame3DUI in the 3DUI layer, we need to make sure this layer is rendered by UICamera. Perform the following steps:

  1. Select our InGame3DUI | Camera GameObject.
  2. For the Camera component, set Culling Mask to display 3D UI only.

Now that our 3D UI Root is created and configured, we can re-enable our InGame2DUI root and make sure its culling mask hasn't been changed. We can do so by following the steps mentioned:

  1. Select the InGame2DUI GameObject and enable it.
  2. Select the InGame2DUI | Camera GameObject.
  3. For Camera, make sure Culling Mask is set to InGame2DUI.

Ok, we're now ready to display 3D widgets!

Scale calibration

What I call scale calibration for the 3D UI is the process of making sure a fullscreen 3D widget is actually taking the entire screen. We'll need to create a calibration sprite of 1920 x 1080 and see if it fits our Game view correctly:

  1. Select the InGame3DUI GameObject.
  2. Create a new child sprite with Alt + Shift +S.
  3. Set its Atlas to the SciFi atlas.
  4. Change its Sprite to the Dark sprite.
  5. Make sure its Type is set to Sliced.
  6. Set white for Color Tint.
  7. Change Size to 1920 x 1080.

We have a virtual screen of 1920 x 1080. With the current 3D UI configuration, you will notice that our 1920 x 1080 sliced sprite is much larger than the screen! This isn't good, and we need to find a way to calibrate our UI's scale.

In order to correct this, we can simply move the camera farther away from the widgets to reduce the UI's display size:

  1. Select the InGame3DUI | Camera.
  2. Set the Transform position to {0, 0, -935}.

Ok, that's better; our 1920 x 1080 sprite now fits the screen without getting out of bounds. You can now delete our calibration, Sprite, from the scene.

Your game scene's Hierarchy view should now have the elements shown in the following screenshot:

Scale calibration

For Unity 4.5 and above, the order of the elements might be different since objects aren't sorted alphabetically anymore.

Now that our UI's scale is calibrated, we can move on and create our first 3D widget.

The score counter

The first 3D widget we will create is a score counter at the top right of the screen:

The score counter

As you can see in the preceding image, our score counter has a slight 3D effect due to a y axis rotation of 20 degrees.

The text label

Let's start by creating the score counter's label:

  1. Select the InGame3DUI GameObject.
  2. Create a new empty GameObject with Alt + Shift + N.
  3. Rename this new child to Score.
  4. Create a new label with Alt + Shift + L.

Ok, we have our new label. Let's configure it now:

  1. Select our new InGame3DUI | Score | Label GameObject.
  2. Set its font type to Unity, with a Lato font.
  3. Set its Font Size to 60, with a Normal (not Bold) style.
  4. Change its Text value to 999999.
  5. Change its Overflow parameter to ResizeFreely.
  6. Set a black Shadow effect with X and Y values as 1.
  7. Change Color Tint to {R: 255, G: 255, B: 150, A: 255}.
  8. Change Pivot to Right (click on the right arrow followed by the middle bar).
  9. Set Depth to 2.

Ok, now that we have our label with its pivot set to the right side, we can add a background sprite that will wrap around it.

The background

Let's add a dark transparent background sprite to make this score counter more visible:

  1. Select our InGame3DUI | Score GameObject.
  2. Create a new sprite pressing on Alt + Shift + S.
  3. Rename this new child as Background.
  4. Change its Atlas value to the SciFi atlas.
  5. Change its Sprite value to the Dark sprite.
  6. Make sure its Type is set to Sliced.
  7. Set Depth to 0 to display behind the label.
  8. Change its Size to 235 x 80.
  9. Change Color Tint to {R: 160, G: 120, B: 30, A: 150}.

Ok, now let's configure the background's anchor to make sure it wraps around the label:

  1. Change Anchor Type to Unified.
  2. Drag our Score | Label GameObject to the Target field.

If you add or remove numbers in the score counter label, you'll see that the background adjusts itself to wrap it accordingly.

We can now add a border to this sprite to have more visible edges.

The border sprite

Let's use the background sprite as a base to create a border sprite:

  1. Select our InGame3DUI | Score | Background GameObject.
  2. Duplicate it by pressing Ctrl + D.
  3. Rename this new duplicate to Border.
  4. Change Sprite to the Highlight sprite.
  5. Uncheck the Fill Center parameter.
  6. Set Depth to 1 to display over the background.
  7. Change Color Tint to {R: 255, G: 255, B: 0, A: 255}.
  8. Drag our Score | Background to the Anchor Target field.

Great, we now have our score counter. We can now place it where it should be.

The position and rotation

Let's make sure it's anchored at the top-right corner of the screen and rotate it slightly:

  1. Select our InGame3DUI | Score GameObject.
  2. Set the Transform rotation to {0, 20, 0} to create a 3D effect.
  3. Click on the Add Component button in the inspector.
  4. Type in anc to search for components with this name.
  5. Select Anchor and hit Enter or click on it with your mouse.

Now, for the newly attached UIAnchor component of Score:

  1. Change Side to TopRight.
  2. Change its Relative Offset to {-0.09, -0.08}.

That's it; we now have our 3D score counter at the top-right corner of the screen! Now, let's see how we can make our score increase when needed.

Note

UIAnchor is a legacy component because all widgets have the built-in anchoring system. However, it's interesting to know it exists and see it can still be used to anchor objects that aren't widgets.

The ScoreController component

In order to control the score counter's behavior, we'll create a new ScoreController component that will update the score label when a player's current score is changed.

The score modification feedback must be obvious. We'll make sure it uses a simple scale animation; the score first scales up, increases its value over time, and goes back to its initial scale when it has reached its final value.

First, let's create our new ScoreController component:

  1. Select our InGame3DUI | Score GameObject.
  2. Click on the Add Component button in the Inspector.
  3. Type in ScoreController with your keyboard and hit Enter.
  4. Make sure Language is set to CSharp, and hit Enter again.
  5. Open the newly added ScoreController.cs script.

Within this new ScoreController.cs script, declare the global variables, as shown in the following snippet:

// We'll need to store the score label
private UILabel label;
// We'll need to separate the displayed score
private int previousScore;
// The private _currentScore value
private int _currentScore;

Also, add a public currentScore variable with a custom setter method in order to make sure that each time the score is changed, the previousScore value is updated and the label's text is refreshed:

// The public currentscore with custom setter
public int currentScore
{
  get
  {
    return _currentScore;
  }
  set
  {
    // Update the previous score to current score
    previousScore = _currentScore;
    // Update the private _currentScore value
    _currentScore = value;
    // Update the label with new score
    UpdateLabel();
  }
}

Now, let's make sure variables are initialized correctly at the start. Replace the default Start() method with the following snippet:

// At start
private void Start ()
{
  // Get the score counter's label
  label = GetComponentInChildren<UILabel>();
  // Set the currentScore value to 0
  currentScore = 0;
}

Now that variables are initialized correctly, we can add the UpdateLabel() method, which is called at the last line of the currentScore getter method:

// Method to update the score label
public void UpdateLabel()
{
  // Launch the coroutine to update the label
  StartCoroutine(UpdateLabelRoutine());
}

The above Updat eLabel() method starts the UpdateLabelRoutine coroutine. Let's add this coroutine, which actually updates the label:

// Coroutine that updates the label
private IEnumerator UpdateLabelRoutine()
{
  // Scale up the score label to 1.2
  UITweener tween =
    TweenScale.Begin(label.gameObject, 0.1f, Vector3.one * 1.2f);
  
  // Wait for the scale tween to finish
  yield return new WaitForSeconds(0.1f);
  
  // Calculate difference between old and new score
  int scoreDelta = currentScore - previousScore;
  
  // While previous score is below current score...
  while(previousScore < currentScore)
  {
    // ...Increase the previousScore value
    previousScore += Mathf.CeilToInt(scoreDelta * Time.deltaTime * 3.5f);
    // Set the label to the previousScore value
    label.text = previousScore.ToString();
    // Wait for next frame
    yield return null;
  }
  
  // When score has reached final score value
  // Update the score label with current score
  label.text = currentScore.ToString();
  
  // Wait a little
  yield return new WaitForSeconds(0.3f);
  // Re-scale down the score label
  TweenScale.Begin(label.gameObject, 0.1f, Vector3.one);
}

The preceding method first scales up the label, increases its value until it reaches the currentScore value, and then scales it back down again.

We can now make sure the score increases when the player brings the power source's correct element. Open the PlayerController.cs script and add this line of code in the UseElement() method just below the targetFeed.Feed() instruction:

// Increase Score
ScoreController.Instance.currentScore += 1000;

Hit Unity's play button. Your score will increase by 1,000 points each time a power feed is fed; for example, if you collect and deliver the lightning element to the lightning power feed.

Ok, great! We are now ready to start working on an in-game pause menu.

The pause button

We'll now create a 3D pause button, as shown:

The pause button

Ok, let's create this button now. We'll need a Buttons holder GameObject:

  1. Select the InGame3DUI GameObject.
  2. Create a new child by pressing Alt +Shift + N.
  3. Rename this new child to TopButtons.

Now that we have our TopButtons holder, we can create the button:

  1. In the Project view, search for button.
  2. Drag Control – Simple Button to our new TopButtons GameObject.
  3. Rename this new button to Pause.
  4. Reset the Transform position to {0, 0, 0}.
  5. In the Inspector view, click on the Add Component button.
  6. Type in sca to search for components with this name.
  7. Select Button Scale and hit the Enter key or click on it with your mouse.

For the attached UISprite component, perform the following steps:

  1. Set Size to 320 x 100.
  2. Change Pivot to Top (middle + up arrow).

For the attached UIButton component, perform the following steps:

  1. Set the Normal color to {R: 255, G: 255, B: 255, A: 255}.
  2. Set the Hover color to {R: 225, G: 200, B: 150, A: 255}.
  3. Set the Pressed color to {R: 120, G: 120, B: 120, A: 255}.

Now, select the child Label GameObject executing the following steps:

  1. Set the font type to Unity.
  2. Set Font to Arial.
  3. Set Color Tint to {R: 0, G: 0, B: 0, A: 255}.
  4. Change Font Size to 40.
  5. Change Text to Pause

Ok, our pause button is looking good. Now, we would like to add a slight 3D effect and position it at the top of the screen:

  1. Select our InGame3DUI | TopButtons GameObject.
  2. Set its Transform rotation to {-15, 0, 0} for a slight 3D effect.

The TopButtons GameObject is just a container and not a widget; we cannot assign a size or pivot to it. We can correct this by adding the UIWidget component to it:

  1. Select our InGame3DUI | TopButtons GameObject.
  2. In the Inspector view, type in widg to search for components.
  3. Select NGUI Widget and hit the Enter key or click on it with your mouse.

Our TopButtons is now considered as a widget. We can set its new UIWidget component's Size and Pivot and make sure it's placed at the top of the screen:

  1. Set its Size to 320 x 100.
  2. Change its Pivot to Top (middle + up arrow).
  3. Set the Transform position to {0, 540, 0}.

That's it; you should now have the pause button attached to the top of the screen:

The pause button

Now that we have a pause button, let's create the associated pause menu.

The pause menu

We will now create this specific in-game 3D pause menu:

The pause menu

Let's start by creating the container panel and box.

The panel and box

First, we need to create a new panel to contain the pause menu's background and border:

  1. Select the InGame3DUI GameObject.
  2. Create a new empty child GameObject by pressing Alt + Shift + N.
  3. Rename this new child to PauseMenu.
  4. Click on the Add Component button in the inspector.
  5. Type in panel to search for components with this name.
  6. Select NGUI Panel and hit Enter or click on it with your mouse.
  7. Set the Depth value of the newly attached UIPanel to 1.

We can now create the pause menu's background:

  1. Select our new InGame3DUI | PauseMenu GameObject.
  2. Create a new child sprite pressing Alt + Shift + S.
  3. Rename the new sprite to Background.
  4. Change Atlas to Wooden Atlas.
  5. Set Sprite to the Window sprite.
  6. Make sure that the sprite type is set to Sliced.
  7. Set Color Tint to {R: 255, G: 200, B: 130, A: 200}.
  8. Set Size to 1100 x 600.

Now, let's add the box's border sprite:

  1. Select our InGame3DUI | PauseMenu | Background GameObject.
  2. Duplicate it pressing Ctrl + D.
  3. Rename this new duplicate to Border.
  4. Uncheck its UISprite and the Fill Center option.
  5. Set Color Tint to {R: 255, G: 230, B: 60, A: 255}.
  6. Change the Depth value to 2.
  7. Change Anchor Type to Unified.
  8. Drag our InGame3DUI | PauseMenu | Background in the Target field.

Now that we have a nice yellow border, we can create the title bar.

The title bar

Let's create the title bar that displays the Pause label:

  1. Select our InGame3DUI | PauseMenu GameObject.
  2. Create a new empty child GameObject by pressing Alt + Shift + N.
  3. Rename this new child to Title.
  4. Select our InGame3DUI | PauseMenu | Background GameObject.
  5. Duplicate it by pressing Ctrl + D.
  6. Drag this new duplicate inside the new Title GameObject.
  7. Check the Fill Center option of UISprite.
  8. Set Color Tint to {R: 255, G: 200, B: 90, A: 255}.
  9. Set the Depth value to 1.
  10. Change Anchor Type to Unified.
  11. Drag our InGame3DUI | PauseMenu | Background in the Target field.
  12. Change the Bottom anchor field to Target's Top.
  13. Set the Bottom anchor offset to -100.

The title bar's background is set up. Now, let's add the title bar's label:

  1. Select our InGame3DUI | PauseMenu | Title GameObject.
  2. Create a new child label by pressing Alt + Shift + L.
  3. Set the Transform position to {0, 250, 0}.
  4. For the attached UILabel component, perform the following steps:
    • Change the font type to Unity.
    • Set Font to GoodDog.
    • Change Font Size to 65.
    • Change its Overflow parameter to ResizeFreely.
    • Change the label's Text to Pause.
    • Set a black Outline effect with the X and Y values as 1.
    • Set Color Tint to {R: 255, G: 200, B: 150, A: 255}.

Ok, good. You should now have a window like this with the following hierarchy:

The title bar

We can now move on to creating the two pause menu's buttons.

Buttons

In this section, we'll create the Resume and Exit 3D buttons.

Resume

We can first create the Resume button by executing the following steps:

  1. Select our InGame3DUI | PauseMenu GameObject.
  2. Create a new empty child GameObject by pressing Alt + Shift + N.
  3. Rename this new child to Buttons.
  4. Open the Prefab toolbar navigating to NGUI | Open | Prefab Toolbar.
  5. Drag the Simple button by navigating to InGame3DUI | PauseMenu | Buttons.
  6. Rename this new button to Resume.
  7. Set the Transform position to {-270, -40, 0}.

Configure the attached UISprite executing the following steps:

  1. Change Atlas to the Game atlas.
  2. Set Sprite to the Background_Button sprite.
  3. Set Size to 420 x 420.

Now, for the attached UIButton component, perform the following steps:

  1. Set the Normal color to {R: 170, G: 255, B: 160, A: 255}.
  2. Set the Hover color to {R: 100, G: 255, B: 100, A: 255}.
  3. Set the Pressed color to {R: 25, G: 75, B: 0, A: 255}.
  4. In the Inspector view, type in sca to search for components with this name.
  5. Select Button Scale and hit Enter or click on it with your mouse.

We can now configure the child label executing the following steps:

  1. Select our PauseMenu | Buttons | Resume | Label GameObject.
  2. Set the font type to Unity with the GoodDog font.
  3. Change Font Size to 60.
  4. Set Text to Resume.
  5. Set a black Outline effect with the X and Y values as 1.
  6. Set Color Tint to {R: 180, G: 255, B: 170, A: 255}.
  7. Change Depth to 6.

Now that everything is set for this button, we can create the resume sprite:

  1. Select our PauseMenu | Buttons | Resume GameObject.
  2. Create a new child sprite by pressing Alt + Shift + S.
  3. Rename this new sprite to Icon.
  4. Change Sprite to the Game atlas.
  5. Set Sprite to the Icon_Play sprite.
  6. Change Type to Simple.
  7. Set Color Tint to {R: 115, G: 240, B: 75, A: 255}.
  8. Set Depth to 5.
  9. Change Size to 380 x 380.

Great! Now that we have our Resume button, we can move on to the Exit button.

Exit

Follow these steps to create the Exit button based on the Resume button:

  1. Select our PauseMenu | Buttons | Resume GameObject.
  2. Duplicate it by pressing Ctrl + D.
  3. Rename this new duplicate button to Exit.
  4. Change the Transform position to {270, -40, 0}.
  5. Set the Normal color to {R: 255, G: 180, B: 160, A: 255}.
  6. Set the Hover color to {R: 255, G: 85, B: 85, A: 255}.
  7. Set the Pressed color to {R: 75, G: 0, B: 0, A: 255}.

We can now update the child label to red, similar to what we did in the background. Execute the following steps:

  1. Select our PauseMenu | Buttons | Exit | Label GameObject.
  2. Set Text to Exit.
  3. Set Color Tint to {R: 255, G: 210, B: 210, A: 255}.

We must now change the icon and make sure it's red too:

  1. Select our PauseMenu | Buttons | Exit | Icon GameObject.
  2. Change Sprite to Icon_Exit.
  3. Set Color Tint to {R: 255, G: 180, B: 180, A: 255}.

Good! Now, let's add a 3D effect to give the impression that our pause menu is displayed on the level's ground:

  1. Select our InGame3DUI | PauseMenu GameObject.
  2. Change the Transform rotation to {22, 0, 0}.

Great! Our pause menu is now ready. Your Game view and Hierarchy should look like this:

Exit

We can now see how to show this pause menu when required.

Displaying the pause menu

We need to display the pause menu when the pause button is pressed. Let's do this using an alpha tween to gradually change the pause menu's alpha value.

The tween alpha

Follow these steps to configure a Tween Alpha component on PauseMenu:

  1. Select our InGame3DUI | PauseMenu GameObject.
  2. Click on the Add Component button in the inspector.
  3. Type in alp to search for components with this name.
  4. Select Tween Alpha and hit Enter or click on it with your mouse.
  5. Set the From value to 0 in the newly attached Tween Alpha.
  6. Change the Duration value to 0.5.

The alpha tween is configured. We must now request it to play when necessary.

The Play Tween

We'll use Play Tween to play the alpha tween when the Pause button is clicked on:

  1. Select our InGame3DUI | TopButtons | Pause GameObject.
  2. Click on the Add Component button in the inspector.
  3. Type in play to search for components with this name.
  4. Select Play Tween and hit Enter or click on it with your mouse.
  5. Drag our InGame3DUI | PauseMenu in the Tween Target field.
  6. Set the If target is disabled field to EnableThenPlay.

The pause menu will be faded in when the pause button is clicked on. We need to make sure it fades out when the resume button is clicked on, using Play Tween again:

  1. Select our InGame3DUI | PauseMenu | Buttons | Resume GameObject.
  2. Click on the Add Component button in the inspector.
  3. Type in play to search for components with this name.
  4. Select Play Tween and hit Enter or click on it with your mouse.
  5. Drag our InGame3DUI | PauseMenu in its Tween Target field.
  6. Set the Play Direction field to Reverse.
  7. Set the When finished field to Disable After Reverse.

Good! The pause menu will now fade out and disable itself when the resume button is pressed. We can now hide the pause button when the pause menu is displayed, and display it again when the resume button is pressed. Perform the following steps:

  1. Select our InGame3DUI | TopButtons | Pause GameObject.
  2. Click on the Add Component button in the Inspector view.
  3. Type in acti to search for components with this name.
  4. Select Button Activate and hit Enter or click on it with your mouse.
  5. Drag InGame3DUI | TopButtons | Pause (itself) in the Target field.
  6. Uncheck the State option to make it disable itself upon clicking.

The Button Activate component enables or disables the state of Target, depending on the State bool's value. In the previous steps, we unchecked the State checkbox, so the pause button will be disabled as soon as it's clicked on.

Now, we can use the same component to re-enable the pause button when the resume button is pressed. Perform the following steps:

  1. Select our InGame3DUI | PauseMenu | Buttons | Resume GameObject.
  2. Click on the Add Component button in the inspector.
  3. Type in acti to search for components with this name.
  4. Select Button Activate and hit Enter or click on it with your mouse.
  5. Drag our InGame3DUI | TopButtons | Pause button in its Target field.
  6. Leave the State option checked.

Now, the pause button will be re-enabled when the resume button is clicked on. We need our pause menu to be disabled at the start. Let's do this by executing the following steps:

  1. Select our InGame3DUI | PauseMenu GameObject.
  2. Disable it in the Inspector checkbox.

Hit Unity's play button. You can now hit the Pause button. PauseMenu fades in as if it were displayed on the level's ground. When you hit the Resume button, the menu fades out and the Pause button reappears.

We can now link the buttons to methods to handle the actual pause and exit behaviors.

Linking the buttons

We'll first add the necessary methods, and then link our buttons to them.

Methods

Open the GameManager.cs script and add the following methods:

// Method called when pause button is pressed
public void PausePressed()
{
  // Request pause
  SetPause(true);
}

// Method called when resume button is pressed
public void ResumePresssed()
{
  // Request unpause
  SetPause(false);
}

// Method called when Exit button is pressed
public void ExitPressed()
{
  // Request to return to main menu
  ReturnToMenu();
}

The above methods will be linked to the buttons shortly. Before we do this, we need to add the required ReturnToMenu() and SetPause() methods:

// Use this method to return to the main menu
public void ReturnToMenu()
{
  // Unpause the game
  ResumePresssed();
  // Destroy the player instance
  Destroy(PlayerController.Instance);

  Transform mainMenu = null;
  mainMenu = MenuManager.Instance.transform.FindChild("Main");
  if(mainMenu != null)
  {
    // Set the MenuManager | Main scale to 1
    mainMenu.localScale = Vector3.one;
  }
  // Launch the EnterMenu couroutine
StartCoroutine(EnterMenu());
}

// EnterMenu Coroutine
private IEnumerator EnterMenu()
{
  // Show the main menu UI by enabling cam
  MenuManager.Instance.uiCamera.enabled = true;
  // Fade in the UI background
  TweenAlpha.Begin(MenuManager.Instance.background, 0.5f, 1);
  // Wait for the tween to finish
  yield return new WaitForSeconds(0.5f);
  // Load the Menu scene now
  Application.LoadLevel("Menu");  
}

// Use this method to pause / unpause game
public void SetPause(bool state)
{
  // Set the timescale to appropriate value
  Time.timeScale = (state ? 0 : 1);
}

Note

Make sure that the Menu and Game scenes are both in the Build Settings of the project by navigating to File | Build Settings.

Good! The preceding code pauses the game when SetPause(true) is called, and resumes it on SetPause(false).

The ReturnToMenu() method destroys the player, shows our main menu by resetting its scale to 1, and launches the EnterMenu() coroutine.

This coroutine re-enables the main menu's camera and fades back the UI background before loading the Menu scene.

We can now move on to linking our buttons to their appropriate methods.

Link

Follow these steps to link our pause, resume, and exit buttons to their respective methods:

  1. Select our InGame3DUI | TopButtons | Pause button.
  2. For the attached UIButton component:
    1. Drag GameManager to the On Click Notify field.
    2. Navigate to GameManager | PausePressed.
  3. Select our InGame3DUI | PauseMenu | Buttons | Resume button.
  4. For its attached UIButton component:
    1. Drag GameManager to the On Click Notify field.
    2. Navigate to GameManager | ResumePressed.
  5. Select our InGame3DUI | PauseMenu | Buttons | Exit button.
  6. For its attached UIButton component:
    1. Drag GameManager to the On Click Notify field.
    2. Navigate to GameManager | ExitPressed.

Now, load the Menu scene and hit Unity's play button. You can launch the game and hit the pause button. The game pauses, and you can either resume the game or go back to the main menu using the two buttons!

Note

Though Time.timeScale is set to 0, the pause menu's alpha tween still works correctly. This is because the tween's Ignore Time Scale option is checked.

Key bindings

We can add a simple feature; when the player hits the Escape key, the game pauses or resumes. We'll do this using the UIKey Binding component:

  1. Open the Game scene
  2. Select both our InGame3DUI | TopButtons | Pause and PauseMenu | Buttons | Resume buttons.
  3. Click the Add Component button in the inspector.
  4. Type in key to search for components with this name.
  5. Select Key Binding and hit Enter or click on it with your mouse.
  6. Set the Key Code field of the newly added UIKey Binding to escape.

You can now hit Unity's play button; you'll see that hitting Escape will pause and resume the game anytime!

Great! We have a slight problem; interactive elements are still active while the game is paused. We need to find a way to easily prevent the player from moving or right-clicking on a power source, or changing the character's destination while the game is paused.

Interaction override

We will create what can be referred to as an interaction override. Here, a trigger collider is placed over our game's interactive elements, which will prevent them from being hit by the interaction raycast of UICamera. Since the 3D UI with NGUI uses the Depth value to check collisions, we should also add the UIWidget component to the interaction override.

We can create it right now for the pause menu:

  1. Select our InGame3DUI | PauseMenu GameObject.
  2. Create a new empty child GameObject by pressing Alt + Shift + N.
  3. Rename this new child to Override.
  4. Click on the Add Component button in the inspector.
  5. Type in box to search for components with this name.
  6. Select Box Collider and hit Enter.
  7. Click the Add Component button again.
  8. Type in wid to search for components with this name.
  9. Select NGUI Widget and hit Enter or click on it with your mouse.

We now have a box collider and UI Widget on our Override GameObject. Configure them as follows in order to make sure they take up the entire screen:

  1. Select our new InGame3DUI | PauseMenu | Override GameObject.
  2. Set the Transform rotation to {-22, 0, 0}.
  3. For the attached UIWidget component:
    • Check the Collider auto-adjust to match option.
    • Set Size to 1920 x 1080.
    • Set Depth to 3.
  4. For its attached Box Collider component:
    • Check the Is Trigger option.

Good! Hit Unity's play button. When you pause the game, interactive elements such as power sources and the ground become inactive because the raycast of UICamera first touches the collider of Override.

Now that we have our nice 3D pause menu, let's see how we can add a 3D text or sprites directly onto the environment's objects.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.189.189.67