Search Unity

GearVR InputTracking.GetNodeStates results in stutter

Discussion in 'AR/VR (XR) Discussion' started by DAVcoHL, Sep 8, 2017.

  1. DAVcoHL

    DAVcoHL

    Joined:
    May 3, 2017
    Posts:
    15
    I'm building a GearVR app in which I use VRDevice.DisableAutoVRCameraTracking(camera, disabled) to disable the 'automatic' built-in unity VR tracking of the camera, and instead set the position and rotation myself using values from InputTracking.GetNodeStates().

    When I do this, however, I see a noticeable stutter when turning my head from side-to-side when deployed to GearVR (doesn't seem to occur on Rift). I'm not sure of the cause.

    I've tested this in a practically empty scene (so framerate is not an issue) where a button press toggles the camera view between a camera with my tracking and a camera with the 'builtin' unity tracking. The 'builtin' tracking is noticeably smoother.

    I have also tried updating the transform values of my camera in just Update(), just FixedUpdate() and both Update() and FixedUpdate() with no noticeable effect.

    I believe this to be a problem with the values reported by InputTracking.GetNodeStates() or the way in which I am using it. Can anyone comment, or tell me what I'm doing wrong?

    The code snipped below shows my setup for 'manually' setting the camera transform;
    Code (CSharp):
    1.     private void Awake()
    2.     {
    3.         VRDevice.DisableAutoVRCameraTracking(centerEyeCam, true);
    4.     }
    5.  
    6.  
    7.     void UpdateNode()
    8.     {
    9.         InputTracking.GetNodeStates(nodeStates);
    10.         for (int i = 0; i < nodeStates.Count; ++i)
    11.         {
    12.             if (nodeStates[i].nodeType == VRNode.CenterEye)
    13.             {
    14.                 Vector3 position;
    15.                 if (nodeStates[i].TryGetPosition(out position))
    16.                     centerEyeCam.transform.localPosition = position;
    17.  
    18.                 Quaternion rotation;
    19.                 if (nodeStates[i].TryGetRotation(out rotation))
    20.                     centerEyeCam.transform.localRotation = rotation;
    21.             }
    22.         }
    23.     }
     
  2. DAVcoHL

    DAVcoHL

    Joined:
    May 3, 2017
    Posts:
    15
    After much head scratching, I've found that the correct way to get smooth tracking while 'manually' setting position/rotation is to update the transform of the camera in the OnPreRender callback.

    I'm guessing that the tracked eye position is updated in a much faster loop that Unity's render/physics update and has changed between the last Update and Render call, resulting in image stutter. So the only way to get a transform that matches the rendered image is to update the transform at the last possible moment.
     
  3. Matt_D_work

    Matt_D_work

    Unity Technologies

    Joined:
    Nov 30, 2016
    Posts:
    202
    Apologies, I missed this at the time.

    Actually, if you look at the tracked pose driver, we update in OnBeforeRender, which happens in the right place. If you cant get away with using the Tracked Pose Driver, then that would be a much better place than OnPreRender.
     
  4. DAVcoHL

    DAVcoHL

    Joined:
    May 3, 2017
    Posts:
    15
    Thanks for the reply Matt. I've since switched to the TrackedPoseDriver, which works fine (I don't think it was available at the time). Interesting about OnBeforeRender - I wasn't aware that function existed.