Search Unity

Associating GetAllAssetNames() with LoadAllAssets()

Discussion in 'Asset Bundles' started by pb_martinwickham, Jan 29, 2019.

  1. pb_martinwickham

    pb_martinwickham

    Joined:
    Mar 9, 2017
    Posts:
    5
    Hi all,
    I'm setting up an asset system based on the following idea:
    1) users of the system request bundles they may need for a period of time
    2) those bundles (and their dependencies) are loaded asynchonously
    3) all assets in the bundles are preloaded via LoadAllAssetsAsync
    4) users fetch the preloaded assets synchronously by type and filename (something like LoadAsset but it just does a fast lookup to one of the existing objects that was previously returned by LoadAllAssetsAsync)
    5) When the user is done, they release their requested bundles, and if no other scopes are using them the bundles are disposed.

    Unfortunately, in order for this to work, I need a way to associate the objects in the array returned by AssetBundle#LoadAllAssetsAsync() with the paths returned by AssetBundle#GetAllAssetNames(). Trying to use the same index won't work, since some assets (like .png files) generate multiple assets (a Sprite and Texture asset), so the array of assets can be longer than the array of paths.

    I've been searching through documentation and blog posts but can't find any good way to do this. If possible, I'd like to avoid creating my own manifest file to pack into each asset bundle, since it's clear that this information is already in the bundle somewhere (just maybe not accessible).

    Any recommendations?
     
  2. pb_martinwickham

    pb_martinwickham

    Joined:
    Mar 9, 2017
    Posts:
    5
    Some experimentation shows that Unity keeps an internal cache of loaded assets, so calling LoadAsset(..) several times will be fast once the asset is loaded and calling LoadAllAssets() will prime the cache. This removes most of the need for a solution to this question.
    LoadAsset hitting the cache still seems to be ~4x slower than an equivalent dictionary lookup, but it's fast enough for my current purposes.

    If anyone finds this and still needs a solution, it seems like it would be doable by using the SerializedObject API and iterating the
    m_Container
    property, similar to this example: https://support.unity3d.com/hc/en-u...Which-Assets-are-included-in-an-Asset-bundle-

    Edit: SerializedObject is only available in the editor so this does not actually solve the problem. Maybe baking a custom manifest is the only way to go?
     
  3. spvn

    spvn

    Joined:
    Dec 10, 2013
    Posts:
    35
    I have exactly the same question. Shame there was no response. Seems like a fairly common use case to cache assets from a bundle. Bumping this hoping for a response?
     
  4. pb_martinwickham

    pb_martinwickham

    Joined:
    Mar 9, 2017
    Posts:
    5
    I ended up with the following workaround:
    If an asset is loaded, the asset cache system will deduplicate it internally. Testing it in editor showed that the internal process is ~4x slower than a dictionary lookup, which is fast enough for my purposes. But the automatic disposal of unused assets needs to be disabled. So I call LoadAllAssetsAsync, put that array somewhere that is tracked by the unused asset checker, and then call LoadAsset on the asset bundle to get the preloaded assets.

    This has the unfortunate side effect that the asset bundle object cannot be disposed and continues to reserve memory for the whole bundle just so we can use its lookup table. So far this has not been a problem for me, because my assets are relatively small.