Unity3D update local assetBundle - unity3d

In my project, I have a bunch of items stored as assetBundles. In my server, I stored a list of item including their id and version. So ideally, using UnityWebRequest.GetAssetBundle(uri, versionId)I just get the item lists every time I open the app, if first opened, it will download every item; if secondly open, it will only download the one I have updated the version number on the server. Everything is very easy.
But now, I want to store those assetBundles at local first so that people don't need to download with cellular data.Is there an easy way to manage those assetBundles?

You can place the AssetBundles in the StreamingAssets folder. This is what the folder should look like:
Assets/StreamingAssets/
When you build the project, Unity will include the AssetBundles in the build. Of-course, you can use the Resources API but the StreamingAssets folder seems to be more appropriate here.
Once you place the AssetBundles there, you can use Application.streamingAssetsPath and AssetBundle.LoadFromFile to load the AssetBundle.
You can also use the WWW API with Application.streamingAssetsPath to load the AssetBundle.

You 'dont' keep a local text file. you have the version number inside the local bundle. You have a text file on the server. then get the text file, compare that with the version in the bundle and update if necessary.
In the server, you can have an assetbundle with only a textasset to secure that too.
you can build the asset bundles and have them in the streamingAssets folder or anywhere and use AssetBundle.LoadFromFile()

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.

Unity Asset Bundles Rebuilding with Old Data

I have a mobile project which displays various AR experiences to the user via a mobile application. This application is made in Unity.
Alongside this Unity project we have a second project that stores asset bundles exclusively. Each AR experience is a prefab marked with a unique asset bundle name. These bundles are stored online and downloaded into the main mobile application when relevant. We're having issues with having these bundles correctly update, when changing things on the prefab such as scale or rotation they aren't reflected in the rebuilt asset bundle.
Here's a look at the process we're using for rebuilding assets, It's only a simple script.
[MenuItem("Spiff/Build AssetBundles")]
static void BuildAllAssetBundles()
{
// BuildPlatformBundles(BuildTarget.iOS);
BuildPlatformBundles(BuildTarget.Android);
}
static void BuildPlatformBundles(BuildTarget platform)
{
// We convert the passed platform enum to a string.
string platformFolder = platform.ToString();
string assetBundleDirectory = "Assets/AssetBundles/" + platformFolder;
// Build our bundles out to the relevent platform specific folder.
if (!AssetDatabase.IsValidFolder(assetBundleDirectory))
{
AssetDatabase.CreateFolder("Assets/AssetBundles/", platformFolder);
}
BuildPipeline.BuildAssetBundles(assetBundleDirectory, BuildAssetBundleOptions.None, platform);
}
Currently we use 'BuildAssetBundleOptions.None' We've also tried the ForceRebuild flag but this has no effect. Am I correct in assuming that Unity has some sort of internal cache it keeps for assets bundles? If so can we clear this somehow so I can ensure 100% that the bundle I am building is going to be the most up to date based on the prefab tagged with it?
Loaded Assetbundles are indeed cached, and will remain so until AssetBundle.Unload() has been called to free up all memory accociated with the asset.
After the asset has been unloaded a newer version of the assetbundle can be downnloaded and instantiated with the new values (Assuming the file downloaded has all the updated information), else it will load the data from cache if available.
On a side note: It seems like you're still using the old assetbundle pipeline. Unity has a plugin tool that makes the assetbundle workflow considerably easier called the assetbundle browser found here. It comes with a way easier UI for building bundles and inspecting bundles, open source and a very customisable pipeline. It may be worth checking out.
Like remy_rm mentioned, do give the Unity Asset Bundle Browser tool a try. It gives more control over what assets are in the bundle.
Your problem can be solved if you ensure two things:
1- When you make changes to a prefab and create a new bundle, is it indeed created with the said changes? (again using the tool would make checking this easier)
2- The bundles you are downloading in the main application are the new ones and not the old cached ones. In Unity Webgl for instance, you need to clear the browser cache to be 100% sure that the application downloads the new asset bundles and doesn't use the old ones in browser cache.

Unity Asset Bundles - Which Files Do I Deploy?

