Search Unity

Cannot read Obb file

Discussion in 'Asset Bundles' started by AcuityCraig, Jul 8, 2021.

  1. AcuityCraig

    AcuityCraig

    Joined:
    Jun 24, 2019
    Posts:
    66
    Not sure if this is the right sub forum for this since its not referencing Addressable but -

    I am using the "Split application binary" option for an android app (oculus Quest). The obb is generated and uploaded with the apk to Oculus App Lab without issues. When I install the app from app lab is downloads the OBB and places it in the expected folder - something like - "/sdcard/Android/obb/com.oculus.demo/main.1.com.oculus.demo.obb"

    In the first scene on the awake method of an game object I call the method:
    AssetBundle bundle = AssetBundle.LoadFromFile(path);

    This is where my issue is. I can confirm the file path is correct (using system.file.exists - and i can see it in the correct location on my quest headset when i plug it into my pc)

    I have the unity console error messages outputting to a text object for troubleshooting and I get the error -
    Failed to read the data from AssetBundle <Name.obb>.

    I have <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> in my androidmanifest.xml and can confirm when i go to the apps page on the quest that the permissions are allowed.

    Can anyone explain to me why it can't read this obb file?
     
  2. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,736
    Try using Application.streamingAssetsPath instead of direct obb location. Unity walks through apk and all mounted obbs and searches for a relative path in such case.
     
  3. AcuityCraig

    AcuityCraig

    Joined:
    Jun 24, 2019
    Posts:
    66
    I'll certain try this but I don't think that'll do it just because of this line in the docs for it -
    "It is not possible to access the StreamingAssets folder on WebGL and Android platforms. No file access is available on WebGL. Android uses a compressed .apk file. These platforms return a URL. Use the UnityWebRequest class to access the Assets."
     
  4. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,736
    It depends on whether you read obb itself or the files from inside obb. The obb is a file on disk and you should be able to read it. Though, when you use split binary and try to read files (like streaming assets) from inside of it, then it's different, since the obb is a zip file and reading files from it means reading from inside a zip archive.
     
  5. AcuityCraig

    AcuityCraig

    Joined:
    Jun 24, 2019
    Posts:
    66
    Gotcha. Thank you. Then I guess my question is - what is the correct way to load a scene that is stored in an OBB file on an android device?
     
  6. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,736
    Both UnityWebRequest and AsseBundle APIs can load from inside obbs. If you place your bundle in streaming assets, then simple append the relative path to bundle to Application.streamingAssetsPath and it should load.
     
  7. AcuityCraig

    AcuityCraig

    Joined:
    Jun 24, 2019
    Posts:
    66
    so if when my app starts I use:
    Code (CSharp):
    1. string path = Path.Combine(Application.streamingAssetsPath, "main." + _instance.bundleCode + ".com.AcuityBrands.LightingFundamentals.obb");
    2. AssetBundle.LoadFromFile(path);
    Assuming my path is correct it should load the entire bundle correct? So if I then call SceneManager.LoadLevelAsync(<SceneName>) of a scene that is inside that bundle it should just load?

    Sorry I'm not picking up how this works - I cannot find a single example of how to do this properly.
     
  8. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,736
    Where do put your obb? Or is obb file your asset bundle?
    The simples way is to put asset bundle into StreamingAssets folder in Unity project, select split binary, then simply append bundle file name to streaming assets path.
     
  9. AcuityCraig

    AcuityCraig

    Joined:
    Jun 24, 2019
    Posts:
    66
    When I select Split Binary it creates the apk and obb. When i upload to Oculus store/Applab both the apk and obb and then download to my device (via the oculus store install) it puts the obb in - "/sdcard/Android/obb/<packagename>/" as expected.
    The OBB file is generated when I generate my build - so its never in my streaming assets bundle. The Obb file appears to be everything but the first scene - just like the docs indicate. The first scene loads and then my startup code above is attempting to load the obb so I can then load the next scene (either the tutorial or main menu) but that fails because it cannot read the obb.
     
  10. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,736
    The obb file created by Unity is not asset bundle, it's a zip archive. If you placed asset bundle in streaming assets directory, you should find that bundle in obbs assets directory.
    Appending bundle file name to streamingAssetsPath should find the bundle regardless if it's in apk or obb.
     
  11. AcuityCraig

    AcuityCraig

    Joined:
    Jun 24, 2019
    Posts:
    66
    OK so I have created a bundle with all my scenes. Still using split binary. I now can see and load that bundle but loading any scenes from that bundle still fail. With a little googling I get mixed results on whether this is possible.
     
  12. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,736
    What errors do you get in logcat?
     
  13. AcuityCraig

    AcuityCraig

    Joined:
    Jun 24, 2019
    Posts:
    66
    Sorry - I have this figured out. I appears I was accessing the obb that unity creates when you use the split binary option. I instead generated assetbundles, put them in streaming assets, and used the split binary option and it now works. The key here was to use -

    In my game manager start function (my game manager is a persistent object set to "DontDestroyOnLoad"

    Code (CSharp):
    1. string mPath = Path.Combine(Application.streamingAssetsPath, "level.obb");
    2.         AssetBundle bundle = AssetBundle.LoadFromFile(mPath);
    3.         scenes = bundle.GetAllScenePaths();
    then in my main menu where you select a level -

    Code (CSharp):
    1. string mPath = Path.Combine(Application.streamingAssetsPath, "level.obb");
    and level.obb is the obb file i created manually that goes into the streaming assets folder. Then to load scenes from you first need to call

    Code (CSharp):
    1. string[] paths = GameManager.Instance.bundle.GetAllScenePaths();
    The docs on this are very conflicting and confusing. Either way, its now working. Hopefully this helps someone else in the future.

    Thank you.
     
    Eclectus likes this.
  14. kalineh

    kalineh

    Joined:
    Dec 23, 2015
    Posts:
    241
    Both UnityWebRequest and AsseBundle APIs can load from inside obbs. If you place your bundle in streaming assets, then simple append the relative path to bundle to Application.streamingAssetsPath and it should load.

    We are using Split Application Binary to generate an .obb file for a Quest project. Loading our asset bundle through AssetBundle.LoadFromFile() fails. Is this definitely the correct way to be doing this? How exactly does the loading logic find the asset bundles inside the obb? How does it do a name lookup or is it just scanning the guid files inside? Does the 'main' part of the obb filename have some particular importance?

    The obb file is confirmed on-device at:
    /sdcard/Android/obb/com.Company.Project/Project.main.Version.com.Company.Project.obb


    The android manifest does have READ_EXTERNAL_STORAGE permissions.

    Comparing the apk and obb files show they both have the same file structure:
    /assets/bundles/android/our_bundle.bundle


    and our loading code is simply:
    AssetBundle.LoadFromFile(Path.Combine(Application.streamingAssetsPath, "/assets/bundles/android/our_bundle.bundle"));


    which fails to load with the full path:
    jar:file:///data/app/com.Company.Project-GUIDHERE==/base.apk!/assets/bundles/android/default_bundle.bundle


    I can only assume that the '!' is handled magically by something in the file loader, but am not sure of it's function. Attempting to load the full obb path manually and appending '!/assets/bundles/...' did not work either.
     
    Last edited: Sep 7, 2022
  15. kalineh

    kalineh

    Joined:
    Dec 23, 2015
    Posts:
    241
    Okay, finally got it to load. Naming the file
    Project.main.#.com.Company.Project.obb
    is wrong, it must be exactly
    main.#.com.Company.Project.obb
    .

    You can verify the obb is mounted by checking Application.streamingAssetsPath, it will be pointing to the .obb file if it is working correctly.

    AssetDatabase.LoadFromFile() loads from this fine, using the
    <obb-path>!/assets/bundles/whatever.bundle
    path handling.

    Using Oculus Developer Hub, dropping in an apk with a wrongly named obb file will still upload the obb file to the /sdcard/Android/obb sub-folder, but it will not be mounted.
     
    mashraf-proven likes this.