Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Prefab required for every scene - DontDestroyOnLoad/DestroyImmediate Q

Discussion in 'Scripting' started by Lo-renzo, Aug 25, 2023.

  1. Lo-renzo

    Lo-renzo

    Joined:
    Apr 8, 2018
    Posts:
    1,318
    The Situation:

    I have a prefab "SceneCommon" with stuff that's common to every scene.

    There's one of these prefabs in every scene. It has the Camera, some managers, Canvases - nothing too special.

    I'd like to convert the SceneCommon to a DontDestroyOnLoad when I enter Play for the first time.

    The problem is that when I load a second scene during Play, there's a SceneCommon there.
    - I don't want to remove it because I want any scene to be playable.
    - I also don't want to instantiate the prefab instead of it already existing in the scene because I can't lose the camera and some other stuff
    - The various managers do things in Awake().

    My proposed solution is: DestroyImmediate.

    I know, huge caveats to using this, but unless I'm mistaken it should work in this situation. I have a script with an early DefaultExecutionOrder on the prefab, which in Awake checks to see if there's already a SceneCommon (singleton) and destroys itself if so.

    The result is that none of the second scene's SceneCommon or its children have an Awake()/Enable()/Disable() or even Destroy() called. The managers on the now-destroyed SceneCommon never have their Awake() called.

    As a result, when I load the second scene, the scene's existing SceneCommon is immediately destroyed and I should be able to go on my merry way using the DontDestroyOnLoad'd SceneCommon.

    So the ultimate questions are:

    - is this an unwise use of DestroyImmediate?
    - is there some other solution that is better?
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,558
    My only caveat is to make sure you never reach the end of a frame with no camera present.

    The reason is that on certain targets (like iOS and Android) this may introduce a frame of "glitchy noise" graphics, or perhaps a bright flash.

    ALSO I don't think there's any actual prohibition against DestroyImmediate. It just will tend to surprise a lot of people when you do it, but sometimes it is necessary. Destroy() doesn't happen until all Update()s are over with.

    For instance, if I want to CreatePrimitive() a Cube but I want to remove the BoxCollider and add a BoxCollider2D immediately, I cannot add the BoxCollider2D because it clashes with the BoxCollider, which even if I Destroy() it first, it still hangs around until end of the Update()s, preventing me from adding the BoxCollider2D.

    Solution:
    - create default cube primitve
    - GetComponent<Collider>() the BoxCollider
    - DestroyImmediate() that Collider
    - AddComponent<BoxCollider2D>()
     
    Lo-renzo likes this.
  3. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    I'm not sure, but are you making the Matrix? And you want the construct to always exist?

    DontDestroyOnLoad() prevents anything that, that main object has in it's children(hierarchy) from being deleted each scene. So if you made a "Main" object, with a Main.cs script, that declares DontDestroyOnLoad(). And have Directional Light, Main Camera, and whatever else childed to that, if you want to carry them through scenes? problem solved.

    But if you want to always have a main scene loaded, then look into
    SceneLoad.additively
    (or however it's written out). That way any extra scenes you run, can just be un-loaded, and you'll go back to that main scene with everything still there.

    However, if you just don't like that new scenes get made without a camera and other stuff, and don't really need a main scene to stay alive, then my mention on DontDestroyOnLoad() fixes that. Or worst case, you can always make a "setup" script that adds a new camera, directional light, etc...