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

Prefabs in addressable scenes

Discussion in 'Addressables' started by SpiralCircus, Jan 27, 2021.

  1. SpiralCircus

    SpiralCircus

    Joined:
    Feb 1, 2014
    Posts:
    34
    If I place a prefab into an addressable scene then build the addressables groups, that prefab is duplicated and bundled in with the scene, to be unloaded again when the scene is unloaded. The original prefab (which is also addressable and bundled in with another group) is seemingly forgotten about and is not used in the scene at all.

    This means, if you unload the scene, the prefab's data is unloaded too. So if, for example you try to have a prefab survive between two scenes (e.g. pick it up in scene A, set DontDestroyOnLoad, carry it to scene B, unload scene A as scene B loads), it loses its textures, materials, meshes etc.

    I am really struggling to understand why the dependency analysys can't identify that at as prefab from another bundle and simply reference that instead, so that I could keep a bundle with common assets in memory throughout the game.

    The only solution i can find right now is to swap the instantiated prefab in the scene with a script that instantiates it at runtime. If I do that I can ensure the prefab comes from its correct bundle and isn't packed into the scene.

    This is not a solution for me, since prefabs might have many scene-specific editor connections (references to other GOs in the scene, dragged into fields in the inspector, for example), and a bunch of overrides to the base prefab's values, which every "intantiator" script would have to duplicate. Our design workflow makes heavy use of the scene editor hierarchy, and many prefabs are placed at design time and then hooked up to eachother in complex ways.

    To me this has completely broken the prefab workflow in unity, not to mention ballooned my build size as seemingly every scene is generating copies of all their prefabs instead of sharing them.

    Can someone help me understand why it works this way? Or correct me if I'm misunderstanding how it works.
     
  2. FlorianBernard

    FlorianBernard

    Joined:
    Jun 9, 2015
    Posts:
    165
    @dc5774 I'm facing the exact same problem and just created another thread about it. Did you figure it out by any chance?
     
  3. SpiralCircus

    SpiralCircus

    Joined:
    Feb 1, 2014
    Posts:
    34
    No not yet, I'm having to instantiate it via script. It seems like this is actually the designed behaviour. What I want is for the scene to reference the bundle in which the prefab is containe,d and so mark it as a dependecy.

    When the scene is loaded it could resolve its dependencies and look for the bundle containing the prefabs. If we manually loaded this bundle ourselves and kept it alive, we could save a whole bunch of loading and unloading of the same assets.

    I assume there's some good reason why it doesn't work this way, something I'm not seeing, but as it is rightnow i think it really damages the prefab / scene editor workflow.
     
    FlorianBernard likes this.
  4. FlorianBernard

    FlorianBernard

    Joined:
    Jun 9, 2015
    Posts:
    165
    That is extremely disappointing to say the least :(

    It seems like such a basic use case, even though I agree with you there must be a good reason for it. I wish this was mentioned somewhere in the documentation. I might not have decided to convert my entire project to Adressable in the first place.

    At that point, I guess I'll have to take the script instanciation route too!
     
    Last edited: Feb 22, 2021
  5. SpiralCircus

    SpiralCircus

    Joined:
    Feb 1, 2014
    Posts:
    34
    Hopefully someone at unity will respond? I'd be curious to know some more about the decision making here.
     
  6. FlorianBernard

    FlorianBernard

    Joined:
    Jun 9, 2015
    Posts:
    165
    Just in case that could help anyone finding this thread --

    I ended up writing an [ExecuteOnEditMode] script component that set each Addressable prefab instance tag as "EditorOnly" (and also set hideFlags to HideFlags.DontSaveInEditor) so they don't get embedded in any build.

    It also instantiates an empty gameObject to which I attach another "instantiator" script which holds the address to the prefab and transform properties. I conveniently move that instantiator at getSibblingIndex() + 1 with a similar name for clarity. I've also made a button with Odin Inspector to show/hide them all (hidden by default).

    Every time an instantiator is created, it registers the asset address to a central addresses list. When time to load the scene, I do
    Addressables.DownloadDependenciesAsync(list) where list is my Unity scene address along with dependencies. Once that's done I can simply do
    Addressables.LoadSceneAsync and instatiators will have their content already loaded.

    This works great for assets with no other override than the transform. I'll definitely try to figure out how to apply other overrides in the future, but not sure how yet.

    Hope that makes sense!
     
  7. SpiralCircus

    SpiralCircus

    Joined:
    Feb 1, 2014
    Posts:
    34
    There's a new section in the docs (or maybe i just missed it last time?)

    Note: If you mark a GameObject in an Addressable loaded scene as DontDestroyOnLoad or move it to another loaded Scene and then unload your original Scene, all dependencies for your GameObject are still unloaded.

    If you find yourself in that scenario there are a couple options at your disposal.

    • Make the GameObject you want to be DontDestroyOnLoad a single Addressable prefab. Instantiate the prefab when you need it and then mark it as DontDestroyOnLoad.
    • Before unloading the Scene that contained the GameObject you mark as DontDestroyOnLoad, call Addressables.ResourceManager.Acquire(AsyncOperationHandle) and pass in the Scene load handle. This increases the reference count on the Scene, and keeps it and its dependencies loaded until Release is called on the acquired handle.
    From https://docs.unity3d.com/Packages/c...al/AddressableAssetsAsyncOperationHandle.html
     
    glenneroo and KwahuNashoba like this.
  8. SpiralCircus

    SpiralCircus

    Joined:
    Feb 1, 2014
    Posts:
    34
    Looking at the second bullet point in that bit of the docs, perhaps there is a strategy available where everything that gets put in DontDestroyOnLoad, also calls acquire on the addressable scene.
     
  9. nicloay

    nicloay

    Joined:
    Jul 11, 2012
    Posts:
    535
    You don't need any scripts. Instead of adding prefabs to the group, try to add prefab folder to the group, so in this case the result bundle will contains information about prefab + all dependencies(materials, textures)
    So when scene see a prefab usage it won't include prefab with dependent resources
     
  10. andymilsom

    andymilsom

    Unity Technologies

    Joined:
    Mar 2, 2016
    Posts:
    294
    Thanks everyone for helping on this issue.

    There are various ways to go about handling this, it generally comes down to maintaining a hold on the memory management.

    When you load Assets or Scenes in Addressables, we keep a reference count on anything that is used, traversing up the dependency tree as needed.
    Now when you load a scene, we know about the scene load. But anything you do is scene memory is unknown, we have no way to know if or how you have moved content around.

    One way to do this is with the documentation about DontDestroyOnLoad/move assets between scene from a scene. Allowing you to unload the scene as you would. But keep a hold on the scene loaded bundle through the newly acquired handle. And release said handle when you are ready.
    Another way is instantiate the Prefabs, or just have the Prefab addressable and have it loaded. Which will keep the shared assets in memory. Allowing your scene memory GameObjects to still reference them.
    You should however make sure they are not implicit to the Scene bundle, see https://docs.unity3d.com/Packages/c...ssets.html#asset-and-assetbundle-dependencies