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

Anonymous
Not applicable
Just to be sure, I confirmed the zip file I posted in the 1st post works with Unity 5.1.2p2 (and probably other Unity 5 versions) and OVR runtime 0.6.0.1. It does require 1 small fix to OVRMainMenu.cs to be compliant to new API:

Change line 283 to this:
#if UNITY_5_0 || UNITY_5_1 || UNITY_5_2

Then it should work as posted. Keep in mind this is using old legacy-integration and not new built-in VR mode that is now available in Unity. I'll see if I can find time to create and post an updated version that uses new native integration.

I haven't tried running 0.7.0.0 runtime yet either. I'm in the process of moving to that now for my other projects, and I'll try this one out just to make sure it still works.

kshaja
Honored Guest
Hi, great work!
Did you had a time to check the new Unity 5.2 version with your code and example . As it support 0.7 runtime now.
Thanks for the share 🙂

GroundControlGa
Explorer
Hey there,

This work is awesome, but it won't run properly on Unity 5.2.2 . I get all sorts of weird behaviours (flickering, no image, etc.) and the interactions won't work.

Anyone else managed to get it working under Unity 5.2.2?

Anonymous
Not applicable
Here is an updated version of the project that works with 5.2.1p2 (5.2.2 should work as well) and uses Native VR + 0.1.2 Oculus Utils so it is compatible with latest Oculus runtimes (0.7 or 0.8):

https://www.dropbox.com/s/g8ptl7w9xdewp ... 5.zip?dl=0

I'll update the 1st post as well. I'll leave the old version linked there in case anyone wants to still use the old Oculus integration.

ccs

motorsep
Rising Star
Does it use uGUI and does it work on Gear VR ?

Anonymous
Not applicable
Yes it uses uGUI and yes it works with GearVR with a bluetooth controller and limited function with the touchpad. If you want to get fancier with the GearVR touchpad to add scrolling of scrollbars or use it to control the cursor beyond just center look position, that is something you would have to add. Currently scrolling is mapped to right stick y-axis and trigger axis (on an xbox 360 controller on desktop). The touchpad, however, will work as equivalent button press/release and allow you to control everything in this scene with look based scroll or submit.

ccs

GroundControlGa
Explorer
"ccs" wrote:
Here is an updated version of the project that works with 5.2.1p2 (5.2.2 should work as well) and uses Native VR + 0.1.2 Oculus Utils so it is compatible with latest Oculus runtimes (0.7 or 0.8):

https://www.dropbox.com/s/g8ptl7w9xdewp ... 5.zip?dl=0

I'll update the 1st post as well. I'll leave the old version linked there in case anyone wants to still use the old Oculus integration.

ccs


It's working like a charm now on Unity 2.2.2. Great work my friend 😉

vrguy2
Protege
Hi guys, so I'm trying to make a Gear VR app that showcases some various models with different animations on each model, using various button they press on the wall in VR. I have about 10 of these models, all with animator controllers attached. I'm using the button script from this post (with the gaze based looking/selection).

The issue is I have no idea how to make so after I click the button it spawns one of the models I specify from my assets folder, plays the animation in the model (fbx models with animator controller that is attached to the model too) and plays the sound for that animation. I tried messing with the on click () stuff that was included, it was directed to a testevents script but I didn't know what to do with that.

I feel like what I'm trying to do is a very simple concept but I have been spending over a week now! Any help would be greatly appreciated. I really want to make this Gear VR app happen. Do I need a special script to replace the testevents script to make this happen?

peterept
Protege
What you can do is, create a prefab for your animation, then instantiate the prefab when they click the button.

Firstly, create a game object at 0,0,0 and add your animation as a child. Add your audio source and set it to play automatically (so if you hit PLAY in editor you hear the sound immeadiately). Add your animation and set it to play automatically (in your FBX import animations).

OK, if you hit play and everything looks good you are 3/4 of the way there.

Now, drag that game object into the project to save it as a prefab.

Now, create a script to add to each button that has a variable for a prefab and a location to spawn it. Give it a script to handle the click. Then drag your prefab onto the variable, and your spawn location, and also tell your button's click event to call that method.

Here's some rough pseudo code:

class SpawnAnimation : MonoBehaviour
{
public GameObject prefab;
public Transform spawnTransform;

public void Spawn()
{
GameObject go = (GameObject)Instantiate(prefab, spawnTransform.position, Quaternion.identity);
go.SetParent(spawnTransform);
}
}

vrguy2
Protege
Thank you peterept. this gives me some hope to finally figure this out. I'll be back tomorrow (posting from my phone) and let you know if it worked!