Best Practices for User Interfaces (UI) in VR with the XR Interaction Toolkit

Tutorial

·

Beginner

·

+10XP

·

20 mins

·

(179)

Unity Technologies

Best Practices for User Interfaces (UI) in VR with the XR Interaction Toolkit

In this tutorial, we'll explore how to implement UI in VR so that it’s comfortable and immersive for your users. We'll look at in-world versions of traditional UI, as well as look back at how we can use Interactable Events with 3D objects, such as buttons and switches, for in-world interaction that never breaks immersion.

Languages available:

1. Best Practices for User Interfaces (UI) in VR with the XR Interaction Toolkit

This tutorial has been verified using Unity 2019.4.12f1 LTS, XR Interaction Toolkit 0.9.3-preview, and Oculus XR Plugin 1.4.3


In this tutorial, we'll explore how to implement UI in VR so that it’s comfortable and immersive for your users. We'll look at in-world versions of traditional UI, as well as look back at how we can use Interactable Events with 3D objects, such as buttons and switches, for in-world interaction that never breaks immersion.


2. Creating a World Space UI

Applying UI directly to a user's screen in VR is like attaching a sticky note to their face. Instead, it’s good practice to anchor the UI in World Space so that it exists in 3D independent of the player (Figure 01). In this exercise, we’ll create a simple starting Scene with a button that loads a second Scene.


Figure 01: World Space UI

Figure 01: World Space UI


1. Create a new Scene.


2. Create a raw image for your title by selecting UI > Raw Image from the GameObject drop-down. This also creates a Canvas set to Screen Space - Overlay.


3. In the Hierarchy view, select your Canvas.


4. In the Inspector, change its type to World Space and drag the Main Camera into the Event Camera property slot (Figure 02).


Figure 02: Canvas set to World Space Render Mode, with Events triggered through the Main Camera.

Figure 02: Canvas set to World Space Render Mode, with Events triggered through the Main Camera.


5. Depending on your source art and how you want the UI to look, you may wish to increase or decrease Reference Pixels per Unit (Figure 03).


Figure 03: Default settings for the Canvas Scaler

Figure 03: Default settings for the Canvas Scaler


6. Create a new empty GameObject by selecting Create Empty from the GameObject drop-down. Name it SceneLoaderGO.


7. Attach a new C# script called SceneLoader and open it in the Script Editor.


8. Delete Start and Update, as we won’t be using these.


9. Add the following namespace:


[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

10. Add the following data member:


[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

11. Add the following method:


[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

12. Save changes and return to the Unity Editor.


13. Add a button by selecting UI > Button - TextMeshPro from the GameObject drop-down.


14. When prompted, click Import TMP Essentials (Figure 04).


Figure 04: Importing TextMesh Pro Essentials

Figure 04: Importing TextMesh Pro Essentials


15. Expand the button in the Hierarchy view and select Text (TMP). Set it to “NEW GAME” (or whatever suits your purposes).


16. Click to select the button in the Hierarchy. In the Inspector, scroll down to On Click (). Click the + sign (Figure 05).


Figure 05: Adding a listener to the OnClick event

Figure 05: Adding a listener to the OnClick event


17. Drag SceneLoaderGO into the Object slot. In the Function drop-down, select SceneLoader > LoadScene() (Figure 06).


Figure 06: The LoadScene() method set to be invoked when the button is clicked.

Figure 06: The LoadScene() method set to be invoked when the button is clicked.


18. Create a second Scene. An easy way to do this is to save the current Scene under a new name, make some changes so that it’s visually distinct from the Scene we’ve been working on, and save again.


19. Reload the original Scene.


20. In the Hierarchy view, select SceneLoaderGO.


21. In the Inspector for the Scene Loader component, enter the name of the second Scene (Figure 07).


Figure 07: Setting the next Scene

Figure 07: Setting the next Scene


22. Add an XR Rig. This works with either type of XR Rig. For this exercise, it doesn’t matter which you choose, as we’re working in Play Mode. For actual builds, you’d use the type most suitable for your project and target hardware.


23. Scale the Canvas/UI GameObjects down and place them so that they’re in front of the XR Rig and visible in the Main Camera’s preview in the Scene view.


24. Save the Scene and enter Play Mode.


25. In the Scene view, or using the Transform, move the Main Camera around. The UI elements remain in their original position rather than sticking to the screen/Camera.


26. Click the button. The second Scene should load. Make sure to include both Scenes in the Build Settings.


27. Exit Play Mode.


28. Try creating more complex interfaces. Rather than a single button, try a Vertical Layout Group.


3. In-World User Interfaces

A more immersive option would be to replace the UI button with the mesh of a button, with an Interactable and with the LoadScene() method attached to the OnSelectEnter event. For more information, see Customizing Interactors and Interactables.


4. Conclusion

With careful design, in-world user interfaces need not cause discomfort or break immersion. Even the traditional Canvas-based UI, when anchored in World Space, can take on the form of a holographic display, interactive kiosk, or whatever suits your project’s world.


Complete this tutorial