cancel
Showing results for 
Search instead for 
Did you mean: 

New Unity UI + OVR Look-Based Input HOWTO

Anonymous
Not applicable
LookInputModule.jpg

Edit6: version 5 of example project/code:
https://www.dropbox.com/s/g8ptl7w9xdewp ... 5.zip?dl=0
Version removed old Oculus integration and uses Native VR support + 0.1.2 utils so it works with latest runtimes (0.7 or 0.8).

Edit5: version 4 of example project/code (fixed for and tested with Unity 4.6.4f1):
https://www.dropbox.com/s/3bpz5rgimbxdk ... 4.zip?dl=0
This version also adds support for a cursor that scales size with distance so it will always appear the same size but be at the right depth.

Edit4: version 3 of example project/code:
[removed - see updated example above]

Edit3: New version of example project and code posted:
[removed - see updated example above]

Edit2: If you don't have time to read all of this thread and just want the code and a sample project, I uploaded one here:
[removed - see updated example above]

Edit: fixed some issues with the code to handle InputField and also was selecting wrong game object in some cases.

I have been messing around with the new Unity GUI stuff in 4.6 release, and I figured I would share a basic solution to get up and running quickly with a look-based input system. Here is how to get a basic look UI working:

1. Add some kind of UI element to your scene. This will also add a Canvas object and an EventSystem object if you don't already have them in your scene. All UI elements must be parented by a Canvas.

2. On the UI Canvas object, set the Render Mode to World Space

3. Arrange your Canvas in world space and add more UI elements as you would like. To get started, I would just add some buttons.

4. Under the OVRCameraRig->CenterEyeAnchor object, add a regular Unity Camera at position and rotation 0,0,0, and set this camera's Culling Mask to "Nothing" so it won't actually bother rendering anything and waste CPU/GPU cycles. I named it "Look Camera". This camera is just for use by the UI event system. By putting it under the CenterEyeAnchor object, it tracks perfectly with the head. The OVR cameras don't seem to work with the UI system, probably because they utilize render textures and not screen space rendering. This dummy look camera solves that problem.

5. For every UI Canvas object you have in the scene, drag this "Look Camera" object into the "Event Camera" field.

6. create a new script called BasicLookInputModule.cs. Copy in this code:

using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using System.Collections;

public class BasicLookInputModule : BaseInputModule {

public const int kLookId = -3;
public string submitButtonName = "Fire1";
public string controlAxisName = "Horizontal";
private PointerEventData lookData;

// use screen midpoint as locked pointer location, enabling look location to be the "mouse"
private PointerEventData GetLookPointerEventData() {
Vector2 lookPosition;
lookPosition.x = Screen.width/2;
lookPosition.y = Screen.height/2;
if (lookData == null) {
lookData = new PointerEventData(eventSystem);
}
lookData.Reset();
lookData.delta = Vector2.zero;
lookData.position = lookPosition;
lookData.scrollDelta = Vector2.zero;
eventSystem.RaycastAll(lookData, m_RaycastResultCache);
lookData.pointerCurrentRaycast = FindFirstRaycast(m_RaycastResultCache);
m_RaycastResultCache.Clear();
return lookData;
}

private bool SendUpdateEventToSelectedObject() {
if (eventSystem.currentSelectedGameObject == null)
return false;
BaseEventData data = GetBaseEventData ();
ExecuteEvents.Execute (eventSystem.currentSelectedGameObject, data, ExecuteEvents.updateSelectedHandler);
return data.used;
}

public override void Process() {
// send update events if there is a selected object - this is important for InputField to receive keyboard events
SendUpdateEventToSelectedObject();
PointerEventData lookData = GetLookPointerEventData();
// use built-in enter/exit highlight handler
HandlePointerExitAndEnter(lookData,lookData.pointerCurrentRaycast.gameObject);
if (Input.GetButtonDown (submitButtonName)) {
eventSystem.SetSelectedGameObject(null);
if (lookData.pointerCurrentRaycast.gameObject != null) {
GameObject go = lookData.pointerCurrentRaycast.gameObject;
GameObject newPressed = ExecuteEvents.ExecuteHierarchy (go, lookData, ExecuteEvents.submitHandler);
if (newPressed == null) {
// submit handler not found, try select handler instead
newPressed = ExecuteEvents.ExecuteHierarchy (go, lookData, ExecuteEvents.selectHandler);
}
if (newPressed != null) {
eventSystem.SetSelectedGameObject(newPressed);
}
}
}
if (eventSystem.currentSelectedGameObject && controlAxisName != null && controlAxisName != "") {
float newVal = Input.GetAxis (controlAxisName);
if (newVal > 0.01f || newVal < -0.01f) {
AxisEventData axisData = GetAxisEventData(newVal,0.0f,0.0f);
ExecuteEvents.Execute(eventSystem.currentSelectedGameObject, axisData, ExecuteEvents.moveHandler);
}
}
}
}



7. Drag this script onto the EventSystem object in the scene.

8. fix Submit Button Name and Control Axis Name to match what you use in the Input Settings if you don't use Unity defaults.

