Unity 2018 Cookbook(Third Edition)
上QQ阅读APP看书,第一时间看更新

The big picture

The UI can be used for three main purposes:

  1. To display static (unchanging) values, such as the name or logo image of the game, or word labels such as Level and Score, that tell us what the numbers next to them indicate (recipes for these can be found in the Chapter 1Displaying Data with Core UI Elements).
  2. To display values that change due to our scripts, such as timers, scores, or the distance from our Player character to some other object (an example of this is the radar recipe at the end of this chapter).
  3. Interactive UI controls, whose purpose is to allow the Player to communicate with the game scripts via their mouse or touchscreen. These are the ones we'll look at in detail in this chapter.

The core concept for working with Unity Interactive UI controls is the registration of an object's public method to be informed when a particular event occurs. For example, we can add a UI Dropdown to a scene named DropDown 1, and then write a MyScript script class containing a NewValueAction() public method to do some action. But nothing will happen until we do two things:

  1. We need to add an instance of the script class as a component on a GameObject in the scene (which we'll name go1 for our example  although we can also add the script instance to the UI GameObject itself if we choose to).
  2. In the UI Dropdown's properties, we need to register the GameObject's public method of its script component to respond to the On Value Changed event messages:

The NewValueAction() public method of the MyScript script will typically retrieve the value selected by the user in the Dropdown and do something with it  for example, confirm it to the user, change the music volume, or change the game difficulty. The NewValueAction() method will be invoked (executed) each time GameObject go1 receives the NewValueAction() message. In the DropDown 1's properties, we need to register GameObject go1's scripted component MyScript's NewValueAction() public method as an event listener for On Value Changed events. We need to do all this at Design-Time (that is, in the Unity editor before running the scene):

At runtime (when the scene in the built application is running), if the user changes the value in the drop-down menu of UI Dropdown GameObject DropDown 1 (step 1 in the diagram), this will generate an On Value Changed event. DropDown 1 will update its display on screen, to show the user the newly-selected value (step 2a). It will also send messages to all the GameObject components registered as listeners to On Value Changed events (step 2b). In our example, this will lead to the NewValueAction() method in GameObject go1's scripted component being executed (step 3).

Registering public object methods is a very common way to handle events such as user interaction or web communications, which may occur in different orders, may never occur, or may happen several times in a short period. Several software Design Patterns describe ways to work with these event setups, such as the Observer Pattern and the Publisher-Subscriber pattern (we'll learn more about this pattern in Chapter 16, Design Patterns).

Core GameObjects, components, and concepts relating to interactive Unity UI development include:

  •  Visual UI controls: The visible UI controls themselves include Button, Image, Text, and Toggle. These are the UI controls the user sees on the screen, and uses their mouse/touchscreen to interact with. These are the GameObjects that maintain a list of object-methods that have subscribed to user-interaction events.
  • Interaction UI controls: These are non-visible components that are added to GameObjects; examples include Input Field and Toggle Group.
  • Panel: UI objects can be grouped together (logically and physically) with UI Panels. Panels can play several roles, including providing a GameObject parent in the Hierarchy for a related group of controls. They can provide a visual background image to graphically relate controls on the screen, and they can also have scripted resize and drag interactions added, if desired.
  • Sibling Depth: The bottom-to-top display order (what appears on the top of what) for a UI element is determined initially by their sequence in the Hierarchy. At Design-Time, this can be manually set by dragging GameObjects into the desired sequence in the Hierarchy. At Run-Time, we can send messages to the Rect Transforms of GameObjects to dynamically change their Hierarchy position (and therefore, the display order), as the game or user interaction demands. This is illustrated in the Organizing images inside panels and changing panel depths via buttons recipe.

Often, a UI element exists with most of the components that you may need for something in your game, but you may need to adapt it somehow. An example of this can be seen in the recipe that makes a UI Slider non-interactive, instead using it to display a red-green progress bar for the status of a countdown timer. See this in the Displaying a countdown timer graphically with a UI Slider recipe.