The previous post focused on creating a simple text popup window based on user interactions. In this post, we take things one step further by creating UIs which can include a combination of text, images, buttons, scrollbars, etc. for a larger interaction set presented to the user. We will be utilizing the Canvas game object in Unity to enable these features.
In the Hierarchy window, right click UI→Canvas. This creates an empty canvas to the scene. In order to make the canvas visible and interact-able with the Hololens, you have to do the following;
1. Change Render Mode to World Space. Unity will prompt you to update the canvas' WorldCamera to use the UIRaycastCamera. Click OK
2. Look and feel: This was really tricky and took multiple attempts (and research online). Generally you want to set the canvas X,Y,Z position to 0, 0, (some reasonable Z around 5. The canvas scaling should be anywhere between 0.01 and 0.1 (again this number is obtained by trial and error)
3. In the canvas Inspector, Add Component→Layout→Vertical Layout Group. I like using this because it neatly organizes all the content I eventually place in the canvas. Once you are comfortable with canvas placement and object adjustment, you can disregard this step.
Great, we have a canvas! Now what?
Let's add some text elements to this canvas. In the Hierarchy window, right click UI→Text. The text game object appears as a child under the canvas.
Text (script) is not editable (AFAIK). We will add a text mesh component (Add Component→Mesh→Mesh Filter). This field is editable, which will come in handy later on in this example. As before, we want a reasonably large font size and lower scale factor to get a crisp font rendering. Since we have used a Vertical Layout Group for the canvas, the text position inside the canvas is frozen. Add the desired text. I also allow both horizontal and vertical overflow for the text.
Update (3/28/18): Text components are, in fact, editable. You need to include using UnityEngine.UI to editthe Text fields of objects in a canvas. This is done using GetComponentInChildren<Text>().text = "Insert string here"
Pro Tip: In this example, the upper left corner of the canvas is the (0,0) position and, just like a regular 2D graph, the lower right corner is (canvas width, -canvas height) coordinate. In our example, that will be (400,-400). You can visually see the canvas origin by the placement of the white cross-hairs on the canvas.
Next step is to add a button to the canvas. In the Hierarchy window, right click UI→Button. The button object appears as a child under the canvas.
The button has some interaction controls and settings. These color options change the look and feel of the button depending on the situation. There is also a text component under the button. Type in "Click Here" in the Text (Script) area.
The final object to add to the scene is a sphere with the red material created in the previous example. I added this at (1,1,5) with a scale of (0.3,0.3,0.3). The canvas is at (0,0,5) with a scale of (400,200).
Now that the components have been added, let's work through the scene and build the scripts.
In this scene, we want to do the following:
1. If the user gazes at the button, change the color of the ball (IFocusable)
2. If the user air taps on the button, change the text with a running count of the number of taps (IInputClickHandler)
In the Scripts folder, create a new script called ButtonInteraction. We will create two public variables that hold the sphere and the text area. We will also create two private variables that hold the sphere's default color and the click count.
In brief, the OnFocusEnter and OnFocusExit scripts will change the default color to a random color and re-instantiate the default color respectively.
The OnInputClicked function will increase the click count and change the text mesh in the text area.
The code is provided below.
This is a sample visual of the game scene:
Assignment: Try adding a second button that resets the count. I'll leave this up to you to do but here are some hints:
1. Use the FindObjectOfType function to access the count number of the script associated with the first button
2. Use get and set methods to access private variables
Pro Tip: How can you find Primitive objects such as spheres and cubes in your scene? You can use tags. This is a clean solution if you want your UI objects to interact with objects in the scene such as players, enemies, objects, etc.