
Unity Cookbook
By :

UI Panels are provided by Unity to allow UI controls to be grouped and moved together, and also to visually group elements with an image background (if desired). The sibling depth is what determines which UI elements will appear above or below others. We can see the sibling depth explicitly in the Hierarchy window, since the top-to-bottom sequence of UI GameObjects in the Hierarchy window sets the sibling depth. So, the first item has a depth of 1, the second has a depth of 2, and so on. The UI GameObjects with larger sibling depths (further down the hierarchy, which means they’re drawn later) will appear above the UI GameObjects with smaller sibling depths:
Figure 2.13: Example of organizing panels
In this recipe, we’ll begin by creating two UI Panels, each showing a different playing card image, and we’ll use one button to move between them. We’ll then expand the recipe by creating one more UI Panel. We’ll also add four triangle arrangement buttons to change the display order (move to bottom, move to top, move up one, and move down one).
For this recipe, we have prepared the images that you need in a folder named Images/ornamental_deck-png and Images /icons
in the 02_04
folder.
To create the UI Panels whose layering can be changed by clicking buttons, follow these steps:
Panel-jack-diamonds
. Do the following to this panel:jack_of_diamonds
playing card image asset file from the Project window into the Source Image property. Select the Color property and increase the Alpha value to 255
(so that this background image of the panel is no longer partly transparent).Button-move-to-front
. In the Hierarchy window, make this button a child of Panel-jack-diamonds. Delete the Text child GameObject of this button (since we’ll use an icon to indicate what this button does).Panel-jack-diamonds
from the Hierarchy window over to the Object slot (immediately below the menu saying Runtime Only).Figure 2.14: Addition of an OnClick event handler
Panel-2-diamonds
with its own move-to-front button and a Source Image of 2_of_diamonds
. Move and position this new panel slightly to the right of Panel-jack-diamonds
, allowing both move-to-front buttons to be seen.In this recipe, you created two UI Panels, each of which contains a background image of a playing card and a UI Button whose action will make its parent panel move to the front. You set the Alpha (transparency) setting of the background image’s Color setting to 255 (no transparency).
You then added an OnClick event handler to the button of each UI Panel. This action sends a SetAsLastSibling
message to the button’s panel parent. When the OnClick message is received, the clicked panel is moved to the bottom (end) of the sequence of GameObjects in the Canvas, so this panel is drawn last from the Canvas objects. This means that it appears visually in front of all the other GameObjects.
The button’s action illustrates how the OnClick function does not have to be calling a public method of a scripted component of an object, but it can be sending a message to one of the non-scripted components of the targeted GameObject. In this recipe, we send the SetAsLastSibling message to the Rect Transform component of the panel where the button is located.
There are some details you don’t want to miss.
While Rect Transform offers SetAsLastSibling
(move to front) and SetAsFirstSibling
(move to back), and even SetSiblingIndex
(if we knew exactly what position in the sequence to type in), there isn’t a built-in way to make an element move up or down just one position in the sequence of GameObjects in the Hierarchy window.
However, we can write two straightforward methods in C# to do this, and we can add buttons to call these methods, providing full control of the top-to-bottom arrangement of the UI controls on the screen. To implement four buttons (move-to-front/move-to-back/up one/down one), do the following:
ArrangeActions
containing the following code and add an instance as a scripted component to each of your UI Panels:
using UnityEngine;
public class ArrangeActions : MonoBehaviour {
private RectTransform panelRectTransform;
void Awake() {
panelRectTransform = GetComponent<RectTransform>();
}
public void MoveDownOne() {
print("(before change) " + gameObject.name + " sibling index = " + panelRectTransform.GetSiblingIndex());
int currentSiblingIndex = panelRectTransform.GetSiblingIndex();
if (currentSiblingIndex > 0) {}
panelRectTransform.SetSiblingIndex(currentSiblingIndex - 1);
}
print("(after change) " + gameObject.name + " sibling index = " + panelRectTransform.GetSiblingIndex());
}
public void MoveUpOne() {
print ("(before change) " + gameObject.name + " sibling index = " + panelRectTransform.GetSiblingIndex());
int currentSiblingIndex = panelRectTransform.GetSiblingIndex();
int maxSiblingIndex = panelRectTransform.childCount - 1;
if (currentSiblingIndex < maxSiblingIndex) {
panelRectTransform.SetSiblingIndex(currentSiblingIndex + 1);
}
print ("(after change) " + gameObject.name + " sibling index = " + panelRectTransform.GetSiblingIndex());
}
}
MoveDownOne()
method and set the function for the up-one buttons to call the MoveUpOne()
method.Note that the MoveDownOne()
and MoveUpOne()
methods subtract and add 1 to the sibling depth of the panel the scripted object is a component of. The methods contain a test, so ensure we don’t try to set a negative panel depth or a depth that is higher than the maximum index for the number of panels.