Search Unity

How to avoid "GameObjects can not be made active when they are being destroyed"

Discussion in 'Scripting' started by Popsucker, Jun 3, 2019.

  1. Popsucker

    Popsucker

    Joined:
    Aug 21, 2018
    Posts:
    6
    When object A is destroyed, object B is set active.
    This works fine in game, but as I quit, both A and B are destroyed, which causes this error.
    This doesn't really impact the game in any way, but I'd like to avoid this error, how can I do so?
     
  2. TaleOf4Gamers

    TaleOf4Gamers

    Joined:
    Nov 15, 2013
    Posts:
    789
    Check if it has been destroyed?

    Code (CSharp):
    1. if(someGameObject != null)
    2. {
    3.     // Run code on non destroyed GameObject
    4. }
     
  3. Popsucker

    Popsucker

    Joined:
    Aug 21, 2018
    Posts:
    6
    At this point, object A is not yet null. It is still an object while it is being destroyed.
     
  4. Lysander

    Lysander

    Joined:
    Feb 24, 2013
    Posts:
    1,588
    Out of curiosity and because it may lead to a better answer (in methodology, rather than directly answering your question itself), how are you checking for ObjectA's destruction to enable ObjectB?

    Also, Equals() is overridden to check for destruction IIRC, so:
    Code (csharp):
    1. if(someGameObject == null || someGameObject.Equals(null))
    2.     return;
    ... may work.
     
    lordofduct likes this.
  5. Popsucker

    Popsucker

    Joined:
    Aug 21, 2018
    Posts:
    6
    That didn't work either

    I had used both
    Code (CSharp):
    1. if(a != null)
    2.    a.SetActive(true);
    3.  
    and

    Code (CSharp):
    1. a?.SetActive(true);
    and your solution of

    Code (CSharp):
    1. if(!a.Equals(null))
    2.    a.SetActive(true);
    doesn't catch it either.
     
    Last edited: Jun 4, 2019
  6. APSchmidt

    APSchmidt

    Joined:
    Aug 8, 2016
    Posts:
    2,080
    What are you trying to do exactly? Some kind of switch? There is an example of switch here: https://learn.unity.com/tutorial/en...omponents?projectId=5c8920b4edbc2a113b6bc26a#
     
    lordofduct likes this.
  7. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    5,666
    Something along these lines would be my suggestion. Haven't tested any of the code, just wrote it directly into the forum off the top of my head.

    Code (csharp):
    1. public class ShouldIInstantiate
    2. {
    3.     public static bool InstantiateObjectB = true;
    4. }
    Code (csharp):
    1. //Call this when you quit the game, do something similar when switching scenes as well
    2. public void QuitApplication()
    3. {
    4.     ShouldIInstantiate.InstantiateObjectB = false;
    5.     Application.Quit();
    6. }
    Code (csharp):
    1. public GameObject ObjectBPrefab;
    2.  
    3. //ObjectA OnDestroy method
    4. void OnDestroy()
    5. {
    6.     if (ShouldIInstantiate.InstantiateObjectB)
    7.     {
    8.         Instantiate(ObjectBPrefab);
    9.     }
    10. }
     
  8. Popsucker

    Popsucker

    Joined:
    Aug 21, 2018
    Posts:
    6
    Basically, I want to make an object appear (already existing, but deactivated) when a certain object is destroyed. This would mean setting gameobjects on and off, not its components. This object has many components attached to it, so I don't want to enable / disable each one.

    This might work, but is there a way to detect when a scene is changing, before OnDestroy is called? Or do I have to go track down every line that changes my scenes and add this to it?
     
  9. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    5,666
    Are your levels so different that you've got quite a large number of different places in your code where you change the scene? Whenever I have more than a few different scenes representing different levels, one of the first things I create is a scene switching manager with a single method I call to switch scenes.

    I don't know the answer on the callback for scene changing.

    Alternatively, in whatever code you're calling to destroy your ObjectA, you can there specifically instantiate ObjectB instead of leaving that for OnDestroy. Then you'd avoid the whole mess. For example, just add something like below to ObjectA and call this method instead when you want ObjectB to instantiate, and clear the instantiate stuff out of OnDestroy.

    Code (csharp):
    1. //Call this to destroy my GameObject instead of calling Destroy somewhere else
    2. //This avoids the mess of putting Instantiation of ObjectB in OnDestroy,
    3. //since this method won't be called on quit or scene change by Unity
    4. public void DestroyMe()
    5. {
    6.     Instantiate(ObjectBPrefab);
    7.     Destroy(gameObject);
    8. }
     
    Last edited: Jun 4, 2019