The Problem with UI in VR
Building a user interface on a flat screen is relatively straightforward. Pick a position on the screen where you want your UI to show and it shows there. As long as you don't make it too intrusive, you can just let that UI hang out there, on top of everything else going on in your game. That is not the case for VR. Here is why.
First, in VR, having a UI element consistently stuck in the same place as the player is navigating the VR world can be a jarring experience. At best, it breaks the immersion and reminds them they are seeing this world through a screen. At worst, it can cause confusion and VR sickness as people try to make sense of the strange behavior and visual stimuli they are seeing. Thus, you need the UI to "belong" in that VR world.
Second, having a UI element always take part of your field of view reduces how much of that world you can see, which is just a shame. Therefore, you need to make the UI easy to find and easy to remove from view.
Make the UI belong in the world
Getting the UI to fit your experience can mean many things. In the simplest of terms, it needs to feel like a real object in the world. There are a couple of ways to achieve this. One way is to make it a static object. Think of it as placing and actual screen inside your world and displaying your UI there. This tends to be very useful for contextual UI. For example, if you are controlling a large spaceship, you may have several stations for controlling different systems and you may need to virtually move in that world to access all of the controls as they are mapped to virtual stations. Another way to make your UI fit the virtual world is to make it follow the player. Mind that following the player is different from being stuck to the player's view. Often, the most intuitive UI follows both principles. Think of a "wearable" UI. For example, if you let the player have a virtual wristband that displays relevant information then the player can glance at their wrist when they need that information but will otherwise not obstruct their view.
In my case, I went with UI that follows the player. Initially, I had the score and some debug text simply stuck to the player position. It was not that intrusive since the player could look around and the UI would not follow their gaze, it would stick to the player position in the world. It had the issue that if the player turned around the UI would stay behind them, out of view. It was still better than having the UI stuck to the player's view but it could be better. So I made it a bit better. I added a script to the UI canvas so that it would constantly look at the camera and had it follow a point in front of the player so that it would hang out in front of them if the player was still and the UI would follow the player around when they moved.
void FollowCamera() { transform.LookAt(lookAt, Vector3.up); // lookAt is the camera transform transform.Rotate(0f, 180f, 0f); // Rotate the canvas 180 degrees on the Y so the canvas faces the camera Vector3 newPosition = transform.position; // use Lerp (linear interpolation) to get the canvas to approach the followPosition transform // (the point in front of the player). followSpeed determines how fast the canvas closes the distance newPosition.x = Mathf.Lerp(transform.position.x, followPosition.position.x, followSpeed * Time.deltaTime); newPosition.y = Mathf.Lerp(transform.position.y, followPosition.position.y, followSpeed * Time.deltaTime); newPosition.z = Mathf.Lerp(transform.position.z, followPosition.position.z, followSpeed * Time.deltaTime); transform.position = newPosition; }
Make the UI easy to find and easy to remove from view
I have yet to do a good job at this. In part because I think that, in my case, I want the player to be constantly focused on how their actions affects their score so I have the score always visible. Even though it is not the most intrusive piece of UI, it still could be made easier to hide. For example, making it hang around knee-high level would make it easier to keep the UI out of view when the player is looking straight ahead but will make it a cinch to find the score by simply looking down a bit.