Crash on Application Exit in CesiumCreditSystem

On application exit, we encounter the following exception:

NullReferenceException: Object reference not set to an instance of an object
CesiumForUnity.CesiumCreditSystem.OnDestroy ()
(at ./Library/PackageCache/com.cesium.unity@17E2BCF9CFA2/Source/Runtime/CesiumCreditSystem.cs:174)

Suspected Cause

It appears that the CesiumCreditSystem prefab is loaded but never enabled. As a result:

  • OnEnable() is never called
  • The _images field remains uninitialized (null)
  • OnDestroy() is still invoked during application shutdown, leading to the NullReferenceException

Additional Observation

While debugging, a second issue was observed with the instantiated CesiumCreditSystem object:

  • After instantiation, the object is activated and OnEnable() is called as expected.

  • Subsequently, the following line is executed:

    creditSystemGameObject.hideFlags = HideFlags.HideAndDontSave;
    
  • This appears to trigger an additional OnEnable() call (possibly due to an internal disable/enable cycle when modifying hideFlags).

  • As a result:

    • Initialization logic in OnEnable() runs twice
    • The ForceUpdateCredits delegate is subscribed twice

Given that C# delegates allow duplicate subscriptions, this would lead to the handler being invoked multiple times (although I don’t know how to trigger that event, so it never happened with me). The delegate is removed only once in OnDestroy()

Hi @myavuzselim ,

Excellent debugging — you’ve identified two real bugs here and your analysis is spot on.

I looked at the current source and can confirm both issues:

Bug 1 (OnDestroy NullReferenceException): _images is only initialized in OnEnable(), but OnDestroy() accesses this._images.Count unconditionally. If the object is destroyed without ever being enabled, this crashes. There’s also a misplaced null check inside the loop — if (this._images != null) is inside the for loop body, where it can never help because this._images.Count has already been called to set up the loop. The guard needs to wrap the entire loop.

Bug 2 (double OnEnable() / double delegate subscription): In CreateDefaultCreditSystem(), Instantiate() activates the object and fires OnEnable(). Setting hideFlags = HideFlags.HideAndDontSave immediately after triggers an internal Unity disable/enable cycle, firing OnEnable() a second time and subscribing ForceUpdateCredits twice. Since OnDestroy() only unsubscribes once, one subscription leaks.

I’ll open a GitHub issue to track both fixes. A couple of quick questions:

  • Which versions of Cesium for Unity and Unity are you using?

  • Does the crash happen in standalone builds as well, or only in the Editor?

Thanks again for the thorough report!

I’ve opened a GitHub issue to track the fixes: [Bug] CesiumCreditSystem: NullReferenceException on exit + double OnEnable() subscription · Issue #685 · CesiumGS/cesium-unity · GitHub

Feel free to follow along there for updates. Thanks again for the thorough report!

Hi Jake.

It is Unity 6.2 (6000.2.15f1)

I have reproduced it with both.

Thanks for confirming

Follow along the two Github issues: