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

Problem with addressable prefabs in scene

Discussion in 'Addressables' started by Omzy, Feb 17, 2019.

  1. Omzy

    Omzy

    Joined:
    Jun 28, 2013
    Posts:
    31
    Hello all, I posted this in the 4gb limit thread and @karl_jones recommended I cross-post here: https://forum.unity.com/threads/bug...n-standalone-build.441116/page-3#post-4224865

    Using Unity 2019.1.0a14 and windows 10, default build settings.

    I am trying the addressable asset system, but running into a problem. All i have done is place the prefabs into my scene and I'm loading the Scene using a simple load level call. It is all just static level geometry/clutter. There are no script calls to load anything. I assumed having prefabs in the Scene serves the same function, that if the object is in the scene, it is the same as referencing it in code. Is that a correct assumption? I'll take some images so you can see what I'm talking about. I have a lot of textures in my game, and I intend to add even more, so reducing the number of textures isn't an ideal answer for me, but rather finding ways that Unity can support large numbers of textures. My build report is as follows:

    Build Report
    Uncompressed usage by category (Percentages based on user generated assets only):
    Textures --> 6064.1 mb 88.6% <---
    Meshes 103.2 mb 1.5%
    Animations 13.5 mb 0.2%
    Sounds 1.8 mb 0.0%
    Shaders 98.5 mb 1.4%
    Other Assets 12.0 mb 0.2%
    Levels 92.4 mb 1.4%
    Scripts 2.3 mb 0.0%
    Included DLLs 3.9 mb 0.1%
    File headers 450.8 mb 6.6%
    Total User Assets 6842.6 mb 100.0%
    Complete build size 1174.9 mb

    I have arranged most of my scene asset into addressable asset folders per the 'Trash Dash' video. Here you can see the folders.
    https://gyazo.com/6ddaa6c4651e175771d9d6f36376de9f

    Here you can see the file sizes in my build directory addressables folder: D:\ProjectH\Builds\Build01\Test_Data\StreamingAssets\com.unity.addressables\StandaloneWindows64


    https://gyazo.com/35e094a6e1cbd3cecec5b025933abc46

    So that looks great, the files are all under 4gb. However, my project still has the same size of the sharedasset files as you can see here, with sharedassets1.asset.resS exceeding 4.5gb:


    https://gyazo.com/272d9854ad369a11a415c175047864fd

    I am still encountering the texture glitch bug where my textures are bugging out (the thing that made me and others notice this 4gb limit in the first place). Perhaps I'm using the addressables system incorrectly. I followed the information that was available to me. Any ideas on why the build continues to generate the large sharedassets file? Sharedassets1.assets.resS is the same size despite reorganizing into addressables. Is this where all the shader variations are compiled? My project seems to generate tons of shader variants, which, from reading on several forums, is normal behaviour. I barely use the Resources folder, there is nearly nothing in there.
     
  2. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    7,846
  3. Omzy

    Omzy

    Joined:
    Jun 28, 2013
    Posts:
    31
    To clarify, I can still have the prefabs in the scene, but I just have to load them before the scene works and they should pop in automagically? My use case is extremely simple. All I want to do is have a large static scene with lots of static geometry and accompanying textures. None of this is dynamic. I am not instantiating any of this content, it should all be there from the get-go as soon as I load the scene. Just like any normal game out there with complex scenes, Skyrim, Fallout, GTA, etc. I am only forced to go this route because my scene has too many textures and this is the recommended fix for that scenario.

    So what I think you mean after reading that article is that I need to call an Addressables.Load function during my scene load which I can create a loading bar from, as the assets are incrementally loaded, then once all of it is loaded, call the actual LoadScene function? If this is the case, must I explicitly load every single asset in the bundle, or can I just load the entirety of the relevant bundles into memory at once? There are hundreds of different objects and it is not practical to load them individually.
     
  4. Omzy

    Omzy

    Joined:
    Jun 28, 2013
    Posts:
    31
    I noticed there is a LoadScene function in the Addressables API. Perhaps this is all I need to do, change my LoadScene to the one from the Addressables. I'll test it out and let you know if it works.
    https://docs.unity3d.com/Packages/c...ityEngine.AddressableAssets.Addressables.html

    EDIT: After some reading, it seems that I am thinking of scenes wrong. If I simply make the scene file addressable, it adds everything inside the scene into an asset bundle since they are all technically dependencies? If this is the case, then the only way I can see to split up a large scene into 3 asset bundles under 4gb would be to delete 2/3 of my scene and save each 3rd that way as separate scenes, then use LoadScene to additively load all of the Sub-scenes (each corresponding to an asset bundle). Does this sound correct to anyone reading this?
     
    Last edited: Feb 18, 2019
  5. tswierkot

    tswierkot

    Joined:
    Feb 15, 2017
    Posts:
    25
    Right now, if you use adressable assets in a scene using direct references (for example, putting a prefab that is an adressable asset in the scene), those assets will be built into scene data if that scene is included in the build settings. You're basically duplicating assets - they're in the scene data and in the built bundles.

    What you can do is write a script, that processes your scene on save and does something like this:
    1) Find all objects that are set as adressables.
    2) Replace those objects with scripts that load and instantiate them.
    3) Save a copy of all these modified objects, including not modified in a separate scene (for example, Scene33_lazy.unity) - this scene should be included in build settings, not the original one.

    All those steps can be automatic - that way a level designer can work on the scene and doesn't have to worry about setting any additional scripts. Then, after loading a scene you also have to wait for all adressable assets used on scene to load and instantiate. You should do this during your loading screen.
     
    chrisMary and Omzy like this.
  6. Omzy

    Omzy

    Joined:
    Jun 28, 2013
    Posts:
    31
    This sounds like a decent approach too. Not very user friendly obviously, but I'll try it. Hopefully it doesn't increase scene load time. It would be nice if there was a simpler way to do this. I mean, honestly just having lots of geometry in a scene should not create a problem that developers have to be creative to solve. If you're trying to do strange things i understand a degree of complexity is expected but i should never have to look under the unity hood just because i want a nice scene with lots of objects. This is 2019 and tons of level designers are dragging and dropping assets from packs to make their scenes look triple A. It doesn't make sense that at a certain point that process stops working because of an engine limitation. It should only be limited by client hardware causing lag or load time issues.
     
    truefx001 likes this.
  7. Omzy

    Omzy

    Joined:
    Jun 28, 2013
    Posts:
    31
    A little update on my tests. I created a simple scene with a bunch of static assets. I saved the base scene as Scene1, then split up the geometry of the rest of the scene into 2 groups and saved each as a prefab. I created 2 new scenes, Scene2, and Scene3 and dropped the respective prefabs with the geometry into each. I made sure none of these scenes were in my build settings. I added these 3 scenes to the addressable assets Default Local Group. I then did Build Player Content.

    I created a scene called MapLoader. Inside this scene is a gameobject with a simple script attached. The script references 3 AssetReferences which allows selection of the 3 scene references. Here is the script (borrowed from a thread on this forum at https://forum.unity.com/threads/scene-dont-load-on-packed-mode-and-on-build-remotepath.551695/):

    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using UnityEngine.AddressableAssets;
    6. using UnityEngine.ResourceManagement;
    7. using UnityEngine.SceneManagement;
    8.  
    9. public class GameStarter : MonoBehaviour
    10. {
    11.  
    12.     public AssetReference[] ScenesToLoad;
    13.     // Use this for initialization
    14.     void Start()
    15.     {
    16.         //AssetToLoad.LoadAsset<scene>().Completed += OnAssetReferenceLoaded;
    17.         //Addressables.PreloadDependencies(AssetToLoad, null);
    18.         foreach (AssetReference scene in ScenesToLoad)
    19.         {
    20.             Addressables.LoadScene(scene, LoadSceneMode.Additive).Completed += OnCompleted;
    21.         }
    22.     }
    23.  
    24.     private void OnCompleted(IAsyncOperation<Scene> obj)
    25.     {
    26.         Debug.Log("Scene Load Complete");
    27.     }
    28.  
    29.     // Update is called once per frame
    30.     void Update()
    31.     {
    32.  
    33.     }
    34. }
    35.  
    Running the game loads the 3 sub-scenes additively into the composite map with all geometry intact in the appropriate locations. I didn't have to do any per-asset loading, they were loaded automatically as scene dependencies. None of the prefabs in the scenes were explicitly set to be addressable. Looking into the build folders reveals that the resS files are very small (max 129kb) and the generated asset bundle was just over 9mb (expected given the amount of geometry in the scene).

    These results show how to split up a scene into chunks and load them additively. I have not done large scale testing yet or lighting tests. I haven't added in a loading bar or anything like that yet. I'll proceed with some large scale tests using a map with >6gb textures next. @karl_jones Hopefully this is able to overcome the 4gb per scene limitation in this thread: https://forum.unity.com/threads/bug-4gb-limit-to-textures-in-standalone-build.441116/
     
    karl_jones likes this.
  8. jonagill_rr

    jonagill_rr

    Joined:
    Jun 21, 2017
    Posts:
    54
    What if the scene is also marked as Addressable and built into its own bundle? Will it still build all the directly referenced prefabs into its own bundle, or will it have a dependency on the built prefab bundles?
     
  9. Omzy

    Omzy

    Joined:
    Jun 28, 2013
    Posts:
    31
    You mark the sub-scenes which have static content as addressable and put them in their own bundles. You keep the base scene (the one that loads the other scenes) inside your build settings. Keep all of your scripts and non-static data in that base scene as that will be included in the build.

    If I understand your question, you're asking if you have separately created prefab bundles and then, after you've done that, you mark a scene as addressable. Well, I think since marking the scene as addressable creates a bundle out of its dependencies, you would have duplicated your data in the bundles. Maybe if you run the redundancy check it will catch this, but I haven't tested that yet. I'll post here when I've finished my tests at scale.
     
  10. Omzy

    Omzy

    Joined:
    Jun 28, 2013
    Posts:
    31
    Surprisingly, my large scene loaded exactly as expected and the lighting is exactly as I designed it. I made sure it was baked before I split the scene and kept all the lights, reflection probes, etc on the base map loader scene which was included with the build. After the sub-scenes popped in, they were all lit correctly. My resS file sizes are now fairly small and the largest bundle for my sub-scenes is 1.5gb (before using bundles my resS was 4.5gb).

    All in all, this approach works and is a fairly simple way to manage large scenes. It also benefits from the future ability to push updates as it uses addressables (as opposed to using non-addressable additive scenes).
     
    MNNoxMortem and karl_jones like this.
  11. Omzy

    Omzy

    Joined:
    Jun 28, 2013
    Posts:
    31
    Someone PM'd me asking for clarification on how to achieve this split scene setup. Here was my response:

    How to Setup Multi-Scene with Addressables
    ------------------------------------------------------------------

    I had to upgrade my project to 2019.1 to use it. You can always duplicate your project and try upgrading unity to see how hard it is to port to 2019.1 without losing any data.

    If you have access to addressables, this is how you do it. You can split it into as many pieces as you want, but lets go with 3 for the purposes of explaining. Your base scene with any scripts/dynamic objects you keep as the master scene. You group all of your static objects into 3 groups around the scene. You can do this by dragging and dropping them into parent groups in your hierarchy. Lets say you now have 3 asset groups, Group1, Group2, and Group3. Your scene at this point still looks the same as it did.

    Now you save the master scene and duplicate it so you have a backup copy. In the master scene, delete all 3 groups and save it again (your scene will be mostly empty). Then Undo your deletes. Now delete everything except Group1 and SAVE AS Scene_Group1. Then Undo your deletes. Now delete everything except Group2 and SAVE AS Scene_Group2, etc for all of your groups. Now you mark the Group1-3 scene files as Addressable in the Project window. Then go into the Addressables window and put each addressable scene into its own asset group so the bundles get split up. You then have the Addressables system build your bundles in the Build section. Make sure your master scene is still in the project build settings, but make sure the Group1-3 scenes are NOT in the build settings. You then add a gameobject with a custom loader script into your master scene that triggers the Group1-3 scenes to load additively using Addressables.LoadScene (dont forget the additive parameter).

    Now when you load your master scene, the rest of the scenes will pop in. They should maintain any lighting you had on the master scene before doing all of this. If you need to modify the scene again, you have to use your Backup Copy and repeat some of these steps.