question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Getting intermittent null ref on SetGlobalListener

See original GitHub issue

Using the new MixedRealityCameraParent prefab, InputManager, etc. with updated code (both on master and 2017.2.0 versions) I’m getting an intermittent null ref exception on

InputManager.Instance.AddGlobalListener(gameObject)
NullReferenceException: Object reference not set to an instance of an object
HoloToolkit.Unity.InputModule.SetGlobalListener.OnEnable () (at Assets/HoloToolkit/Input/Scripts/Utilities/SetGlobalListener.cs:16)

Specifically, the instance variable is null.

In the current version of the script, OnDisable and OnDestroy wrap the RemoveGlobalListener call in an if statement

private void OnDisable()
    {
        if (InputManager.Instance != null)
        {
            InputManager.Instance.RemoveGlobalListener(gameObject);
        }
    }

But OnEnable does not:

private void OnEnable()
    {
        InputManager.Instance.AddGlobalListener(gameObject);
    }

Presumably, this should be

private void OnEnable()
    {
       if (InputManager.Instance != null)
        {
            InputManager.Instance.AddGlobalListener(gameObject);
        }
    }

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:22 (10 by maintainers)

github_iconTop GitHub Comments

3reactions
genereddickcommented, Oct 22, 2017

OK. I’ve also mostly used single scenes, but for larger projects I’m not sure how well this scales – maybe just an unwarranted assumption on my part from looking at other Unity projects. Perhaps I’m also abusing Singletons in my project.

It might be helpful to have an project in the HoloToolkit-Examples that uses multiple scenes so that cross scene issues can be detected.

One additional question about this is the hard dependency between the MixedRealityCameraParent’s SetGlobalListener script and the InputManager. Because of the lack of a null check on the OnEnable function, if you don’t have an InputManager in the scene – for example if you have a short-lived splash scene that doesn’t allow interactivity – it will throw an error.

  private void OnEnable()
    {
        InputManager.Instance.AddGlobalListener(gameObject);
    }

Maybe this is necessary as other assets in the MixedRealityCameraParent, such as MixedRealityTeleport, depend on it, but if so the dependency should be make explicit (maybe it is, haven’t looked at the documentation recently). Otherwise, seems like they could be refactored to allow for separate inclusion in a scene.

1reaction
genereddickcommented, Oct 21, 2017

I have a working theory that seems to explain the behavior (sorry, behaviour) and the inconsistency.

The two objects interacting are the MixedRealityCameraParent gameobject and attached script SetGlobalListener and the InputManager gameobject with the attached InputManager script inheriting from Singleton.

Awake is effectively random as to when it is called. But, so is OnDestroy. OnEnable can have dependencies as to when called. Static values are preserved across scene loads.

Two scenes each with a MixedRealityCameraParent and an InputManager. When the transition between the scenes is called, the order in which the two objects are destroyed is important.

If the camera is destroyed first the SetGlobalListener OnDestroy checks for null on the InputManager.Instance.

if (InputManager.Instance != null)

Because this is not yet null, the InputManager.Instance.RemoveGlobalListener function is called. Next the InputManager is destroyed and the Singleton static values are reset and ready for the new scene. All is OK.

If the InputManager is destroyed first, the gameobject is destroyed and the Singleton static values reset and ready for the new scene. Now the camera is destroyed. SetGlobalListener calls its OnDestroy method which checks

if (InputManager.Instance != null)

Now though, the Instance is null and searchForInstance has been reset to true. So in the Singleton Instance property, we hit this:

public static T Instance {
        get {
           if (instance == null && searchForInstance)  {
                searchForInstance = false;
                T[] objects = FindObjectsOfType<T>();
                if (objects.Length == 1) {
                    instance = objects[0];
                } else if (objects.Length > 1) {
                    Debug.LogErrorFormat("Expected exactly 1 {0} but found {1}.", typeof(T).ToString(), objects.Length); }
            }
            return instance;
        }
    }

This resets searchForInstance to false. But, there is nothing to return from FindObjectsOfType<T> as the InputManager has already been destroyed. The new scene loads but the static value of searchForInstance survives the scene transition.

Now, if the InputManager loads before the MixedRealityCameraParent, the InputManager Singleton Awake method works properly, reassigns the Singleton Instance property, the searchForInstance value is still false but that is now correct, and all is again OK.

However, if the MixedRealiityCameraParent loads first, then the SetGlobalListener OnEnable gets called, but because the static searchForInstance is still false and the instance is still null, accessing InputManager.Instance throws the nullreference exception.

private void OnEnable() {
        InputManager.Instance.AddGlobalListener(gameObject);
  }

After this the InputManager Awake is called and you still get a functioning inputmanager. Though I think things are still in a bad state as the MixedRealityCameraParent is never added to the AddGlobalListener call.

This seems to mactch what I’m seeing, especially when I include the timing of the SetGlobalListener OnEnable, OnDisable and OnDestroy functions.

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to fix sporadic null reference exception when ...
1. Use object initializer (also set IsEnabled = true instead of calling Start() ). · 4. Why would you want to do that?...
Read more >
Intermittent (Null Reference Exception) - SQL Server
This error occur in an intermittent matter on our production server and we cannot reproduce it on our dev. environment.
Read more >
NullReferenceException in Singleton intermittently
When I run with the MonoDeveloper attached to the Unity process, sometimes I get a NullReferenceException. MonoDeveloper just pauses on a ...
Read more >
Why are null references shunned while throwing ...
Sometimes that handling might involve throwing another exception, but you should never be letting a null reference exception go unhandled. Ever.
Read more >
Fix Null Reference Exception in Unity - YouTube
Here I have another debugging tutorial on how to fix a NullReferenceException error in Unity. This lesson will teach you more about ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found