Search code examples
c#unity-game-enginegameobject

Unity WebGL Gameobject disabled from somewhere


So, I have a update running on a monobehaviour script(Let's call it Script A) that's in the scene. This update fires a event, so other non-monobehaviour scripts can listen to this when they need a update for something. However, at the start of the app it runs the update on Script A for a short time, but after a while it randomly stops calling the update on Script A.

So I started to place some debugs in standard monobehaviour functions like awake, start, disable, enable etc. Turns out the object is disabled from somewhere without me using or calling it anywhere. This problem only occurs on WebGL. In the editor the OnDisable event is never called and the update keeps running fine.

I tried various fixes, like all the debugs logs everywhere, I tried debugging the stacktrace to find out what is calling this OnDisable, saidly this doesn't show in the WebGL console. It just says: StackTrace:

public class UpdateManager : MonoBehaviour
{
    private static UpdateManager _instance;
    public static UpdateManager Instance
    {
        get
        {
            if (_instance == null)
            {
                _instance = FindObjectOfType<UpdateManager>();

                if (_instance == null)
                {
                    GameObject updateManager = new GameObject("UpdateManager");
                    _instance = updateManager.AddComponent<UpdateManager>();
                }
            }

            return _instance;
        }
    }

    public delegate void OnUpdateEvent();
    public event OnUpdateEvent OnUpdate;

    private void Awake()
    {
        Debug.Log("UpdateManager: Awake!"); 
    }     

    private void Start()
    {
        Debug.Log("UpdateManager: Start!"); 
    }

    private void OnEnable()
    {
        Debug.Log("UpdateManager: OnEnable!"); 
    }

    private void OnDisable()
    {
        Debug.Log("UpdateManager: OnDisable!, Stacktrace: " + UnityEngine.StackTraceUtility.ExtractStackTrace()); 
    }

    private void Update()
    {
        Debug.Log("UpdateManager: Update!");
        OnUpdate?.Invoke();
    }

I would like to know what is disabling this object since I have no clue. Good to note here is that it's only disabled once at the beginning, and after I enable it again it runs fine for the remaining time.

The only places I call this script is in a static class somewhere:

    private static void initializeRefreshCycle(int expiresIn)
    {
        if (expiresIn > 0)
        {
            if (_refreshRoutine != null)
            {
                CoroutineManager.Instance.Stop(_refreshRoutine);
                _refreshRoutine = null;
            }

            DateTime expirationDateTime = DateTime.Now;
            _refreshTime = expirationDateTime.AddSeconds(expiresIn * 0.85f);
            Debug.Log(string.Format("<< API TOKEN WILL BE AUTOMATICALLY REFRESHED IN {0} SECONDS >>", expiresIn * 0.85f));

            UpdateManager.Instance.OnUpdate += OnUpdateEarly;
        }
    }

And then the function that actually listens to the call:

   public static void OnUpdateEarly()
    {
        if (!HasAlmostExpired) return;

        SSOCommunicator.RefreshToken(_refresh);
        UpdateManager.Instance.OnUpdate -= OnUpdateEarly;
    }

Looks like the first time it stops somewhere, and once it reached the subscribing again, it runs fine for the remaining time.


Solution

  • I found out it's a garbage collection issue. Since I would always call UpdateManager.Instance to call a function I never had a hard reference to that instance. So it was somehow destroyed at start only on WebGL. I solved it by keeping a hard reference in the awake of a script. So just having a simgple _updatamanager = Updatemanager.Instance solved it.