Which way is better to handle AssetBundle Download Management - unity3d

Before going to ask the question, I will explain what kind of requirements I need.
In my game, there are a lot of textures needed in order to play it. Because of this and the limitation of ipa size (iOS), I think using assetbundle is a must. Because the existing code implementation, I create the assetbundle, 1 asset bundle for 1 image. For example: I have 100 images, then I will create 100 assetbundle(with the mainasset will be the texture), with the same name.
I want my game can be played offline AFTER at first time the user has downloaded all the needed assetbundles. So if the user play for the first time or download the updated version of my game, the game will be forced into special scene where it will download all needed assetbundle, after that, the user can play the game without internet connection.
I thought there are 2 ways regarding of how to download these assetbundle:
The normal way: I put all 100 assetbundles in my server, and put 1 xml file, which consist all assetbundles information and its version. At the special scene, the game will download the xml file, and from that it will download 100 assetbundles via WWW.LoadFromCacheOrDownload. The purpose is just to store the needed assetbundles to the cache of game. After successfully downloaded all of them, user can play offline and if the game need the assetbundle to be loaded, then I just callagain the WWW.LoadFromCacheOrDownload, since it is still in the cache, it can be played offline. Of course, I assume the cache is still there as long as I dont clear the cache explicitly.
The hard way: I will zip all 100 assetbundle to 1 zip file. The game will download the xml file, and the zip file. I will decompress the zip, and put all 100 assetbundle in the mobile storage (iOS and Android). So after that, in case the game need to load the asset, I just call the WWW.LoadFromCacheOrDownload with the url is using file:/// scheme that point to the path of mobile storage.
Summary:
The Normal Way:
Minus: I assume the cache is still there, but if there is something wrong in the cache, the user can't play the game.
Plus: simple implementation, because the assumption that cache will be fine.
The Hard Way:
Minus: well, i don't know it is minus point or not, but this one, I have to implement the unarchived zip file and store them in storage. More implementation needed at server side and the application side. And since I am newbie, I don't know the best practice in this area.
Plus: more robust
So which one is better ? or any better recommendation?

We have essentially implemented a mix of your normal and hard way for our application. As yours, it's rather texture heavy, so most groups of texture assets are packed into their own asset bundles. (In our application texture have a logical grouping, so we don't pack them individually). We however don't download them directly to the cache. We download these to the sdcard and from there load them (or get them from cache) as we need them. (i.e. LoadFromCacheOrDownload).
It depends a bit on your situation, but I would generally advise against packing them into a single zip file. Primarily with regards to updates. It has happened in our case that an asset needed some updates, or that we wanted to add assets later on. By having an XML file or database containing versioning data, updating the data on the device is trivial. And if only one bundle changes, you only need to download that single bundle. And 2MB vs 450MB in our case is quite the difference.

Related

Is there any way to split data files into smaller chunks in Unity WebGL builds?

I am limited to the size of web applications I can build by the "Build\application.data" file.
I.e if its over a certain size I cannot upload it certain hosts, github, etc.
Ideally I would like to split the application into multiple data files under a certain size, while the application is still executable.
How would this be possible? Is this something I can do from Unity build configuration?
Can I do it after the build is done?
Can I split the file into chunks by archiving it with zero compression, and somehow still execute it from the browser? There is a file called Build.Loader.js, is it something that can be edited for this purpose?
This is for the purposes of using the application after it has been uploaded, not sharing it, I do not want to compress it into separate archives, or use gitlfs, I've tested this and the application does not work from the browser with github and gitlfs.
Thanks
Unity has 2 technologies for split data file:
Asset bundle
An AssetBundle is an archive file that contains platform-specific
non-code Assets (such as Models, Textures, Prefabs, Audio clips, and
even entire Scenes) that Unity can load at run time
Addressbles
The Addressable Asset System allows the developer to ask for an asset
via its address. Once an asset (e.g. a prefab) is marked
"addressable", it generates an address which can be called from
anywhere. Wherever the asset resides (local or remote), the system
will locate it and its dependencies, then return it.
Both technologies create separate files that you can host on a server and download as needed. Addressable is a newer technology that Unity team recommends.
Probably the total size of the bundle will grow, but user will be able to download only the necessary assets and the amount of data for the user may decrease
If you do not use Unity solutions, you can divide data file into parts. But on the client side (javascript) you will need to download all the parts, connect them and pass to Unity loader. You probably won't be able to use the browser's built-in gzip or brotli (not sure). It seems to be quite difficult.

Including non-standard resources in Unity HoloLens app

