Unity XR InputDevice Characteristics always None for Oculus Quest - unity3d

I am using the latest XR Interactive Toolkit in 2019.3.
I have an XR Rig in my game with the left and right hand XR Controllers.
I have a script of my own that I am looking at the XR controller InputDevice characteristics member to try to determine which hand the controller is.
The characteristics member is always None. Here is some of my code:
var characteristics = InputDeviceCharacteristics.HeldInHand | InputDeviceCharacteristics.Left;
bool leftHand = ((_controller.inputDevice.characteristics & characteristics) == characteristics);
Debug.Log(string.Format("is left hand: {0}, {1}, {2}, {3}", leftHand, _controller.inputDevice.characteristics, InputDeviceCharacteristics.HeldInHand, InputDeviceCharacteristics.Left));
The output for both controllers is: false, None, HeldInHand, Left
Is this a bug or is there something I need to do to prime it or get the characteristics to populate?

Quest controllers will not be recognized as HeldInHand. You can use:
List<InputDevice> allDevices = new List<InputDevice>();
InputDevices.GetDevices(allDevices);
You get 3 devices - Quest, Left and Right Controllers.
Then use a .contains filter to separate left and right controller inputs:
if (device.name.Contains("Right"))
{device.TryGetFeatureValue(CommonUsages.primary2DAxis, out localRightPrimaryAxis);
}

Related

what does find_interface: error in godot vr mean?

I was following this tutorial https://docs.godotengine.org/en/3.1/tutorials/vr/vr_starter_tutorial.html
for vr in godot and the first few lines of code are (in func _ready())
var VR = ARVRServer.find_interface("OpenVR") ###
if VR and VR.initialize():
get_viewport().arvr = true
get_viewport().hdr = false
OS.vsync_enabled = false
Engine.target_fps = 90
when I run the code I get the error find_interface: Condition "idx == -1" is true. Returned: _null
The program runs, but the camera is static and moving the headset doesn't do anything. Doing vr stuff atm is probably out of my league but I just wanted to play around with it. please let me know if you have a solution, thanks! (also i am using a samsung odyssey plus)

How do you get the rotation (or transform) of WMR motion controllers

Is there a way to access the rotation of a controller using WMRToolkit? I know about solvers, but they seem to focus on using position. For reference, the idea is simply to set the rotation of another gameobject to be the same as the rotation of the controller, which seems like it should be a simple task.Thanks in advance!
This document shows how to use Unity API to get the position and rotation of a motion controller:Getting a hand or motion controller's pose
Besides, there is a new XR input mapping system in Unity 2019.1, if you are using unity of 2019.1 or later, you can try the following code:
bool TryGetCenterEyeFeature(out Quaternion rotation)
{
InputDevice device = InputDevices.GetDeviceAtXRNode(XRNode.RightHand);
if (device.isValid)
{
if (device.TryGetFeatureValue(CommonUsages.deviceRotation, out rotation))
return true;
}
rotation = Quaternion.identity;
return false;
}

Godot TouchScreen swipe detector

I'm making a simple android mobile game in Godot3.1. I would need to make a swipe detector that would determine if the player swiped and in which direction (left or right).
I tried this:
var swipe_start = null
var minimum_drag = 100
func _unhandled_input(event):
if event.is_action_pressed("click"):
swipe_start = event.get_position()
if event.is_action_released("click"):
_calculate_swipe(event.get_position())
func _calculate_swipe(swipe_end):
if swipe_start == null:
return
var swipe = swipe_end - swipe_start
if abs(swipe.x) > minimum_drag:
if swipe.x > 0:
_right()
else:
_left()
This works when you click with your mouse and swipe but it doesn't work when you play it on your android phone.
Any ideas?
That code only considers clicks and not screen touches, to correct that you have two options:
Go to Project > Project Settings > Input Devices > Pointing and turn on the Emulate Mouse From Touch option.
Or use the following code:
func _unhandled_input(event):
if event is InputEventScreenTouch:
if event.pressed:
swipe_start = event.get_position()
else:
_calculate_swipe(event.get_position())
instead of:
func _unhandled_input(event):
if event.is_action_pressed("click"):
swipe_start = event.get_position()
if event.is_action_released("click"):
_calculate_swipe(event.get_position())
With the last solution the code only accounts for screen touches so you wont be able to test it on PC unless you go to Project > Project Settings > Input Devices > Pointing and turn on the Emulate Touch From Mouse

Inspector displays different rotation than script

I want to read out the X rotation of my camera.
The Inspector tells me "Rotation X = 10".
I would like to retrieve this value by code.
Therefore I added a script to my player gameobject and assigned the camera as "camera".
Then I used this code:
void Start()
{
Debug.Log("RotX World: " + camera.transform.rotation.x.ToString());
Debug.Log("RotX Local: " + camera.transform.localRotation.x.ToString());
This resulted in the value "0.08715578" instead of "10" (which is displayed by the Inspector).
What am I missing here?
Thank you!
I found the solution, I have to use eulerAngles like this, not camera.transform.rotation.
The correct way to store the rotation would be in a Vector3 like this:
_CameraRot = new Vector3(camera.transform.rotation.eulerAngles.x, camera.transform.rotation.eulerAngles.y, camera.transform.rotation.eulerAngles.z);
I wonder if what the Inspector shows under "Rotation" are actually the eulerAngles?

Navigation based on screen orientation (landscape or portrait) in Flash CS6

I'm creating an app that will have a different menu if the phone is held landscape, or portrait.
I figure I have to tell flash to move to a new frame when the phone moves from landscape to portrait or vice versa, but I'm not sure the exact code to after creating the orientation event listener.
There are two ways. Listen for a StageOrientationEvent or listen for Event.RESIZE. I personally prefer to use RESIZE as it is called slightly more often and keeps your interface in sync more.
var landscapeNav:Sprite; // this would be your landscape nav. Obviously does not have to be a Sprite
var portraitNav:Sprite; // same as landscapeNav, but this represents your portrait nav
stage.addEventListener( Event.RESIZE, this.stageResizeHandler );
function stageResizeHandler( e:Event ):void {
if ( stage ) { //just to make sure the stage is loaded in this class so we avoid null refs
if ( stage.stageWidth >= stage.stageHeight ) {
landscapeNav.visible = true;
portraitNav.visible = false;
}
else {
landscapeNav.visible = false;
portraitNav.visible = true;
}
}
}
This could definitely be cleaned up (landscapeNav.visible = stage.stageWidth > stage.stageHeight) but this should give you something to go on. If you want to do an animation as Atriace suggested, you would do a TweenLite/Max call within the conditional in the function instead of setting visible to true/false (after the animation is done, though, you should set visible to false just for the same of optimzation)
You don't need to create a new frame. In fact, it may be more visually appealing to watch the old menu slide off, and the new one to animate in (like with TweenLite).
The documentation on orientation change can be found # Adobe's ActionScript APIs specific to mobile AIR applications: "Screen Orientation", and the API.