Forum Discussion
Anonymous
11 years agoNew Unity UI + OVR Look-Based Input HOWTO
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:
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
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
Replies have been turned off for this discussion
- knowledgehammerHonored GuestAny possibility of creating a sample project or .unitypackage for download?
- ApprovedAnonymousYeah. I'll try to put one together. :)
- ApprovedAnonymousHere ya go. Includes latest code and a sample scene with a button, slider, scrollable text window, toggle, and input field all working. :)
https://dl.dropboxusercontent.com/u/87937814/LookInputSample.zip - ndavidenHonored GuestThanks for getting back so quickly! I I'll be sure to test this out when I have time tomorrow. I'll get back to you if I run into anything else with your code. :D
- AguaHonored GuestThanks for writing this out.
I'm just getting into the basics of UI stuff.
Hasn't been easy to find explanations of UI, especially VR related.
Always appreciated. - ezRocketProtege
"ccs" wrote:
Here ya go. Includes latest code and a sample scene with a button, slider, scrollable text window, toggle, and input field all working. :)
https://dl.dropboxusercontent.com/u/87937814/LookInputSample.zip
Slider doesn't work for me in the built demo.
Edit: ...because I don't have a controller :lol:
I'm gonna make a simple GUI that follows the camera like a HUD, will post it here once it's done and somewhat useable.
Can't find any tutorials or examples anywhere else so might as well make them ourselves :D
Also, you can enable a crosshair with "C" but at the moment it follows the mouse making it pretty much unusable as a tracker for where you're looking. Will disable and see if it's accurate enough to use.
Building a HUD = easy, making it follow the cam = hard. - weasel47Heroic ExplorerTo the OP, have you tried this with 5.0 at all? In 5.0.0b11, it throws this error while compiling:
Assets/Scripts/BasicLookInputModule.cs(48,83): error CS1061: Type `UnityEngine.EventSystems.RaycastResult' does not contain a definition for `gameObject' and no extension method `gameObject' of type `UnityEngine.EventSystems.RaycastResult' could be found (are you missing a using directive or an assembly reference?) - ApprovedAnonymousI'm stuck on 4.6 for now as my current project won't easily port to 5.0.
I guess they changed this particular class around. The 4.6 docs show gameObject as a valid field:
http://docs.unity3d.com/460/Documentation/ScriptReference/EventSystems.RaycastResult.html
I can't find 5.0 documentation. You might be able to figure this out by opening the code in the editor and poke around with the available fields on RaycastResult. What you need is the game object that was hit by the raycast. That is the UI element you are looking at. That needs to be passed the various events.
At some point I will dive into 5, but I unfortunately I don't have time to do that right now. - weasel47Heroic Explorer
"ccs" wrote:
I'm stuck on 4.6 for now as my current project won't easily port to 5.0.
I guess they changed this particular class around. The 4.6 docs show gameObject as a valid field:
http://docs.unity3d.com/460/Documentation/ScriptReference/EventSystems.RaycastResult.html
I can't find 5.0 documentation. You might be able to figure this out by opening the code in the editor and poke around with the available fields on RaycastResult. What you need is the game object that was hit by the raycast. That is the UI element you are looking at. That needs to be passed the various events.
At some point I will dive into 5, but I unfortunately I don't have time to do that right now.
Thanks! I had thought that autocomplete would show me what I needed, but it only listed "Equals" and "ReferenceEquals."
I just right-clicked -> Go to Declaration and found that there's a public GameObject property "go." I guess they changed the name.
Sure enough, I changed "pointerCurrentRaycast.gameObject" to "pointerCurrentRaycast.go" and it works now!
It looks like Sliders aren't covered. I'll see if I can figure out what they need... - ezRocketProtegeHas anyone managed to get the a UI component to properly follow the OVRcam?
Quick Links
- Horizon Developer Support
- Quest User Forums
- Troubleshooting Forum for problems with a game or app
- Quest Support for problems with your device
Other Meta Support
Related Content
- 1 year ago
- 2 years ago
- 2 years ago
- 6 months ago