I'm building an app that must visualize a large point cloud on HoloLens 1st gen. As performance is an issue wit large clouds, I'm using Potree, an octree that takes care that only a preset number of points from the cloud are rendered.
The solution works in the editor, but, you guessed it, not when deployed on HL.
The point cloud in the Potree format is a set of couple of .json and hundreds of .bin files stored in hundreds of subfolders following the octree structure, all of that stored within a single folder, and the path to this folder is accessed by the renderer at runtime. However, I don't know how to include this folder in the HL app. Using Resources doesn't work as it's not really a standard resource. I've seen Asset Bundle suggested elsewhere, but according to this post asset bundling doesn't work on HL.
Is there a way to simply put this complex file structure in an accessible directory on HoloLens?
I feel completely stuck here and any help would be much appreciated.
Some of the things I've tried:
Keijiro Pcx doesn't work here. If rendered as single pixels, points cannot be seen in AR, and if rendered as meshes, the performance is abysmal (which led me to a conclusion octree structure should be used)
the solution here shows how to load one .xml file, but I have hundreds of files so I don't think it would work for me
similarly, this post deals with one .obj file
Unity 2019.4
HoloLens 1st gen
For anyone stumbling upon this - I ended up using Unity StreamingAssets and accessing the folder with Application.streamingAssetsPath - works beautifully!
Using pcx needs to be adjusted to binocular rendering in publishing settings. Please uncheck "Enable Depth Buffer Sharing" in XR Settings, and change "Single Pass" to "Multi Pass", as shown in the figure.enter image description here

Dealing with massive amount of user generated images in Unity3D

I need to create a system where we load images into the game. Those images can be uploaded by the users of my app through a dashboard. I download them to the device(persistent data path) and load them from there.
The question is, should I load them as AssetBundles(through Addressables) or straight from disk with Texture.LoadImage(bytes).
Keep in mind that I will not be able to apply custom compression for them. I use the same compression for all files, whether it's an asset bundle or not. The problem with asset bundles is the management of them. When you update the unity version + the fact that I need to have unity run on a server and create them every time someone uploads an image to the dashboard.
TL;DR;
Is the loading of an image that bad with Texture.LoadImage(bytes) that you should use AssetBUndles even if it involves way more work and problems?
Someone else answered this in a Unity forum.
The best option you can pick is to use RawImage component, which uses textures not sprites, removing the need to load a sprite from a texture, making it much faster. Case in which asset bundles are not required, simplifying the solution while keeping a decent loading speed.
Answer here: https://answers.unity.com/questions/1758532/dealing-with-massive-amount-of-user-generated-imag.html

iphone embedding images in the executable file

When releasing to the application store someone wrote in an offhand comment that you need to avoid embedding your images into the executable.
How do you do that?
I've seen code in various books that suggests encoding images as C byte array constants in the source code, and I can say that that's definitely a bad idea for reasons ranging from inefficient pixel formats to unsalvageable memory. That would qualify as "in the executable file" in a way that bundle resources don't, since bundle resources are packaged alongside the executable rather than within it.
I am not sure if I get you correctly, but maybe he meant accidentally adding image files to the Compile Sources category in your build target? This usually does not happen with images, but i have seen it happening with js files.
Perhaps they meant that you should only include images in the bundle that are essential.
The bundle is essentially read-only so you cannot remove an image from the device that is in the bundle. Therefore placing lots of example images that you expect a user to remove/not want is not a good idea because when the user deletes the images from inside your app no space on the device will be reclaimed.
Of course it is fine to place images in the bundle just make sure that they are required and are not taking up unnecessary space that the user cannot reclaim.

Where to cache remote image files in iOS?

I am planning to cache the images from a server and use show it as a sort slide show in my App. I would be asynchronously loading the images.
I have two options:
Either to cache the images as a File and use it whenever necessary.
Cache the images objects in memory and use it when ever necessary and write it in to files when Application quits.
Which one would be better?
Please let me know if you you have any kind of suggestions regarding caching images.
Your second approach has 2 major flaws:
If there's too many images then your application will get low memory warning and you'll have to dispose your images from memory anyway
It's also not a good idea to save all images to file on application quit - it is not guaranteed that your saving code will finish on application exit (e.g. if it takes too long system may just terminate your app and your images will be lost)
I'd suggest saving images to files right after you download them and keep in memory reasonable number of images you need to show without visible delay (loading extra images when required and disposing of unnecessary ones)
I would recommend you the first option. Leaves you more flexibility, e.g. when the data size increases the memory size.
I'd do it like this: Have a NSMutableDictionary with the cached images (as UIImage objects). If the image is not in the cache, look whether it's available as a file. If it's not available as a file, load it, put it into your dictionary and also write it to a file.
As for where to write the files to: you can either use the NSTemporaryDirectory() or create a directory inside your NSLibraryDirectory (use NSSearchPathForDirectoriesInDomains to locate it). The later has the advantage/disadvantage that it will be in the iTunes backup (whether that's an advantage or not depends on the use case). Using the Library directory is Apple's recommended way of storing data that is backed up but does not appear in the iTune's file exchange thingy (Documents directory).
I have started using EGOImageView to handle my caching; it's very versatile and handles the intricacies of caching for you.
It works very well for pulling images via http, you can find it on the EGO developer website here
http://developers.enormego.com/
For image caching solution on iOS platform, you might want to consider SDWebImage framework available at: https://github.com/rs/SDWebImage. It is very easy to integrate and takes care of all your image caching worries.: read more about the working here: https://github.com/rs/SDWebImage#readme
We recently picked this up for our app and it works great.