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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Reliability of asset bundle hashes in AssetBundleManifest

Discussion in 'Asset Bundles' started by dlegare-synapse, Nov 6, 2019.

  1. dlegare-synapse

    dlegare-synapse

    Joined:
    Jan 17, 2018
    Posts:
    54
    I'm updating my project's asset bundle automation pipeline, and am currently running into some issues with how Unity generates hashes for asset bundles. Specifically I'm using
    AssetBundleManifest.GetAssetBundleHash()
    and getting inconsistent hashes for the same asset bundle.

    I ran some tests using one asset bundle at a specific commit of my project. What I found was:
    • Building the same asset bundle on different machines would result in a different hash reported from Unity. What's more, running an md5 checksum on the generated files showed that the generated files were different.
    • Building the same asset bundle with a different active build target (i.e. I built an asset bundle targeted for Android once with Android as the active build target in the editor and once with Windows as the active build target) resulting in a different hash from Unity, though the md5 checkshum of both bundles was the same.
    That second point (changing the active build target changes the hash, regardless of what build target the bundle uses) is proving to be especially troublesome for me. I have been using the
    DryRunBuild
    option in order to generate hashes for all of my bundles on all supported platforms in one go, which is very useful when integrating the build process into a CI server. However, I noticed today that the hashes generated by the dry run don't actually match the hashes on the built bundles (except for whichever built target happens to be active when doing the dry run). For reference, the code I'm using for this process can be found here.

    While looking into this more, I found an official Unity tutorial stating that the AssetBundleManifest hash shouldn't even be used for versioning in the first place:

    This is surprising to me, as we've been using this hash for a while on existing projects and had assumed everything was working fine (at least we hadn't yet found any major issues that we traced back to the asset hashes). This also makes me question if we should even be trying to use the hash returned by
    GetAssetBundleHash()
    , or if we should be using some other method of generating a hash, such as taking the md5 checksum of the generated file.

    So, to summarize:
    • Is
      AssetBundleManifest.GetAssetBundleHash()
      the "right way", or even a reliable way, to get a hash to use for versioning/caching an asset bundle?
    • If
      GetAssetBundleHash()
      isn't the right way to version an asset bundle, what would the recommended way be?
    • Is it intended/expected that
      DryRunBuild
      not produce correct hashes for asset bundles?
    • Is it intended/expected that the active build target would have an impact on the generated hash for an asset bundle, regardless of that build target is actually used for the bundle?
    • If it's not expected that
      DryRunBuild
      or changing the active build target would have an impact on the hash, what other reasons should I investigate to explain why the hashes are inconsistent?
    Some additional details that may be relevant:
    • The project is on Unity 2018.4.11f1.
    • Our machine that builds our game (including asset bundles) is a macOS machine.
    • We use SVN for version control (probably not relevant, but it has come up in other forum threads on the subject).
    I appreciate any help anyone can offer!
     
    tgrotte likes this.
  2. dlegare-synapse

    dlegare-synapse

    Joined:
    Jan 17, 2018
    Posts:
    54
    Also, is this something that is addressed by the Scriptable Build Pipeline? I know the SBP is supposed to fix various issues with asset bundle build stability, would this be one of them?
     
  3. dlegare-synapse

    dlegare-synapse

    Joined:
    Jan 17, 2018
    Posts:
    54
    I realized that there was a chance that at least part of the inconsistency that I'm seeing could have to do with something specific to the project I'm working on, and could potentially be fixable. To provide a more thorough test, I setup some tests in a separate Unity project. The tests were run in Unity 2019.2.4f1 to also try to determine if any issues were older bugs that might have been fixed since Unity 2018.4. The source for the tests can be found on GitHub.

    In order to test the build pipeline, I did the following:
    • Tested building asset bundles for two platforms: Android and Standalone Windows.
    • Tested running the build with two different active build targets: Android and iOS.
    • Tested both dry run builds and full bundle builds for each of the above.
    • Tested both the built in build pipeline and the Scriptable Build Pipeline (version 1.5.4) for each of the above.
    • Tested with three bundles: One with a prefab and custom scripts in it, one with a texture, and one with a material using a custom shader.
    I've attached a file with the test outputs, but to summarize:
    • The hashes from dry run builds are inconsistent for asset bundles built for targets not matching the current build target.
    • Hashes from dry run builds for the current build target seem to be consistent with the hashes produced by the full build.
    • Hashes from full bundles builds seem to be consistent regardless of the active build target. This differs from my original tests, so it may be something that was fixed in Unity 2019.
    • The Scriptable Build Pipeline seems to produce consistent hashes for both dry runs and full builds, regardless of the active build target.
    That last point (that the SBP produces consistent hashes) is exciting, but comes with a major caveat: When building for a non-active build target with the SBP, it will automatically change the specified build target to be active. This happens even for dry run builds. Unfortunately, this defeats the purpose of dry run builds for me, since I was using them as a way to generate the hashes for all bundles quickly, without having to switch platforms and wait for assets to import (which can be very slow in our project). It also means I can't use that functionality from a batchmode build, since the underling functionality isn't available in batch mode.

    For my purposes, this effectively tells me that the only way to reliably get the hash for an asset bundle is to fully build it. Slightly inconvenient for my CI setup, but not unreasonable.

    This does leave me with an additional question, though: When does it make sense to do a dry run build? I have only ever used it to get the resulting
    AssetBundleManifest
    , and the only information in there that can't be gotten through
    AssetDatabase
    is the hash (as far as I can tell).
     

    Attached Files:

  4. dlegare-synapse

    dlegare-synapse

    Joined:
    Jan 17, 2018
    Posts:
    54
    Ah, I just noticed that SBP doesn't actually support
    DryRunBuild
    . That at least partially explains the results I was seeing, and backs up my assessment that the dry run build functionality didn't have a clear use case.
     
  5. tgrotte

    tgrotte

    Joined:
    Apr 17, 2019
    Posts:
    25
    "Unfortunately, this defeats the purpose of dry run builds for me, since I was using them as a way to generate the hashes for all bundles quickly, without having to switch platforms and wait for assets to import (which can be very slow in our project)."

    You could try using Unity Cache Server to speed this up. Also apparently there's an upgraded version called Unity Accelerator now too: https://blogs.unity3d.com/2019/09/11/speed-up-your-team-with-the-unity-accelerator/
     
  6. Neto_Kokku

    Neto_Kokku

    Joined:
    Feb 15, 2018
    Posts:
    1,751
    In our CI setup we simply keep a separate checkout for each to avoid these issues and preserve each platform library folder between runs. We'll have to to see how 2019.3 fast platform switcher factors into this when we start using it in our projects.
     
  7. araki_yuta

    araki_yuta

    Joined:
    Jan 21, 2020
    Posts:
    14
    It may be related, but when I was testing Addressables, it seems like when ever I delete the Library folder, the asset hash changed (for assets that are never changed...).
    I was doing that test because we don't commit Library folder to our git, having consistent hash was something we expected.
    I read somewhere in the forum that this was bug and was fixed something like 2018.4.12? fairly recently like last December. I've updated my editor to 2018.4.15f1 and seems like hashes are matching up now.

    FYI:https://forum.unity.com/threads/the...h-time-if-i-remove-the-library-folder.494879/
     
    Last edited: Feb 10, 2020
  8. a3dline

    a3dline

    Joined:
    Dec 28, 2013
    Posts:
    17
    2018.4.20 building the same commit from Git gives different hashes. The project is built from scratch (without the Library folder) on the BM
     
  9. Neto_Kokku

    Neto_Kokku

    Joined:
    Feb 15, 2018
    Posts:
    1,751
    A large portion of Unity's platform-specific asset serialization is not deterministic. Building bundles from scratch will result in slightly different files every time. The only thing that can prevent this is keeping the previous run bundle, their manifests, and the library folder around, with their original timestamps too (because Unity will rebuild a bundle if any of the source assets are newer than the bundle file). It's a pain.
     
    NamiaLus likes this.