Search Unity

Question DontDestroyOnLoad not working for some objects

Discussion in 'Scripting' started by MidniteOil, Sep 21, 2021.

  1. MidniteOil

    MidniteOil

    Joined:
    Sep 25, 2019
    Posts:
    345
    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
    Code (CSharp):
    1.     private GameObject InstantiateGameObject(GameObject prefab, bool setActive)
    2.     {
    3.         var queue = GetQueue(prefab);
    4.         var gameObject = Instantiate(prefab);
    5.         DontDestroyOnLoad(gameObject);
    6.         gameObject.SetActive(setActive);
    7.         queue.Enqueue(gameObject);
    8.         return gameObject;
    9.     }
    Here's the script that's attached to the gameobject that will deactivate it when the particle effect stops
    Code (CSharp):
    1.     // If true, deactivate the object instead of destroying it
    2.     public bool OnlyDeactivate;
    3.    
    4.     void OnEnable()
    5.     {
    6.         StartCoroutine("CheckIfAlive");
    7.     }
    8.  
    9.     private void OnDestroy()
    10.     {
    11.         Debug.LogError($"{name} is being destroyed.");
    12.     }
    13.  
    14.     IEnumerator CheckIfAlive ()
    15.     {
    16.         ParticleSystem ps = this.GetComponent<ParticleSystem>();
    17.        
    18.         while(true && ps != null)
    19.         {
    20.             yield return new WaitForSeconds(0.5f);
    21.             if(!ps.IsAlive(true))
    22.             {
    23.                 if (OnlyDeactivate)
    24.                 {
    25. #if UNITY_3_5
    26.                         this.gameObject.SetActiveRecursively(false);
    27. #else
    28.                     this.gameObject.SetActive(false);
    29. #endif
    30.                 }
    31.                 else
    32.                 {
    33.                     GameObject.Destroy(this.gameObject);
    34.                 }
    35.                 break;
    36.             }
    37.         }
    38.     }
    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:
    upload_2021-9-21_18-13-41.png

    Note that it doesn't appear under DontDestroyOnLoad afterwards
    upload_2021-9-21_18-10-53.png
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,739
    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:

    Code (csharp):
    1. DontDestroyOnLoad( myGameObject.transform.root.gameObject);
    Are you parenting these things somewhere not marked DDOL? Because that will also de-DontDestroyOnLoad() them.
     
    CodeRonnie likes this.
  3. MidniteOil

    MidniteOil

    Joined:
    Sep 25, 2019
    Posts:
    345
    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).
     
    Kurt-Dekker likes this.
  4. kuruta-kurapika

    kuruta-kurapika

    Joined:
    Feb 11, 2023
    Posts:
    1
    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!