Beginner, Tutorials, Uncategorized, Unity3D

Unity3D Animated Pause Menu, Part 4: Responding to Player Input

Now that we have a functioning animator controller, it’s time to accept player input so that we can actually pause the game and bring up the menu.

To do this, create a new C# script called PauseController. This will be a very simple script; it’s 20 lines including whitespace, because all it needs to do is update the isPaused parameter of our animator controller. Here it is, in all its glory:

You’ll want to add this to the scene, so go ahead and drop it on the Canvas game object and drag the animator component to the canvasAnimator slot in the inspector.

There are a couple interesting things to note here. First, the isPausedHash bit. Animator parameters are identified by strings in the animator window and when getting or setting parameters in code, but this can be inefficient when updating them frequently (say, every frame). The preferred solution is to precompute the internal identifier that the animator uses to refer to the parameter, which allows for optimized lookup. Animator.StringToHash allows us to do this: is takes the string parameter name, and returns an integer identifier that we can use in its place. The only problem is that the identifier is not stable (we can’t just fetch it once then store it, because it might change between builds or potentially between plays of the game), so we simply cache it during the startup lifecycle of the component.

Input settings
Input settings
The second bit is on line 15, where we use Input.GetButtonDown("Cancel"). We could have bound the pause button to a specific key on the keyboard, but we’ve instead chosen to bind it to what is termed as an “input axis,” in this case, the “Cancel” axis. By default, this is the escape key, but it can be redefined by you, or even by the player later, and provides much more flexibility. You can find your project’s axes (and modify them or create new ones) via the Edit > Project Settings > Input menu. Note also that the Cancel axis is the same one used by the UI event system by default, so by using it, you’re providing a more consistent experience for your players.

As I mentioned, this script is very simple: when the player activates the Cancel button (again, the escape key by default), we toggle the isPaused parameter in our animator controller. After adding the PauseController component to the scene, you can test it out in play mode. There’s one problem though: activating the pause menu doesn’t actually pause the game. The easiest solution to that is to simply adjust the time scale in the PauseController when we change the isPaused parameter, but I want to take a slightly different approach, using a state machine behaviour.

State Machine Behaviours

Unity’s StateMachineBehaviour is a class, like MonoBehaviour, which you can extent and add to one or more animator states, and which provides hooks to execute code in response to certain events, like entering or exiting the state. In our case, the behavior we want is to stop gameplay when we enter the Paused state of our animator, and resume gameplay when we leave it.

Create StateMachineBehaviour
Create StateMachineBehaviour
To create the StateMachineBehaviour, go to the Animator window, select the Paused state, and click the Add Behaviour button in the inspector, beneath the Transitions controls. Click New Script, and name it something like PauseSMB. Hit enter to confirm. Here’s what a newly-created script looks like:

You can see that there are five events that a StateMachineBehaviour handles: OnStateEnter, OnStateUpdate, OnStateExit, OnStateMove, and OnStateIK. These five states provide enormous flexibility in scripting your animations, and we’ll explore them in greater depth in another tutorial. For the purposes of our pause menu, though, we only care about two: OnStateEnter and OnStateExit. Uncomment those two, and remove the rest.

Pausing and unpausing the game is a simple matter: we simply adjust Time.timeScale to be either 0 (paused) or 1 (full-speed). There are more interesting things you can do with the time scale, but for the pause menu, we’re only interested in “full paused” and “full speed.” Change Time.timeScale to 0 in OnStateEnter, and change it to 1 in OnStateExit. Remember that we added the StateMachineBehaviour to the Paused state, so this reflects our expectations on how the game should behave: when we enter the state, the game should pause, and when we leave it, the game should resume again.

Here’s the code:

Just like the PauseController class, this is very simple. As I mentioned, we could have put this logic in the PauseController itself, but by instead putting it in a state machine behavior that is explicitly tied to the Paused state, we’re making a clean separation between “telling the game to pause” and “telling the game what to do when it’s paused.” Now it doesn’t matter if we always trigger the pause transition from the PauseController or if we eventually decide to add a new way to pause the game: the logic is in one place.

