Fatal : StackOverflow exception during entering Main Thread

  1. Introduction:
    I was Loading my single-tons in the first scene,
    But StackOverflow exception occured.
    (on a function with name containing ‘enter’ and ‘main’ and ‘thread’)
    And then, My engine suddenly quit.

  2. Reproducible codes :


     StartLoad.cs

using UnityEngine;
using UnityEngine.SceneManagement;

public class StartLoad : MonoBehaviour
{
    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        GameObject.Find("ObjectPoolManager").GetComponent<ObjectPoolManager>().LoadScene("MainScreen");
    }
}

ObjectPool.cs : Used In ObjectPoolManager.cs
using UnityEngine;
using System.Collections.Generic;

[System.Serializable]
public class ObjectPool<Type> : IPool where Type : IPoolable
{
    [SerializeField]
    private List<GameObject> DisabledGameObjects;
    [SerializeField]
    private List<GameObject> EnabledGameObjects;
    [SerializeField]
    private int capacity;
    [SerializeField]
    private bool isDontDestroyOnLoad;
    public ObjectPool(int capacity = 100, bool isDontDestroyOnLoad = true)
    {
        this.capacity = capacity; DisabledGameObjects = new List<GameObject>(); EnabledGameObjects = new List<GameObject>(); this.isDontDestroyOnLoad = isDontDestroyOnLoad;
    }

    public GameObject Instantiate(GameObject original, Transform parent)
    {
        GameObject gameObject;
        if (DisabledGameObjects.Count == 0)
        {
            if (EnabledGameObjects.Count < capacity)
            {
                gameObject = Object.Instantiate(original, parent);

            }
            else
            {
                throw new System.Exception($"ObjectPool is Full.\ncapacity : {capacity}");
            }
        }
        else
        {
            gameObject = DisabledGameObjects[0];
            DisabledGameObjects.Remove(gameObject);
            gameObject.SetActive(true);
            gameObject.GetComponent<Type>().Start();
        }
        EnabledGameObjects.Add(gameObject);
        gameObject.transform.SetParent(parent);
        return gameObject;
    }

    public void Destroy(GameObject gameObject)
    {
        EnabledGameObjects.Remove(gameObject);
        DisabledGameObjects.Add(gameObject);
        gameObject.transform.SetParent(null);
        if (isDontDestroyOnLoad)
        {
            Object.DontDestroyOnLoad(gameObject);
        }
        gameObject.SetActive(false);
    }

    public void DestroyEverything()
    {
        foreach(GameObject gameObject in EnabledGameObjects)
        {
            Destroy(gameObject);
        }
    }

}

public interface IPoolable
{
    public void Start();
}

public interface IPool
{
    public GameObject Instantiate(GameObject original, Transform parent);
    public void Destroy(GameObject gameObject);
    public void DestroyEverything();
}

ObjectPoolManager.cs
using System.Collections.Generic;
using UnityEngine;

public class ObjectPoolManager : MonoBehaviour
{
    [SerializeField]
    private List<IPool> objectPools = new List<IPool>();

    [SerializeField]
    private List<string> poolNames = new List<string>();

    void Start()
    {
        DontDestroyOnLoad(gameObject);
    }

    // Update is called once per frame
    void Update()
    {
    }

    void OnEnable()
    {
    }

    public IPool newPool<T>(string name) where T : IPoolable
    {
        IPool pool = new ObjectPool<T>();
        objectPools.Add(pool);
        poolNames.Add(name);
        return pool;
    }

    public IPool GetPool(string name)
    {
        for (int i = 0; i < poolNames.Count; i++)
        {
            if (poolNames[i] == name)
            {
                return objectPools[i];
            }
        }
        return null;
    }

    public IPool GetOrNewPool<T>(string name) where T : IPoolable
    {
        IPool pool = GetPool(name);
        if (pool == null)
        {
            return newPool<T>(name);
        }
        else
        {
            return pool;
        }
    }

    public void LoadScene(string scene)
    {
        foreach (IPool pool in objectPools)
        {
            pool.DestroyEverything();
        }
        GameObject.Find("ObjectPoolManager").GetComponent<ObjectPoolManager>().LoadScene(scene);
    }
}

Although, there is my fault, putting function in Update()

Resolved now : Infinite recursion in Update() quits the program.
But It Could be also Engine bug.

void recursion()
{
    recursion();
}
void Update()
{
    recursion();
}

this would produce bug.

No, you don’t have an infinite recursion in Update and it’s not an engine bug. You have an infinite recursion inside your LoadScene method since you call LoadScene again at the end of the method. That’s the issue. So line 65 in ObjectPoolManager is the issue. Your LoadScene method also does not load any scenes. All you do it iterating through your pools to destroy everything and then you recursively call the method itself.

Of course, putting your method call in Update also doesn’t make much sense but it’s not the issue.

1 Like