Hi,
I’m using the new XR Toolkit on 2019.4.8f. I’ve set up a stationary XR rig with the Tracked Pose Driver set to Rotation only mode. When I move around in the app my controllers get offset by the movement, making them float off in the distance. I assume this offset it applied within the XR Controller class.
Is there a quick fix I could apply?
Solution
Inside the XRController.cs I’ve added a couple of lines of code
0. Add dependency of
using UnityEngine.SpatialTracking;
- Make property that will allow you to track the head of the user
private InputDevice m_HeadInputDevice;
....
public InputDevice headInputDevice
{
get
{
return m_HeadInputDevice.isValid ? m_HeadInputDevice : (m_HeadInputDevice = InputDevices.GetDeviceAtXRNode(XRNode.CenterEye));
}
}
- Inside the Awake function find and initiate the tracking type
private TrackedPoseDriver.TrackingType m_trackingType;
....
var trackedPoseDriver = FindObjectOfType<TrackedPoseDriver>();
m_trackingType = trackedPoseDriver.trackingType;
- Find this line of code
if (inputDevice.TryGetFeatureValue(CommonUsages.devicePosition, out devicePosition))
transform.localPosition = devicePosition;
and replace it with
if (inputDevice.TryGetFeatureValue(CommonUsages.devicePosition, out devicePosition))
{
if (m_trackingType == TrackedPoseDriver.TrackingType.RotationOnly)
{
if (headInputDevice.TryGetFeatureValue(CommonUsages.centerEyePosition, out centerEyePosition))
{
transform.localPosition = devicePosition - centerEyePosition;
}
}
else
{
transform.localPosition = devicePosition;
}
}
This will essentially offset the controller position using the head position.
Update:
Here is a standalone class that you can use instead XRController
public class OculusController : XRController
{
private InputDevice _headInputDevice;
private TrackedPoseDriver.TrackingType _trackingType;
private InputDevice HeadInputDevice
{
get
{
return _headInputDevice.isValid
? _headInputDevice
: (_headInputDevice = InputDevices.GetDeviceAtXRNode(XRNode.CenterEye));
}
}
private void Start()
{
var trackedPoseDriver = FindObjectOfType<TrackedPoseDriver>();
_trackingType = trackedPoseDriver.trackingType;
}
protected override void OnBeforeRender()
{
//No way to check if enabled as m_UpdateTrackingType is private
UpdateTrackingInputOverride();
}
private void LateUpdate()
{
UpdateTrackingInputOverride();
}
private void UpdateTrackingInputOverride()
{
if (_trackingType != TrackedPoseDriver.TrackingType.RotationOnly) return;
//Try to get device position
if (!inputDevice.TryGetFeatureValue(CommonUsages.devicePosition, out var devicePosition)) return;
//Try to get center eye position
if (HeadInputDevice.TryGetFeatureValue(CommonUsages.centerEyePosition, out var centerEyePosition))
{
transform.localPosition = devicePosition - centerEyePosition;
}
}
}