Search Unity

Resource Management

Discussion in 'Addressables' started by Zullar, Mar 20, 2019.

  1. Zullar

    Zullar

    Joined:
    May 21, 2013
    Posts:
    651
    I'm looking for advice on the best way to manage my assets/resources.

    It looks like there are a few ways to handle assets.

    -Scenes (when a scene in included in a build so are the assets in the scene)
    -Resources folder (EVERYTHING in the resources folder is included in the build)
    -Asset bundles
    -Addressable Asset System
    -Editor (I load many assets in editor to automate... but these are not used in the build at runtime)

    And within each of these options there are many ways to build and load/unload assets. Interdependent references & shared assets. It's kind of overwhelming.

    Currently I use the Resources folder. But this has 2 problems
    1: It has a 4GB limit (https://forum.unity.com/threads/bug-4gb-limit-to-textures-in-standalone-build.441116/)
    2: It is inefficient (everything is the folder is built... even file's I don't use)

    So I'm moving away from the resources folder to a new system. But I'm not sure what that system should be.

    Is it safe to use Asset Bundles or will they be depreciated soon with the introduction of the Addressable Asset System? Or is the Addressable Asset System just another interface layer on top of Asset Bundles meaning Asset Bundles are here to stay?

    Here's a video of editor prefab generation.


    For runtime I load levels that contain prefabs. But almost everything else is generated by script (GUI, monsters, equipment, etc.). I have a reference to every asset in a script (here's an example).
    Code (csharp):
    1.  
    2.     public static readonly BatEnumAudioClip KeyCaveWormAttack = new BatEnumAudioClip(3003, "KeyCaveWormAttack", "Audio/Effects/FreeSoundDotOrg/CaveWormAttack/172004__skinnysoundguy__creature-beast-retch");
    3.     public static readonly BatEnumAudioClip KeyCaveWormDie = new BatEnumAudioClip(3004, "KeyCaveWormDie", "Audio/Effects/FreeSoundDotOrg/CaveWormDie/177453__andromadax24__s-pain-slith-16");
    4.     public static readonly BatEnumAudioClip KeyCaveWormUnburrow = new BatEnumAudioClip(3005, "KeyCaveWormUnburrow", "Audio/Effects/FreeSoundDotOrg/CaveWormUnburrow/169557__jorickhoofd__gravel-impact-3");
    5.     public static readonly BatEnumAudioClip KeyCaveWormUnburrow2 = new BatEnumAudioClip(3006, "KeyCaveWormUnburrow2", "Audio/Effects/FreeSoundDotOrg/CaveWormUnburrow2/121893__stephensaldanha__creature-small-high-pitch-roar", volumeMultIn: 2.5f);
    6.     public static readonly BatEnumAudioClip KeyCaveWormDigLoop = new BatEnumAudioClip(3007, "KeyCaveWormDigLoop", "Audio/Effects/FreeSoundDotOrg/CaveWormDigLoop/82722__prozaciswack__digging", volumeMultIn: 0.5f, r1In: 1f, r2In: 6f);
    7.     public static readonly BatEnumAudioClip KeyPortalLoop = new BatEnumAudioClip(3008, "KeyPortalLoop", "Prefabs/Scene/Portals/PortalScene/Stuff/L_Bughole_circle", r1In: 2f, r2In: 6f);
    8.     public static readonly BatEnumAudioClip KeyExplosion = new BatEnumAudioClip(3009, "KeyExplosion", "Audio/Effects/FreeSoundDotOrg/110115__ryansnook__small-explosion", volumeMultIn: 0.4f);
    9.     public static readonly BatEnumAudioClip KeyFrostCastBegin = new BatEnumAudioClip(3010, "KeyFrostCastBegin", "Audio/Effects/FreeSoundDotOrg/Ice00/138484__randomationpictures__chill-hit");
    10.     public static readonly BatEnumAudioClip KeyRepel = new BatEnumAudioClip(3011, "KeyRepel", "Audio/Effects/FreeSoundDotOrg/Repel/139476__odeean__sound-jump");
    11.     public static readonly BatEnumAudioClip KeyBlock = new BatEnumAudioClip(3012, "KeyBlock", "Audio/Effects/FreeSoundDotOrg/218460__thomasjaunism__wood-block-hit_CC0");
    12.     public static readonly BatEnumAudioClip KeyBeep = new BatEnumAudioClip(3013, "KeyBeep", "Audio/Effects/Custom/Effect_Pyter_Laser Beam");
    13.     public static readonly BatEnumAudioClip KeyMiss = new BatEnumAudioClip(3014, "KeyMiss", "Audio/Effects/FreeSoundDotOrg/Miss/9509__petenice__whooshCC");
    14.  
    Then to use an asset I will basically call PlayAudioClipNetworked(KeyBeep) and it will play on all clients.

    The reason I need a reference to every asset is for networking. If an audio clip is played what I do is send the auto clips integer ID across the network and tell all clients to play it. Then when the client receives the message they look up the asset from the ID and plays it locally.

    I think these are the are the 2 things I want to include in my build.
    1: Anything that's in one of my scenes
    2: Anything that's referenced in one of my scripts!!! (Unsure the best way to do this)
    ... and dependencies.

    Regarding what assets are loaded at runtime: Since my assets are not part of the scene I currently load them manually at application startup. It takes a few seconds and doesn't take up that much memory. I don't have that many assets and loading almost everything at startup is doesn't seem too bad at the moment. The alternative is to load assets the 1st time they are used... but this can create glitchy gameplay. (i.e. the 1st time an explosion occurs it will have to load the explosion prefab, audio sources, etc. and causes a gltich)


    Currently what I'm leaning towards is using my scripts that reference assets to also build Asset Bundles. That way anything that is not included in a script is not included in the build (unless it's used in a scene).


    From what I've read using Asset Bundles I will iterate through each asset and set it's AssetImporter.assetBundleName to an asset bundle, or null if not used.

    Then call BuildPipeline.BuildAssetBundles(...) to build all asset bundles.

    Then at runtime load the assets from the bundle.

    Does this seem like the proper approach?

    Thanks in advance.
     
    Last edited: Mar 20, 2019
  2. MNNoxMortem

    MNNoxMortem

    Joined:
    Sep 11, 2016
    Posts:
    723
    I'd say: If you have the time to wait until 2020 to ship, then implement it using the Addressable Asset System (AAS). It is essentially just a wrapper above asset bundles with additional functioality and does a lot of stuff for you.

    However, as we are exploring it heavily at the moment, we also run into development stopping bugs all the time. At it's current state for any complex project it is simply not production ready (and Unity never stated it is yet!). It works more than well enough to start developing using it and especially using local asset bundles (which are built to streaming assets by default) seems to be relatively stable. Simply don't rely on updating those bundles yet - simply clean and rebuild them for now.

    The great thing about remote bundles is, it essentially means you sacrifice a bit of server storage and download time for the user, but don't need to consider which assets you actually reference from scripts. You load whatever you need via the AAS and simply build everything. If it is remote bundled and you pack your bundles small enough (either pack separately or different groups) it means it wont be shipped along the player anyway. And to top this: The AAS gives you theorethically a lot of control. You could enable/disable bundles before building them by whatever criteria you have.

    The Id-Asset lookup is simple as well. Simply use a wrapper which holds id and asset reference (or simply the AAS key - that is how we do it) and then load the asset on demand. If you share this catalog both client/server/other clients can share assets via id but will actually load the asset from bundles.
     
    Last edited: Mar 21, 2019
    unity_bill and Zullar like this.