Why the asset bundle slow in StreamingAssets on android device?

I am loading the resource in Editor using AssetDatabase is fast, but when I export the assetbundle, copy them into StreamingAssets, and load them using WWW on android device, it really very slow make my game can not play.
I see many people copy them asset bundle from StreamingAssets to persistentData path at the first time when the application launch, is it useful to speed up the load time, and why is it?
Thank you~

Hey,

What platform are you building for? Only Android?
Also, did you measure your game’s performance using the profiler? what takes most of the time?

On Android, your game is deployed to the device in an .apk file. This is essentially a zipped file with some internal structure. While deploying your game with StreamingAssets, these files are actually stored inside the .apk (e.g: zipped).

In order to access them, Unity allows you to easily access the bundles under streaming assets using the WWW class. Internally, it probably uses some Android APIs for accessing these files (AssetManager?) which probably have some overhead.

What we do, in order to directly access our asset bundles under StreamingAssets, is to add native android code that copies the bundles from streaming assets to another folder that is directly accessible from code (using System.IO.File), and then we can load them directly. This actually runs pretty quick (although our bundles are very small in size, so YMMV).

Hi, @liortal
I want to check this method, copy the AssetBundle from StreamingAssets to other folder.
It takes time when the user first launch, and take twice space than normal. I know many game do this way, but I want to find is there any good API to process it to avoid this copy?

As i said, you can still use the WWW class (WWW.LoadFromCacheOrDownload). It knows how to handle files in StreamingAssets. Internally, it may do the same thing (copy the files out) though i am not sure.

I am using WWW.Load data from StreamingAssets, but it very slow.

It is better to copy it outside of the StreamingAssets because on Android it’s inside a Jar file, so there is an additionnal it to uncompress it.

But even there, overall file access on Android seems pretty slow, cause us to have slow loading time when loading data from files.

If you go with WWW.LoadFromCacheOrDownload(), it will uncompress the file and store it in the cache folder on the device first, then load the cached file instead.

Just to clarify - files in StreamingAssets folder are not compressed with zip and packaged as raw data to apk. You can see them in a transient file raw.ap_ in Temp folder while building.

You can also use AssetBundle.LoadFromFile to load bundle directly from StreamingAssets folder.
Depending on compression method it will be either decompressed to memory (LZMA compressed bundle with default options) or decompressed/read when loading data from it (LZ4 or uncompressed bundle).

@alexeyzakharov can you explain what do you mean by “files in StreamingAssets folder are not compressed with zip” ?

When the APK is installed, does it get uncompressed? or do the files under StreamingAssets are stored in a compressed format (inside the APK) ?

Hi,

StreamingAssets are packaged into APK with -0 flag for AAPT tool (or -0 -Z for fastzip). Meaning that correspondent segment in APK is uncompressed. APK is a zip container which consists of blocks of potentially different compression types. You can use e.g. APK Analyzer to check what’s compressed and what’s not.
We don not extract and store any data from APK during installation or any other time. Player’s data is streamed and decompressed when requested by LoadScene or LoadAsset API. Android-specific resources are decompressed by OS.
StreamingAssets file are considered as “foreign” files which can be used by any external code (including direct access by file descriptor) and be already compressed (video, audio).

So, can i directly access files from streaming assets using Syste.IO APIs, like reafing files, etc?

Also, on android, can i directly load an asset bundle via AssetBundle.LoadFromFile from streaming assets?

No. StreamingAssets are not supported for System.IO API. You can access them only with Java code.

Yes, since 5.3, see e.g. example for AssetBundle.LoadFromFile.

Is WWW.LoadFromCacheOrDownload the best option on Android phones?
In our game it makes our first load 3-10x slow than subsequent runs. (20-50seconds vs 5 seconds, it is dependent on LZMA vs LZ4, which is understandable)

Hi guys,

I’m having a similar problem for my game, I’ve posted a question here:

Appreciate any feedback!

Well, i found myself an answer. Don’t know if it helps anyone, but posted here anyway is my hacky solution:
https://answers.unity.com/questions/1445881/assetbundlemanagerloadassetasync-doesnt-work-on-so.html?childToView=1447043#answer-1447043

I’m trying to use the streaming assets for shipping our app with an initial assets bundles - so that later we can patch them if needed.

It seems that reading from the streaming assets is pretty slow, can we improve it somehow?
It is better to ship one zip file to the streaming assets and then extract it and use WWW.LoadFromCacheOrDownload in order to read it locally?

We’re building our app for iOS and Android…

Which version are you using? There were improvements to that, don’t remember the version exactly.

2017.4.1f1

Then it has those improvements. On Android StreamingAssets are located inside apk and need to be pulled from it, which isn’t very fast.

Don’t know if it’s still ok to reply in this thread, but I have a related problem.
1.Build all resources into AssetBundles;
2.Compressed all ABs into StreamingAssets;
3.Need to Decompress those ABs into persistentData;
4.Use WWW www = new www(url) to read files in StreamingAssets;
5.I use multithread to decompress since there’re many files;
6.Works fine in Normal build.
Here is the problem: If I build a “Development build”, or run this code in Editor, an exception throwed says “Create can only be called from main thread.”
Is there any way to fix it?