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 for common assets

Discussion in 'Asset Bundles' started by liortal, Oct 9, 2017.

  1. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    Posting this question here since this forum deals specifically with asset bundles.

    In our game, we have many "common" assets used across the project. For example, this can be fonts, images used for the UI buttons (such as X for close, etc) and other asset types.

    Our game also uses asset bundles for downloadable content. The downloadable content also requires access to the common assets. One approach is to duplicate the common assets and include them into the downloadable content.

    A better approach would be to mark the common assets into an asset bundle and have other asset bundles depend on them.
    • Is this scenario supported? i know that the AssetBundleManager sample uses the manifest for managing dependencies between asset bundles, but how will that actually work?
    Consider an example with the following assets:

    Scene A (asset bundle called 'downloadable_scene')
    Font 'Arial' (asset bundle 'common')

    In this scene, there's a reference to Font "Arial", creating a dependency (downloadable_scene bundle depends on the 'common bundle)

    When loading the downloadable_scene bundle, the 'common' bundle will also be loaded, but will the object reference be hooked automatically by Unity? or should i manually load them from the common bundle?

    • The same question applies also in case 'common' is included into the game build (e.g: in StreamingAssets) and loaded immediately on the game startup. Will all object references to assets from this bundle be hooked automatically? or should i first detach the references and load them manually from the bundle?
     
  2. pahe

    pahe

    Joined:
    May 10, 2011
    Posts:
    542
    Short answer:
    Yes, this is working via dependecies.

    Long answer:
    You may have to configure your assetbundle loading system to first download the assetbundle manifest, which contains the dependecies for your assetbundles, then check if there are dependencies, download them (which also may have depedencies) and then download your assetbundle you want to have.

    We're doing this in our project, so the player may load the "Camp" scene which contains a sword mesh and texture in an assetbundle. Later the player loads a "Battle" scene which also contains the sword mesh and texture and via the dependency system the same assetbundle as before is reused (saving memory and the download).
     
  3. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    Thanks for the answer. are you sure this is how it works though?
    For example, in our project we have 2 large fonts. I tried to mark them with an asset bundle label, but they are still directly referenced by scenes that are included in the game build, so they are included into the game.

    Is there an option to have an asset bundle with those assets, but still keep scene reference to them, so that once the bundle is loaded these reference will function just as before ?
     
    Last edited: Oct 11, 2017
  4. pahe

    pahe

    Joined:
    May 10, 2011
    Posts:
    542
    I'm pretty sure, yes, though I can only tell for NGUI. We're not using the Unity native font & label system.
    NGUI has its own system to work just with references, which content may be changed dynamically (pretty much like HD / SD atlas textures). Don't know if there is such a system natively in Unity.

    font.png
     
  5. mkg2w

    mkg2w

    Joined:
    Aug 19, 2013
    Posts:
    54
    We're conducting a couple of experiments for a game of ours where we find that individual asset bundles are larger than the original assets themselves. From this documentation, I suspect common assets that are also referenced in the main game, are copied into each of the asset bundles.

    The implication is that the common asset needs to be separate from the main app itself?
     
  6. Ryanc_unity

    Ryanc_unity

    Unity Technologies

    Joined:
    Jul 22, 2015
    Posts:
    332
    So just chiming in here with some technical details:
    First, we have 2 ways to build content for your game: Player Data & Asset Bundles

    Player Data is what is generated via the build player pipeline. BuildPipeline.BuildPlayer or "Build" button in the Build Player Window. This data contains any global managers (Player Settings, Graphics Settings, etc), Scenes defined in Editor Build Settings, Assets in any Resources Magic Folder, and finally Objects (parts of assets) referenced by any of the previously mentioned things. (I may have missed some things).

    Asset Bundles is what is generated via build asset bundle pipeline. BuildPipeline.BuildAssetBundles. This data contains only the Assets, and Objects (parts of assets) referenced by any of the added assets.

    So that's the basic background, and now to build upon that.

    Data built during one call in the build pipeline can not be referenced (pointed to, loaded, etc) by anything build during a second call. Minor exceptions being advanced use cases where you layout the data in such a way to force it to work, but that is beyond the scope of this post.

    So based on that, today, you can not have a scene that is in Player Data reference anything in Asset Bundles with out using code to manually load the bundle and asset. (Same applies in reverse). So to put it in a more visual method:
    [Player Data <-> Other Player Data] <- / -> [Asset Bundles <-> Other Asset Bundles]

    Future note: when we are "done" with the 2018 build pipeline and everything runs though it. It would be very easy to have any and all data reference each other. Though I still would not recommend doing so, and I've probably gone into more detail than needed.
     
    NotaNaN, Dhoren and pahe like this.
  7. Ryanc_unity

    Ryanc_unity

    Unity Technologies

    Joined:
    Jul 22, 2015
    Posts:
    332
    So back to your issue:
    Based on my previous post your Player Data (game build) which includes the scene will not know about your Asset Bundles, so the Player Data will pull in the fonts so they can be used. What you will need to do to fix this is load the fonts dynamically using code and not an object reference on your asset.
     
  8. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    that is not really feasible. we have a single font that is used across the game. if i understand your suggestion, i'd have to add custom code for every Text component in the game to assign the loaded font (after it has been loaded from the asset bundle).
     
  9. pahe

    pahe

    Joined:
    May 10, 2011
    Posts:
    542
    Yeah, pretty much that (please correct me if I'm wrong). NGUI is doing that way with the referenced font. You only store the reference to a prefab which will later contain your font.

    So your game flow would be like this then:
    1. Start app, show loading screen where you download assetbundles. Either you use a small standard font here or show no text at all.
    2. Download your assetbundle with the font.
    3. Once it is downloaded, grab the font and assign it to your font reference (prefab).

    I don't know what kind of scripts you use for your project, but you could derive a class from your text script and replace the scripts on your text components (yeah, not nice, but could be okay if you don't have a very huge project).

    As Ryan said: If you want to have an asset from your assetbundles, don't reference that asset in your project or else it gets included! In our project, we have a seperate project for assetbundles to make sure that that couldn't happen at all.
     
  10. Ryanc_unity

    Ryanc_unity

    Unity Technologies

    Joined:
    Jul 22, 2015
    Posts:
    332
    This is where a singleton or other game manager pattern comes in handy. You spin up a manager that handles loading certain global data such as this shared font and store the reference on the manager. From there your text component grabs the reference on the manager instead. Alternative to this approach is the Dependency Injection method using assets such as StrangIoC or Zenject to "push" the shared font reference into your text component when it is constructed instead.
     
    Dhoren likes this.
  11. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    Yes it's possible, but loading a font is done automatically as part of scene / prefab loading by the engine I wish to keep it that way... looks like what i want to achieve is not supported right now (unless i implement your suggestion).
     
  12. dregan

    dregan

    Joined:
    Jun 11, 2015
    Posts:
    3
    I plan to include some of the AssetBundles in the shipping game (in StreamingAssets folder) and the rest would be downloadable.
    I would like to create an AssetBundle of common assets and ships in the game (these are simple assets textures etc no references to scripts) . Both the shipped AssetBundles and downloadable asset bundles will reference the common bundle. I’m reasonable sure this can work as long as I load the common bundle before I load any of the other bundles.
    ie, There are 3 types of bundles
    1. a1,a2,a3 ... included in streaming assets
    2. c1 - common assets included in streaming assets
    3. d1,d2,d3, downloadable bundles, there are similar to type 1 bundles just not included in build

    I have two questions that would help if I was clea

    1 If at a later point after ship , I create additional content I assume as long as hash of common bundle stays the same Can the downloadable bundles I create later can safely reference them ?

    and related to this

    2 Are the version hashes for AssetBundles consistent across builds as long as Content doesn’t change ?

    thanks in advance for any info.
     
    Last edited: Oct 28, 2017