Eye Tracker Stopped Working after Updating to 1.12.0

Give us as much detail as possible regarding the issue you're experiencing:

Unity Editor version: 2022.3.42f1
ML2 OS version: 1.12.0
Unity SDK version: 2.6.0
Host OS: Windows

Hi,

My eye tracker code had stopped working since the recent update. Log is as follows:

NullReferenceException: Object reference not set to an instance of an object.
  at MagicLeap.OpenXR.Features.EyeTracker.MagicLeapEyeTrackerFeature.GetStaticDataInternal () [0x00000] in <00000000000000000000000000000000>:0 
  at MagicLeap.OpenXR.Features.EyeTracker.MagicLeapEyeTrackerFeature.GetEyeTrackerData () [0x00000] in <00000000000000000000000000000000>:0 
  at EyeTracker.FixedUpdate () [0x00000] in <00000000000000000000000000000000>:0 

Given that the bug comes from GetStaticDataInternal(), I believe this probably isn't about my code implementation. The code ran well on OS 1.12.0 with Unity SDK 2.5.0 and MLSDK 1.10.0 before. I also had trouble reverting my Unity project to use the old sdk, since whenever I change the Unity package version it goes to "loading assets" forever and if I shut down my Unity project and reopen, the same log would show up after deployment (even though it's showed in the project setup tool that I'm on mlsdk 1.10.0 and unity sdk 2.5.0). I have many calls to the eye tracker API in my code, but I'll attach my code here:

    void Start()
    {
        // Request necessary permissions
        Permissions.RequestPermissions(new string[]
        {
            Permissions.EyeTracking,
            Permissions.PupilSize
        }, OnPermissionGranted, OnPermissionDenied);

        // InputSubsystem.Extensions.MLEyes.StartTracking()
        CenterEyePositionAction = new InputAction(binding: "<EyeGaze>/pose/position");
        EyeRotationAction = new InputAction(binding: "<EyeGaze>/pose/rotation");
        triggerAction = new InputAction(binding: "<MagicLeapController>/trigger");
        headRotationAction = new InputAction(binding: "<OpenXRHmd>/deviceRotation");
        CenterEyePositionAction.Enable();
        EyeRotationAction.Enable();
        triggerAction.Enable();
        headRotationAction.Enable();
    }