I have created some asset bundles from my Unity assets using the directions given in the Unity documentation section on AssetBundle Workflow. After running the "Build AssetBundles" command, each asset bundle results in four files: myasset, myasset.meta, myasset.manifest, myasset.manifest.meta.
Now I am ready to deploy these bundles to a web server and implement downloading/caching in my Unity project. I have found numerous examples such as this that show the download URL to be a single file with a .unity3d extension. This is leading me to conclude that I am missing a step - I assume that all four of my files will be required by the app and that I have to do something to combine them into a .unity3d file first.
What file(s) do I need to deploy? Are there any additional steps that I need to take before my file(s) are ready to upload? Thanks in advance for any advice!
Just myasset will suffice.
Sometimes people optionally add .unity3d as a filename extension to their Asset Bundles. It is just a community convention, and is completely optional. Source (copied below)
Vincent-Zhang
Unity Technologies
Just a reminder, we don't have an official file extension ".unity3d" for asset bundle, it's not mandatory. You can use whatever file extension as you want, or without file extension.
But usually people use ".unity3d" as the file extension just because we used it in the official sample code at first time...
Unity creates the .meta files for all assets- you don't have to worry about those. In short, your myasset file is enough. I do not add file extensions to mine. Do note that if you use the strategy shown in the example that you shared that the client will re-download the bundle from the server every time. You need to additionally provide a version number if you want to take advantage of caching. You can see this in some of the method overloads here, the ones that have a Hash128 or uint "version" parameter. Caching is great because you can use the bundle that is already saved on the device next time instead of downloading from the server when no changes have occurred. The version/hash number you provide essentially gets mapped to the file name. Whenever a matching version is found, the file on disk is used. Update the version number to something else when the content changes to force the client to download anew.
You may want to reference the .manifest file for the CRC value listed there. You may have noticed a crc parameter in the link I shared as well. This can be used to ensure data integrity during transmission of the bundle data. You can make sure the downloaded content's CRC matches that of the bundle when you created it.

Streaming assets folder VS Resources Folder in Unity?

I want to Know the difference between Streaming assets folder and resources folder in Unity3d?
Want to extend answer by holo559.
Streaming Assets are just copied as files and can thus be accessed as such. Useful for including files like sqlite databases or other files you want to be able to use StreamReader on. They do not work on some platforms such as WebGL due to the web not having filesystem support. Can also be interchanged during runtime.
Resources are embedded into your program and are therefore platform independent. Useful for having example text files for configurations such as json or yml files.
Streaming Assets :
Any files placed in StreamingAssets are copied as it is to a particular folder on a target machine. Any asset placed inside StreamingAssets can be used while the application is running.
Resources :
Resources class allows you to find and access Objects including assets. You can access assets using "Resources.Load" stored in Resources. All assets in the "Resources" folders will be included in a build. This resources folder comes handy when we have to access multiple assets, instead of using their path names we can use its reference.
There are a few more differences worth mentioning:
1- Unity will include the dependencies of an asset when you put it in a Resources folder, Streaming Assets won't.
2- Using Resource API you can both load an asset and deserialize it. using Streaming Assets you have to do all file operations manually.
3- Resource API allows you to Unload unused assets.
4- Unity will try to create a lookup tree when your game launches, depending on the number of assets, this can take time.

Write a File into the App Bundle

I have a Webservice to download some News and write them into a plist-file somewhere in NSLibraryDirectory, thats fine. But if the user has no Internet connection or the webservice is offline or whatever, I load a Default-Newsfile from within the AppBundle.
At the moment I have to replace the Default-File manually before every AppStoreUpdate to keep it up to date.
My Question: Is there an easy way to write into the App Bundle while debugging via Simulator, so the Default-File will everytime be up to date.
I tought about something like:
#ifdef SIMULATOR
//Write to AppBundle
#endif
Note:
It's all about the time while I use the Mac and the Simulator, I don't want to do that in the Published App!
Yes, I already replace the Ressource in my Bundle, but by hand and I want it to realize automatically.
I want to keep my Projectfolder up to date, before I compile it for any Device or the AppStore.
AppBundle is Read-only you cannot write anything to it programmatically, however if you update the resources in your Project through Xcode, you get the updated file automatically in the AppBundle..
Ok, based on your comment, here's what you need (I think - still not completely clear on the question, but let me know if this works for you).
Create an empty file (say news.plist) in your project folder (SRCROOT). Add this to your repo.
Add this file in your project's resources and add it in Copy Bundle Resources step in Build Phases
When you download content from internet, save it to project's temporary folder, then copy it to SRCROOT/news.plist overwriting existing file (optionally add a check on file checksum to avoid unnecessary change). This step is required ONLY when running on simulator.
Whenever developers check-in, the updated news.plist should be checked in to the repo.
To make SRCROOT available in code, add SRCROOT=\"${SRCROOT}\" to GCC_PREPROCESSOR_DEFINITIONS.
Other developer won't need to do anything except the last step - check in the updated file every time it changes.
Does this help?
No, you might be possible to get the simulator to write to you App Bundle, but this does not mean that the file your project (the one that gets compiled when you build for the app store) will be updated.
Why not just save the new to the documents directory, then always load this file. After the app is started, start a background thread and try to update the plist file. Of you are successful in retrieving the news over the write the plist file in the document directory.
This way the user will have an file that was retrieved the last time the device was able to get the file.
You could add an file in the app bundle which you copy to the documents directory on first start of the application, just to make sure that the user has data in the app.