Simple Gaze Cursor in Unity

simple_gaze_cursor.png

It's hard to tell exactly what you're looking at in Virtual Reality. A 3D cursor in the center of your gaze can be a great way to fix that problem.

In this guide, you'll learn how to create a pointer that lands on whatever object you are looking at. If there's nothing in your direct line of sight, we'll put it at a fixed distance from the center of your gaze.


Super Condensed Version

  • Create a C# script, "SimpleGazeCursor.cs
    • Make public variables for the Camera and Cursor prefab
    • On each frame, raycast from the camera. If it hits something, place the cursor at the hit point and rotate it according to the normal angle of the hit. If it doesn't, place the cursor at a fixed distance in the direction of the raycast.
  • Create a Cursor prefab with imported 3D assets (.fbx) and apply a material to it.
  • Add "SimpleGazeCursor.cs" to your player object and attach the Camera and Cursor prefab

The files in the following zip file will be helpful for this tutorial:

SimpleGazeCursor.zip

Set up a test scene

1. Create a simple scene to test out the cursor you're going to make. In my scene, I have a Directional Light and two Cubes, one scaled out in the X and Z to act as a floor.

2. Next, create an empty Game Object and call it "Player".

3. Drag the "Main Camera" (that was in the scene by default) onto the "Player" object, making it a child.

sample_scene.png

Create the cursor script

1. Create a new C# script in the Project pane and call it "SimpleGazeCursor".

2. Double click on the script to open it in Visual Studio. You should see a template for your SimpleGazeCursor class with a Start() function and an Update() function.

3. Add three public variables and one private variable after the curly bracket of the class declaration:

public class SimpleGazeCursor : MonoBehaviour {
    public Camera viewCamera;
    public GameObject cursorPrefab;
    public float maxCursorDistance = 30;
    private GameObject cursorInstance;
    ...

4. Add the following line to the Start() method, between the curly braces:

void Start () {
    cursorInstance = Instantiate(cursorPrefab);
}

5. Add a call to UpdateCursor() to the Update() method, between the curly braces:

void Update () {
    UpdateCursor();
}

6. Create a new method called UpdateCursor(), which will contain all of the logic to update the cursor each frame:

private void UpdateCursor()
{
    // Create a gaze ray pointing forward from the camera
    Ray ray = new Ray(viewCamera.transform.position, viewCamera.transform.rotation * Vector3.forward);
    RaycastHit hit;
    if (Physics.Raycast(ray, out hit, Mathf.Infinity))
    {
        // If the ray hits something, set the position to the hit point
        // and rotate based on the normal vector of the hit
        cursorInstance.transform.position = hit.point;
        cursorInstance.transform.rotation = Quaternion.FromToRotation(Vector3.up, hit.normal);
    }
    else
    {
        // If the ray doesn't hit anything, set the position to the maxCursorDistance
        // and rotate to point away from the camera
        cursorInstance.transform.position = ray.origin + ray.direction.normalized * maxCursorDistance;
        cursorInstance.transform.rotation = Quaternion.FromToRotation(Vector3.up, -ray.direction);
    }
}

Full script can be found in the zip file (SimpleGazeCursor.zip).

Create the cursor prefab

cursorPrefab.png

1. Create an empty Game Object and call it "Cursor".

2. Import the Cursor assets (SimpleGazeCursor.zip) and make both of them children of the "Cursor" Game Object.

assets.png
hierarchy.png

3. Open up the Materials folder and select "Cursor_MAT." Then change the Albedo color to whatever you like.

materials.png

4. Drag the "Cursor" Game Object down into the Project pane to create a Prefab from it.

gameobject.png

5. Finally, delete the "Cursor" object from the Hierarchy.

Tie it all together

1. Select the "Player" Game Object. Drag the SimpleGazeCursor script into the Inspector pane to attach it.

inspector.png

2. Drag the "Main Camera" object into the "View Camera" slot.

3. Drag the "Cursor" prefab into the "Cursor Prefab" slot.

4. Hit "Play" and check out your new cursor in Virtual Reality!

 

I hope this was helpful! Please let me know what you thought.