Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Asset Bundles Double Build Size?

Discussion in 'Scripting' started by HomeBearJosh, Jun 8, 2018.

  1. HomeBearJosh

    HomeBearJosh

    Joined:
    Dec 13, 2017
    Posts:
    33
    In order to bring down loading-times, I've been attempting to implement asset bundles.
    My approach: simply bundle up all the assets into a couple of large bundles and replace all Resources.Load() calls to AssetBundle.LoadAsset().

    Good news: Loading times are down.
    Bad news: the build size has doubled.

    My guess would be the new asset bundles in the StreamingAssets folder are included on top of actual the assets. But these are no longer in the Resources folder, so why are they included?
    Because they are referenced outside of the Asset Bundles, such objects that are simply placed in scenes that aren't loaded through LoadAsset()?

    Thanks to anyone who can clear this up for me. :)

    TL;DR:
    Put assets in Resources folder into asset bundles; Resources folder empty.
    Load time down, but build file size doubled. Why?
     
  2. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,186
    If the assets are still being included, then your size would increase. Check your build logs to see if that is the case.
     
  3. HomeBearJosh

    HomeBearJosh

    Joined:
    Dec 13, 2017
    Posts:
    33
    Yes, I was wondering how that could be the case if I packaged all my assets within asset bundles?
    Am I supposed to build the bundles and then delete the assets or something?
    Because that sounds crazy.
     
  4. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,186
    Make sure you don't have any references to the assets in the scene. Sounds like you're using Resources.Load originally, but if there is any script that you've dragged and dropped into, it will include the asset.
     
  5. HomeBearJosh

    HomeBearJosh

    Joined:
    Dec 13, 2017
    Posts:
    33
    Alright, thanks, sounds like my suspicion about references was correct.
    So I can't have any references at all? Everything should be instantiated through AssetBundle.LoadAsset()?

    I have tons of scenes with backgrounds, for instance, which are GameObjects with a SpriteRenderer + Sprite asset.
    Should I load all those in code, with LoadAsset()?
    I thought references like this were the fastest option and should be used when possible?
     
  6. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,186
    If you have a sprite/image in your scene that is your background. Then you drag and drop a sprite from your project folder into the proper field on that object and now you see the sprite in your scene, that sprite is now included in your build.

    Or, if you have a sprite variable on a script and you drag and drop that sprite into that variable, then that sprite is now in your build.

    If it didn't include it, you'd lose your references, which is why it does this.

    If you also bundle that sprite into an assetbundle, you will now have the sprite included in your build with whatever settings you have on it plus it will be in the assetbundle.

    Since you can release assetbundles and download them from a server long after you release a build of your game, Unity doesn't maintain references to stuff inside a bundle.

    You have to consider what you are using the stuff for. Build size is smaller when you move stuff to local bundles, but you may have some loading overload when you "extract" your bundle. Load time is faster if you don't bundle something and keep a reference to it as well, but you may have a larger build.

    Just consider what you plan to do with the images, audio, video, models, whatever it is you are trying to bundle to see what is the best use case.
     
  7. HomeBearJosh

    HomeBearJosh

    Joined:
    Dec 13, 2017
    Posts:
    33
    Alright, so I've been taking reading and rereading this reply and working on trying to solve this problem.
    What I did is I went through every single scene and threw it as a new asset bundle in the asset bundle browser.
    This way, I could see what its dependencies were, and how much memory they'd consume.
    Any referenced assets could as such be moved in their appropriate asset bundles, removing the scene reference.
    Finally, after I confirmed the scene took only a couple of KBs, I removed it from the asset bundle.

    Now I can say, best as I can tell, that no dependencies exist anymore from scenes to assets that aren't already in asset bundles. I even packed all scenes themselves as a single bundle, and it amounted up to 43MB.
    See the attachment.

    All the bundles together amount to 3.63GB, which makes sense.
    But when I build the game, the build size is 6.28... almost double, as before, as if I've improved nothing.
    The extra gigabytes come from 'sharedassets' files, which likely represent the scenes in the game, which should take only 43MB in total.

    So... what could possibly cause this?
    I'm really starting to think I'm completely misunderstanding this whole concept...
     

    Attached Files:

  8. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,186
    Also note if you have anything in streamingassets, there is no processing on streamingassets. Everything is included in it's raw form without any compression. Resources is also always included, but these do have compression applied.

    Did you look at your build report log to see what it says?
     
  9. HomeBearJosh

    HomeBearJosh

    Joined:
    Dec 13, 2017
    Posts:
    33
    Thanks for helping out!
    The sizes I reported were indeed uncompressed; the streaming assets folder is around 3 gigs.
    When I select all folders of the project, that'd be around 6-7 gigs.
    So it seems regardless of scene references, the game still incorporates most/all assets on top of the asset bundles...

    I looked at this build report log but didn't really know what to think of it.
    It simply states the assets amount to 6 gigs.
    Glancing through the assets, it looks like most if not all assets are indeed included.
    Why, I have no clue.
     

    Attached Files:

  10. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    Stupid question, but do you still happen to have assets in your Resources folder that are supposed to be in the asset bundles? I believe everything in the Resources folder gets included in your build even if they are not referenced by any scenes in the build, because you could still use a Resources.Load call on them.
     
  11. HomeBearJosh

    HomeBearJosh

    Joined:
    Dec 13, 2017
    Posts:
    33
    Not a stupid question, but no.
    I have deleted the entire folder after moving all the assets out of it.

    So, what I think is happening...

    When I right-click a scene, and click on 'Select Dependencies':
    This selects all assets used/referenced by this scene.

    When I drag 'n drop the scene in the asset bundle browser:
    I see a list of assets used/referenced by this scene.

    There is a discrepancy between the info these two approaches give me.
    The bundle browser tells me the scene is pretty much empty, but 'select dependencies' tells me otherwise.

    scene_size_assetbundle.jpg The size is 89.6KB when added to the bundle browser.

    scene_dependencies.png
    When I 'Select Dependencies' of this scene, it apparently still depends on lots of assets.
    I assume these assets are added to the build on top of the asset bundles.

    So the asset bundle browser tells me the scene is empty, but the inspector tells me the scene is not.
     
  12. HomeBearJosh

    HomeBearJosh

    Joined:
    Dec 13, 2017
    Posts:
    33
    I'm pretty sure I got this figured out now.
    I simply confused asset bundle dependencies with actual scene dependencies.
    If the scene uses assets, regardless of whether these assets are in bundles, these WILL be included.

    So right now I'm simply expanding on my tool to automatically remove in-scene asset references and set these assets during run-time by loading them from the asset bundles.
     
  13. marklin

    marklin

    Joined:
    Oct 8, 2014
    Posts:
    7
    @HomeBearJosh So in conclusion, the drop-into-scene functionality of Unity should be avoided and only used for prototyping. At the end, everything in the scene should be added by code.

    Is that right?
     
  14. HomeBearJosh

    HomeBearJosh

    Joined:
    Dec 13, 2017
    Posts:
    33
    Exactly, that is how I interpreted all of this.
    Unity is known for its component / drag 'n drop functionality, so discovering this causes asset duplication problems when switching from typical resource folder usage to asset bundles really threw me off, to be honest.

    So, yes, you go about your typical Unity way for prototyping/designing your game.
    Then (to prevent doubling your assets when using asset bundles) cut all those references (sprites, audio, etc.) by dynamically loading them from asset bundles with scripts.

    If it's helpful:

    For my situation, I wrote a couple of scripts that looks at my scene, object by object, component by component.
    If the script finds assets worth removing references for, like audio files, it will remove the reference, and add a script to that object that loads that same reference from an asset bundle. The script can also define what bundle to avoid searching through multiple ones, to save time.

    When the scene references are gone, I won't be able to see my level design anymore.
    That makes revising things annoying. This why my 'asset setter' scripts also allow for the inverse.
    That is, the scripts allow to check the scene for 'asset bundle scripts' on objects, and then set scene references (sprites, etc.) based off that. This will make my level visible and editable again. After editing, I make sure to set the scene references back to asset bundle references, making the level 'invisible' again.
     
  15. marklin

    marklin

    Joined:
    Oct 8, 2014
    Posts:
    7
    @HomeBearJosh Sadly, it actually makes sense right? I mean, I don't think it's Unity's job to make sure the assets we drop into the scene will get loaded from their corresponding asset bundle.

    I guess I'll be searching to make a solution like yours.

    Thank you for your reply.
     
  16. orb

    orb

    Joined:
    Nov 24, 2010
    Posts:
    3,037
    This seems to be working as intended. Referencing what's already in the project embeds that data, even if you switch references to a bundle, because the editor can't know what the code is doing, it can only run it. It doesn't have static analysis and fancy code inspection.

    I think the real problem is the lack of a good asset bundle tutorial, maybe. The workflow isn't entirely intuitive.
     
  17. HomeBearJosh

    HomeBearJosh

    Joined:
    Dec 13, 2017
    Posts:
    33
    Both of you guys are correct.
    It's our responsibility to correctly handle asset loading, but a lot of online advice regarding this refers to usage of the Resources folder or grabbing scene references. Later on in development, during optimization, you discover that asset bundles are great, and... oops! You already built your entire system around Resource/scene reference usage.

    I know Unity specifically says not to use Resources, but I'd wager it still happens a lot.
    Like orb said, a good intuitive very visible tutorial sounds like a good idea to catch people's attention when they search for how to handle asset management.