Setting Animator to Unscaled Time
Setting Animator to Unscaled Time
If you enter play mode and test things out, you’ll notice something strange: the game pauses properly (you’ll want to add something moving to the scene to confirm this), but the pause menu doesn’t appear until you unpause the game (at which point, it suddenly appears and plays the proper “transition out” animation). This is because by default, the Animator component respects Time.timeScale. When we hit escape to bring up the pause menu, we successfully transition to the Paused state, and then immediately halt the progress of the animation by setting Time.timeScale to 0 (you can confirm this by going to the Animator window and seeing the transition bar stuck at the very beginning). This is great for keeping character animations in sync with the game speed, but doesn’t work as well for animations that only happen while the game is paused. To remedy this, select the Canvas gameobject in the hierarchy, find the Animator component, and change Update Mode from Normal to Unscaled Time (remember to exit play mode first so that your changes are preserved).

At this point, we’ve set up our pause menu UI, animated it, and added code to allow the player to pause and unpause the game. We could call it good, but in the next section, we’ll talk about how to add a little polish to what we’ve created. Thanks for following along so far!

Beginner, Tutorials, Uncategorized, Unity3D

Unity3D Animated Pause Menu, Part 2: Animating the UI elements

Following the setup of all the UI elements for the pause menu in part one, we’re now going to create an animation for the transition between the unpaused and paused states of the game. As a reminder, here’s a preview of the finished state of the pause menu, showing the transition animation:

Pause menu animating in and out with example gameplay in background
Pause Menu in Action

Before we get started, let’s talk a little bit about animation in Unity3D. Unity’s animation system, Mecanim, uses curves to represent motion. Most commonly, these motion curves drive the movement of 3D models, but you can actually use Mecanim to animate any public property that Unity knows how to serialize. We’re going to use this to our advantage in our pause transition to move UI elements around the screen.

With Mecanim, you can either edit the curves directly, or use the keyframe-based dopesheet to specific values, and let Mecanim figure out the curves for you. In this case, we’ll be use the dopesheet as it’s easier to work with and we’re not going to be doing anything too complex.

Open the Animation window (⌘6 on OSX, ctrl-6 on Windows), select the Canvas game object in the hierarchy, and click the Create button. Doing this will prompt you to create a new Animation asset, as well as creating a new animator controller and adding an Animator to the Canvas game object if it doesn’t already have one. Note that you could technically animate the menu elements directly, but as we split them up to allow for more complex transitions, and because we want to later be able to animate multiple, discrete UI elements with one animator controller, we’re going to add the animator to the Canvas, which is the highest-level parent of a UI element.

After creating a new animation clip, we enter “record” mode by default, but first we want to set all our pause menu UI elements to their default (unpaused) state. Click the red Record circle exit record mode, then select the panel background, panel contents, and title text, and move them off-screen. To achieve the transition effect I wanted, I moved the panel background on the x axis to the right, the panel content on the x axis to the left, and the title text on the y axis up. They don’t have to be a huge distance off-screen, just enough so that they’re not visible during gameplay (you can use the Game window to check this, or enter play mode to try it out). My UI view now looks like this:

Current UI Setup
Current UI Setup

With our initial state set up, we’re ready to animate! Select the Canvas game object and pick your pause animation out of the dropdown menu if it’s not already selected, then hit the red button to enter Record mode. You know that it’s working properly when your editor play mode buttons turn red:

We’ll want to add three properties: Panel Background > Rect Transform > Anchored Position, Panel Content > Rect Transform > Anchored Position, and Title > Rect Transform > Anchored Position. This adds keyframes for each property at 0:00 and 1:00 (one second). If you played your animation now, it would do… a whole lot of nothing, because the beginning and ending keyframes have the same value, which is in effect saying “do nothing for one second”. Let’s change that. Drag the playback head (the red line) to the one second mark (clicking on the keyframe at the time you want to change won’t have the desired effect) and “zero out” the Anchored Position properties, setting each UI element in the pause menu to the position that it should be in when the game is paused. You can either set them in the Animation window directly, set the appropriate fields on the Rect Transform in the inspector (animated fields turn red as well when in record mode), or reposition the elements by hand in the scene view.

