With the release of Unity 4.6 and its new UI system, we thought it was time to go into more detail on how we designed and built the interface of Fragments of Him using Unity 4.6. We have been actively using the Unity 5 beta so far, but most (if not all) of the UI systems should work exactly the same as in 4.6. In this blog post I'll be going over most of the technical aspects of the menu in Fragments of Him. Let's start by showing how the interface currently looks:
Fragments of Him in-game menu
The menus in Fragments of Him appear relatively simple and its mainly for players to change game, audio, and graphics settings. Here's the flowchart of the menu to give you an idea of how it's structured:
With the options panel active, each of the following buttons (e.g. Gameplay) opens up a panel with the respective options.
Organising the Scene
When you see the menu from within Unity 4.6 then this is what you would see:
Let's go over what we're actually looking at.
1 - The strong lined white rectangle on the left (with the Fragments of Him logo in it) is the interface that is overlain on the game screen. It is where we'll have to move objects to if we want them to be visible to the player.
2 - The Menu Panel is the first panel that we show when starting or pausing the game with primary options such as Start/Continue, Load Game, Options, and Exit Game.
3- The Options Panel is what you see positioned outside the white rectangle and this panel will appear when clicking on the options button. The menu panel will slide out and the options panel will slide in.
4 - When an option is clicked on, the Options Container will slide in which contains all the options such as gameplay, graphics, audio, and controls. Conversely, when leaving the options panel, the options container will slide back out revealing the menu panel once again.
In the scene hierarchy this looks something like this:
Scene Hierarchy for the menu
To give players the interaction feedback they need we are using the new button component that allows us to indicate how a buttons should behave in various states. All of our buttons have the same basic interaction setup that looks like this in the inspector:
Button Inspector View
We handle the transitions between button states with mecanim (you can see the structure of that below), this is done so that the art team has a little bit more control over the animations (and our Lead Artist Tino has this thing for smooth transitions between states). Do note that this is the Unity 5.0 interface for mecanim, which probably looks different in Unity 4.6. The list on the left are the triggers that trigger the animation states, On the right side you see that these states can be driven from any situation.
Hooking it all up
Until this point it was all pretty easy and straight forward. Then we tried to make this all flow into each other seamlessly, accommodating for whatever the player wanted to do with it. In our experience we noticed that we couldn't animate the entire interface with only Mecanim. That meant for us that we had to solve some things with code.
At first we opted for letting the art team assemble and animate the entire interface using the Unity 4.6 features. We figured that it would them full control of how things would look and feel. However, back then we didn't realise that Mecanim relies on the internal timescale to perform its animations. When we set the Time.timeScale to 0 in order to pause the game, it also meant that the interface would not animate as intended.
EDIT: Thanks to everyone tweeting me for a solution to this, apparently there's a dropdown box in the Animator called "Update Mode" (see image below). Set that to "Unscaled Time" and it'll work just fine!
Unity Animator Component
To solve this problem, we went over a couple of different solutions. In the end had to settle for somewhat of a hack. To pause the game we would set the timeScale to 0.00001f. Then we set the animation speed of the interface animations to 100000 to make it look like everything in the interface plays out in real-time.
When you enter the options panel, the code takes over and all the animations are scripted. This is done by using iTween (iTween has a very useful 'ignoretimescale' parameter). For those curious as to how that works, this is the code that makes sure that the panel slides into view of the viewport:
The code handles the sliding in and out of panels and also makes sure that the player gets the correct feedback. Additionally, we accommodate the interface to be used with either a game controller, mouse, or keyboard. Each of these input interfaces also requires its own set of feedback systems.
Step by Step
Whenever the player presses the menu button, which is usually the Escape key on the keyboard or Start if you're using a gamepad, the menu should pop up. What we do is simply turn on container 1 and 2 using GameObject.SetActive(true);. In addition to that we want to make sure that if the player is using a controller, the first object is highlighted. We do that with EventSystem.SetSelectedGameObject(continuebutton, null); and we make sure to trigger the mecanim animation using Animator.SetTrigger.
When you're in container 1 and press the Options button, we use Animator.SetTrigger to move container 1 to the left, and move container 2 to the right at the same time. Clicking on a button in container 2 will call a script that moves container 3 into view. The options container is different than 1 and 2, as that one contains multiple panels. Whenever a button is clicked in container 2, the code will select the correct panel to be turned on (once again, with GameObject.SetActive(true);). This happens off-screen to ensure that the player doesn't see any popping of the menu. When the player backs down from the menu all of the above will be done in reverse. At first the code would play and set the player back into container 2, where Mecanim will take over to animate the menus once again.
When we started thinking about the design and functionality of the interface we wanted to have dropdown menus for things such as the resolution. Back when we built the interface, we soon found out that there wasn't an out of the box solution for dropbdowns that suited our needs. Eventually, we managed to come up with a solution that makes clever use of mecanim, masks, and buttons. Here is how it works in action
To get this to work we first created a list of all the options that we needed to have in the dropdown list as buttons and place it the way we wanted it. Then we mask off all the options we don't need with a mask component. To make the dropdown slide in and out it's simply a matter of animating the bounds of the mask to what we want to mask off. Finally, in order to trigger this dropdown animation we placed a button on top of the first dropdown option to make it slide down. Any selection from the dropdown list that is revealed will make the interface slide back in again. It might not be elegant, but it works.
Supporting different resolutions
Something that we didn't immediately thought of when designing the interface is the various resolutions that the interface needs to support. This is where Unity 4.6 really shines as we can use the Rect Transform to anchor the various panels, windows, containers, and buttons that we use to make up the interface.
As a result, we can now use resolutions all the way down to 1024px by 768px while still having everything in frame and readable.
We aren't completely done with the interface yet but apart from a few small things we are not expecting to be changing things too drastically. Hopefully you have gotten a little insight in how we used the new Unity 4.6 interface features and we would like to know how you end up using it.