9. disable or remove Standalone Input Module and Touch Input Module on the Event System object.

That's it. Push play. Look around with headset and you should see it highlight the buttons/sliders/etc. as you are looking around. When you hit the submit button it will trigger that UI element (buttons On Value Changed operations will be called if you set any of those up). Sliders get selected when you click them and can then be manipulated with the axis that was chosen on the BasicLookInputModule component.

I hope someone finds this useful since there isn't much out there on how to do this yet.

ccs
105 REPLIES 105

p4blo
Level 2
Great solution, works perfectly 🙂

Thanks so much for sharing

TomasRiker
Level 2
First of all, thanks for posting this.

There's a problem: I can't get dragging for the slider working, even though I checked "Use Look Drag Slider".
The scrollbar works.

Funnily, it works your pre-compiled version. So I guess something has changed in Unity since then.

Any ideas what that might be?

_Deleted_Us2025
Level 2
Lifted, nailed in, awesome! - man you rock.
Thanks for the share! 😄

dignifiedweb
Level 4
Thanks for sharing this, it worked so perfectly! I was easily able to grab your one script, add my own cursor, and add a look-based input to my UI. I appreciate the hard work! The sample project was really well done too, by the way.

Anonymous
Not applicable
Glad others have found this useful!

I'm sorry I haven't been able to respond to all the posts. I have my day job + trying to do a VR startup on the side, and I can barely keep up! I'll try to get back to this post at some point to see if I can correct any issues that have popped up.

ccs

Anonymous
Not applicable
I don't know if anyone else encountered this, but I updated from 4.6.0f1 to 4.6.3f1 today and all my clicks and button presses stopped working. It seems that now the cursor canvas is winning the raycast and processing all the events so they are not getting to the underlying UI object. To remedy this, simply disable or remove the Graphic Raycaster component on the Cursor so it won't receive events. I'm not sure why the Graphic Raycaster on the Cursor didn't win the raycasts before, but perhaps that was a bug that Unity remedied which is why it is popping up now in 4.6.3f1. I will update the sample project and try to upload a new version. I also plan to take a stab at 5.0 before too long and I will try to make sure this works with that.

ccs

Anonymous
Not applicable
I fixed up the issues others were seeing with drag issues and clicking with cursor and posted a new version of the project:

https://www.dropbox.com/s/3bpz5rgimbxdk ... 4.zip?dl=0

It looks like the previous version of my code broke in newer versions of unity because they removed the begin and end drag handlers from the slider component, and my code only enabled drag on slider if the call to begin drag actually executed. Now it tries to drag even if the component doesn't have a begin drag handler.

The above was built with Unity 4.6.4f1.

This version also adds a scaling cursor option which scales the size of the world cursor based on the distance it is being drawn at such that it should always appear the same size, but will always be at the right focal distance in the scene.

ccs

Hegarz
Level 2
Hey, firstly thanks a million for sharing this, however I'm having a bit of a problem.

I downloaded the example you've uploaded and I have that working completely fine, so I stirpped it down to just the cursor and one canvas and it works fine.

I've then tried to rebuild this in my project, seems to go fine in the sense that when I play the scene, the cursor gets centered, however from here on the cursor does not track with the headset and if I print our cursor.position in the UpdateCursor function in LookInputModule script the value does not change.

Do you have any ideas what might be causing this? Note I do not have the very latest OVR controller instead it is the version just before, I'm quite close to a project deadline so I don't want to replace the previous controller unless absolutely necessary.

Thanks again for the great work, and if you could get back to me that would be very much appreciated!

Edit: To update/elaborate further, it's now detecting rotation of the headset on the Y-axis giving horizontal movement, but nothing on the x axis to give vertical movement

Anonymous
Not applicable
Do you have the Event Camera set on the Canvas point to a dummy camera that must be placed under the CenterEyeAnchor transform that OVR provides under the camera rig? It should be placed at 0,0,0 position with 0,0,0 rotation. The attached images illustrate what has to happen. This camera is what is used to get the point that you are looking at, so it is important that it be placed dead center of the OVR cameras. If you are using an older OVR SDK that doesn't have CenterEyeAnchor, you can create your own under the LeftEyeAnchor and just offset it a little bit to the right (+x). You will have to experiment to get it to feel right.

eventcamera.png

Also make sure to set this dummy camera to Culling Mask = Nothing so it doesn't waste CPU/GPU rendering anything. Clear flags should also be set to Don't clear to prevent clearing any other rendering from other cameras.

eventcamera2.png

Lastly - the cursor will only appear when you are actually looking at a UI element. You should place a Panel under your Canvas in world space, and make sure the Canvas itself is set to World Space and is on the UI layer.

ccs

evolvingtech
Level 2
@CCS - Thank you very very much for you fine code example!

I do have a question... I am running Unity 5.0.1f1 and I get the following deprecation warning:

Assets/OVR/Scripts/Util/OVRGridCube.cs(146,35): warning CS0618: `UnityEngine.Renderer.castShadows' is obsolete: `Property castShadows has been deprecated. Use shadowCastingMode instead.'

Any thoughts on how to fix this?