With that done, hit play in the animation window. You’ll see the different elements of your pause menu slide in, but one second to bring up a menu is almost painfully slow. Players are nothing if not impatient, so we need to make the transition snappy to avoid frustrating them. Plus, I think that, rather than all the motion happening at once, it will look better if the background flies into place first, followed by the text and buttons sliding in, followed by the logo dropping into place. Exit animation play mode, and adjust the animation by dragging the keyframes in the dopesheet. I found that about a quarter second per element (so, multiples of 0:15 on the timeline), with the next element starting its motion as the previous reached its destination, felt about right for the feel I wanted to achieve. Here’s a look at my finished dopesheet, about 50% through the full animation (as indicated by the red playback head line):

Completed Dopesheet

With that, we’ve completed the animation for our pause menu elements. The last thing to do is select the animation clip asset we’ve created and uncheck the Loop Time property in the inspector, as a preparation for creating the pause transition state machine in the next tutorial post. Thanks for following along!

uGUI, Uncategorized, Unity3D

Animating Multiple UI Elements with One Animator Controller

Have you ever wanted to animate multiple UI elements at once in Unity? Unity3D 4.6 brought with it the long-awaited Unity GUI (or uGUI) system, and with that, a lot of potential for creating great in-game UIs. When building your game’s UI, you will probably want to animate different aspects of it, whether that’s sliding a menu in from off-screen, fading in text, or any of a number of other effects. One option is to create separate animator controllers for every element, but that can quickly get out of hand: the number of assets to keep track of increases for every UI element you want to animate, not to mention the possible performance implications of running many separate animators at the same time.

A better solution is clearly to use a single animator controller to manage animations for multiple parts of your in-game UI, but there are some caveats. Animating an element implies having multiple states per element: fading in and out “Game Paused” text, sliding a panel on and off screen, and so on. Trying to manage all of these with a single state machine will result in a combinatorial explosion of required states… GamePausedPanelShown, GameUnpausingPanelHidden, GameUnpausedPanelShown, GameUnpausedPanelHidden are an incomplete list of states that you might require for just two animated elements!

The answer is in animation layers. You might be familiar with layers as allowing you to do facial animation in addition to action animations for your 3D models, but we can apply them here by creating one layer for each element you want to animate and change at runtime.

Animating UI Components with Layers
Animating UI Components with Layers

In this example, I’m demonstrating the scenario I mentioned before: I want to fade in and out a “Pause” text in response to the user pausing the game, and I also want to be able to slide a panel on-screen to display some non-critical information to the player upon request.

For the pause text, I have a simple 3-state state machine, and transition between them by setting a boolean isPaused animator parameter in response to user input. I’m doing something similar to animate the panel, with an isPanelVisible parameter. The Base layer is empty. All told, it took me five or ten minutes to set up.

However, if you repeat my setup and try to pause the game, you may be dismayed to find that your UI isn’t animating at all. That’s because there’s one additional step, the “secret sauce” to making this work: setting the layer weights. Unity defaults the weight of a new layer to 0, meaning it won’t contribute to the overall animation at all. You’ll want to set the weight of all your UI animator layers to 1, meaning the animations played by the layers’ states fully contribute to the final animation. This setting is found in the cog menu of the layer in the Animator window, as demonstrated in the gif below:

Setting Layer Weight
Setting Layer Weight

For a 3D model, you would tune layer weights based on how much that layer should reasonably contribute to the model’s animation, and is in general a more complex process, but for UI animation, each layer is basically independent of the others, and you want to make sure that all layers get to run their full animation. Setting all layer weights to 1 enables this.

One final thing to note is that if you have already begun animating a UI element on the Base Layer of your animator controller, and would like to move it to a new layer, leaving the default layer uncluttered, you can accomplish this by adding a new empty layer, then dragging that empty layer to the top of the layer list. Layers cannot be copied (so far as I know), but Unity treats the top layer as the default layer, giving it a forced layer weight of 1, and letting you set up multiple layers to control discrete UI components.

You can download the example Unity project.