void FixedUpdate()
    {
        // Only proceed if both permissions have been granted
        if (!eyeTrackPermissionGranted || !pupilSizePermissionGranted)
            return;

        String row = "0";

        EyeTrackerData eyeTrackerData = eyeTrackerFeature.GetEyeTrackerData();
        bool hasData = eyeTrackerData.PosesData.Result == XrResult.Success;

        //Obtain gaze tracking input
        // vergence is gone in Unity SDK 2.5.0
        // bool hasData = _eyeTrackingDevice.TryGetFeatureValue(EyeTrackerUsages.vergencePosition, out Vector3 vergencePosition) &
        //               _eyeTrackingDevice.TryGetFeatureValue(EyeTrackerUsages.vergenceRotation, out Quaternion vergenceRotation);

        if (hasData)
        {
            fixationPoint = eyeTrackerData.PosesData.FixationPose.Pose.position;
        }
        else
        {
            fixationPoint = Vector3.zero;
        }



        if (eyeTrackerFeature != null && eyeTrackerFeature.enabled)
        {
            // Retrieve all eye-tracking data
            long currentTime = eyeTrackerData.GazeBehaviorData.Time / 1000000;
            if (prevGazeTime == currentTime)
            {
                // Debug.Log("Duplicate gaze time. Skipping frame: " + currentTime);
                return;
            }
            prevGazeTime = currentTime;


            row += "," + currentTime.ToString();
            // Debug.Log($"Gaze Time: {eyeTrackerData.PupilData[0].Time}");

            // Log Pupil Data
            foreach (var pupilData in eyeTrackerData.PupilData)
            {
                // Debug.Log($"Pupil Data - Eye: {pupilData.Eye}, Diameter: {pupilData.PupilDiameter} meters");
                row += "," + pupilData.PupilDiameter.ToString("F4");
            }

            // fixation point


            // Vector3 centerEyePosition = CenterEyePositionAction.ReadValue<Vector3>();
            // Quaternion centerEyeRotation = EyeRotationAction.ReadValue<Quaternion>();
            // or, use Eye Tracker instead of Input System
            Vector3 centerEyePosition = eyeTrackerData.PosesData.GazePose.Pose.position;
            Quaternion centerEyeRotation = eyeTrackerData.PosesData.GazePose.Pose.rotation;

            Vector3 centerEyeDirection = centerEyeRotation * Vector3.forward;
            Quaternion headRotation = headRotationAction.ReadValue<Quaternion>();
            row += "," + centerEyePosition.ToString("F3").Replace(",", "|");
            row += "," + centerEyeRotation.ToString("F3").Replace(",", "|");
            row += "," + centerEyeDirection.ToString("F3").Replace(",", "|");
            row += "," + fixationPoint.ToString("F3").Replace(",", "|");
            row += "," + headRotation.ToString("F3").Replace(",", "|")


            // Debug.Log($"Fixation Point: {fixationPoint}");
            // Debug.Log("Center Eye Position: " + centerEyePosition);
            // Debug.Log("Center Eye Rotation: " + centerEyeRotation);
            // Debug.Log("Center Eye Rotation Direction: " + centerEyeDirection);
            if (fixationPoint == Vector3.zero)
            {
                // Debug.Log("Vergence Point not found. Using Center Eye Position and Rotation.");
                fixationPoint = centerEyePosition + centerEyeRotation * Vector3.forward * 1f;
            }

            // cube at fixation point
            if (showFixationCube)
            {
                if (fixationCube == null)
                {
                    fixationCube = GameObject.CreatePrimitive(PrimitiveType.Cube);
                    fixationCube.AddComponent<Renderer>();
                    fixationCube.GetComponent<Renderer>().material = new Material(Shader.Find("Universal Render Pipeline/Lit"));
                    fixationCube.transform.localScale = new Vector3(0.025f, 0.025f, 0.025f);
                }
                fixationCube.transform.position = fixationPoint;
            }

            // Log Gaze Behavior Data
            GazeBehavior gazeBehavior = eyeTrackerData.GazeBehaviorData;
            // Debug.Log($"Gaze Behavior - Type: {gazeBehavior.GazeBehaviorType}, Duration: {gazeBehavior.Duration}, Amplitude: {gazeBehavior.MetaData.Amplitude}, Direction: {gazeBehavior.MetaData.Direction}, Velocity: {gazeBehavior.MetaData.Velocity}");
            row += "," + gazeBehavior.MetaData.Amplitude.ToString("F3");
            row += "," + gazeBehavior.MetaData.Direction.ToString("F3");
            row += "," + gazeBehavior.MetaData.Velocity.ToString("F3");
            row += "," + gazeBehavior.GazeBehaviorType.ToString();
            row += "," + gazeBehavior.Time.ToString();
            row += "," + gazeBehavior.OnsetTime.ToString();
            row += "," + gazeBehavior.Duration.ToString();

            // Log Geometric Data
            foreach (var geometricData in eyeTrackerData.GeometricData)
            {
                // Debug.Log($"Geometric Data - Eye: {geometricData.Eye}, Openness: {geometricData.EyeOpenness}, Position: {geometricData.EyeInSkullPosition}");
                row += "," + geometricData.EyeOpenness.ToString("F3");
            }

            // log gaze target data
            var ray = new Ray(centerEyePosition, centerEyeDirection);
            if (Physics.Raycast(ray, out RaycastHit hit, 15f, ~(1 << LayerMask.NameToLayer("Ignore Raycast"))))
            {
                row += "," + hit.transform.name;
            }
            else
            {
                row += ",None";
            }


            row += "," + triggerAction.ReadValue<float>().ToString("F3");

          

        




            if (showFixationCube)
            {
                switch (gazeBehavior.GazeBehaviorType)
                {
                    case GazeBehaviorType.Fixation:
                        fixationCube.GetComponent<Renderer>().material.color = Color.yellow;
                        break;
                    case GazeBehaviorType.Saccade:
                        fixationCube.GetComponent<Renderer>().material.color = Color.red;
                        break;
                    case GazeBehaviorType.Pursuit:
                        fixationCube.GetComponent<Renderer>().material.color = Color.green;
                        break;
                    case GazeBehaviorType.Blink:
                        fixationCube.GetComponent<Renderer>().material.color = Color.blue;
                        break;
                    case GazeBehaviorType.EyesClosed:
                        fixationCube.GetComponent<Renderer>().material.color = Color.gray;
                        break;
                }
            }
        }
    }

I am also a bit confused by the release note here - in the release note of 2.6.0, it says "Unity Developers that used the experimental Eye Tracker OpenXR Feature should update their Unity SDK to 2.5.0. The new 1.11.0 OS is incompatible with the previous version of the API." Is this a typo or should I stick with 2.5.0 and 1.11.0 OS?

If there's no quick fix to this, could you please advise on how to properly revert my Unity project?

Thanks in advance for your help!

You are correct that should have been 2.6.0 instead of 2.5.0. Are you using the the eye tracking for gaze tracking only?

I am doing gaze tracking, pupil size and gaze behavior, but it seems that EyeTrackerData eyeTrackerData = eyeTrackerFeature.GetEyeTrackerData();
would already through this error.

I was able to revert the project, so on OS 1.12.0, ML SDK 1.10.0 and Unity SDK 2.5.0 it works fine. Do you think it's an issue with MLSDK 1.11.0?

Thanks!

I'm not sure. Are you able to share the script and reproduction steps?