DontDestroyOnLoad not working for some objects

Greetings,

I’m optimizing one of my games and have added object pooling. I’m using the typical approach where I have a dictionary mapping prefab names to a queue.

It’s working fabulously except for one prefab. It’s a pretty simple GameObject with some particle effects (explosion).

When I spawn a new object, if I didn’t find an existing one in the pool that’s not already active I Instantiate a new one and immediately call DontDestroyOnLoad on it and then add it to the pool.

It’s working great inside the scene and it gets used repetitively, no problem.

But when I Load a new scene it’s getting destroyed (confirmed with a breakpoint in OnDestroy() on an attached script.

I also noted that that gameobject doesn’t show up under DontDestroyOnLoad in the scene. I step through in the debugger and see the DontDestroyOnLoad() getting executed but it doesn’t get added to DontDestroyOnLoad in the scene.

Here’s where I instantiate new gameobjects and add them to the pool

    private GameObject InstantiateGameObject(GameObject prefab, bool setActive)
    {
        var queue = GetQueue(prefab);
        var gameObject = Instantiate(prefab);
        DontDestroyOnLoad(gameObject);
        gameObject.SetActive(setActive);
        queue.Enqueue(gameObject);
        return gameObject;
    }

Here’s the script that’s attached to the gameobject that will deactivate it when the particle effect stops

    // If true, deactivate the object instead of destroying it
    public bool OnlyDeactivate;
   
    void OnEnable()
    {
        StartCoroutine("CheckIfAlive");
    }

    private void OnDestroy()
    {
        Debug.LogError($"{name} is being destroyed.");
    }

    IEnumerator CheckIfAlive ()
    {
        ParticleSystem ps = this.GetComponent<ParticleSystem>();
       
        while(true && ps != null)
        {
            yield return new WaitForSeconds(0.5f);
            if(!ps.IsAlive(true))
            {
                if (OnlyDeactivate)
                {
#if UNITY_3_5
                        this.gameObject.SetActiveRecursively(false);
#else
                    this.gameObject.SetActive(false);
#endif
                }
                else
                {
                    GameObject.Destroy(this.gameObject);
                }
                break;
            }
        }
    }

And yes, I’ve confirmed that OnlyDeactivate is true. The object is being destroyed when loading a new scene, not when the particle effect stops.

Here’s a screenshot showing where the object has been Instantiated, DontDestroyOnLoad is called and it’s added to the pool:

Note that it doesn’t appear under DontDestroyOnLoad afterwards
7512038--926218--upload_2021-9-21_18-10-53.png

It’s not the problem but I would recommend staying away from using the property shortcut gameObject in your lines 4 through 6… at a minimum it is prima facie confusing and adds needless extra noise to the brain cage when reading your code.

You can’t mark any old GameObject as DDOL. It has to be a root GameObject. One way to ensure you are doing this is to be explicit:

DontDestroyOnLoad( myGameObject.transform.root.gameObject);

Are you parenting these things somewhere not marked DDOL? Because that will also de-DontDestroyOnLoad() them.

1 Like

Dude, whatever you’re getting paid to help us out it isn’t enough - lol.
You nailed it. For that particular prefab I was parenting it to the transform of another GameObject which is why DontDestroyOnLoad() didn’t work for it.

I will remove the overload I put on my ObjectPooler that took SpawnGameObject(GameObject prefab, Transform parentTransform) and just use the one that takes a prefab, Vector3 (position) and Quaternion (rotation).

1 Like

OMG, I was having this problem for days now, lots of my gameobjetcs not working with DontDestroyOnLoad() and the reason was because I was parenting them. Can’t believe it. Thank you for the indirect solution!