ultraleap / UnityPlugin

Ultraleap SDK for Unity.
https://docs.ultraleap.com/unity-api/
Apache License 2.0
531 stars 168 forks source link

Infinite Editor GUI loading loop when tracking service is not installed or not running on system #1618

Closed HakimW closed 6 months ago

HakimW commented 6 months ago

Since updating to the latest stable (6.15.0), there is an issue originating from the ServerStatus class throwing a NullReferenceException at line 30, causing Unity to go into an infinite GUI loading loop, rendering Unity completely unresponsive.

The line causing the Exception in the ServerStatus class is the following:

lastStatus = Marshal.PtrToStructure<LeapC.LEAP_SERVER_STATUS>(statusPtr);

At the top of the callstack is the LeapTrackingProvider.OnDrawGizmos function at line 1148, where it is attempting to call the DetectConnectedDevice function.

As far as we have tested, this error can be reproduced by simply installing the latest version of the package into a unity project, add a LeapXRServiceProvider to the scene and quit the Ultraleap Tracking software on the System (or just not having the software installed on the system at all).

Altough this won't happen when the Ultraleap Tracking software is installed and running it is very inconvenient to develop with this issue since not every team member and freelancer working on our project has the tracking software installed and they should not be required to install it to develop on features in the project that are completely independent from the Ultraleap implementation.

This issue does not appear when manually downgrading to the 6.14.0 version of the package.

MattGrayUL commented 6 months ago

Thanks for raising this! I'll get it fixed for the next release :)

If you need a temporary fix, you can limit the GUI lockup time to <1s by having a local version of the Plugin (either via a local Git package, or via .unitypackage) and editing ServerStatus.GetStatus() to be like this:

public static void GetStatus()
{
    if (lastRequestTimestamp + requestInterval < Time.realtimeSinceStartup)
    {
        IntPtr statusPtr = new IntPtr();
        LeapC.GetServerStatus(500, ref statusPtr);

        if (statusPtr != IntPtr.Zero)
        {
            lastStatus = Marshal.PtrToStructure<LeapC.LEAP_SERVER_STATUS>(statusPtr);

            MarshalUnmananagedArray2Struct(lastStatus.devices, (int)lastStatus.device_count, out lastDevices);
            LeapC.ReleaseServerStatus(ref lastStatus);
        }

        lastRequestTimestamp = Time.realtimeSinceStartup;
    }
}
MattGrayUL commented 6 months ago

Linked a PR to track with this issue here https://github.com/ultraleap/UnityPlugin/pull/1619

HakimW commented 6 months ago

Awesome, thank you for the quick response!

MattGrayUL commented 6 months ago

this has been merged into develop and will go out with the next release :)