top of page
back2.png
land.jpg
back.png

Google instant play + Unity Asset Bundle
(Google asset delivery)

To publish the game for Google Play Instant it is necessary that the size of the game should be less than 20 megabytes. (The maximum size for the instant version has been changed from 15 MB to 20 MB.)

 
Considering the scale of the project, assuming the optimization of assets and removing unnecessary items, it may not be possible to reach this volume. This is where there is no choice but to use Asset Bundle.
 

In this article, we will try to reduce the size of the game using asset bundles and solve common issues in the process.


 

0- Assets and Final Output

First, keep in mind that the Scenes specified in the Build Settings and all the assets referenced by them will be included in the final build.
 
Also, all the assets that are in the Resources folder (any folder with this name, under the Assets folder or Packages with any depth) and the StreamingAssets folder, as well as the assets that are referenced here, will come in the final build.

 

Also, all the codes that are not in the Editor folder and are under the Assets folder or have Assembly Definition will come by default in the final build.


The items included in the final build can be seen in detail through the Console window by clicking on the three dots on the top right and opening the Log Editor (Open Editor Log). Scroll down to see the logs for the latest build.
 

 

 

 

 

 

 

 

 


"Sample log and volume of different parts without compression in the final output"

1- Using Asset Bundle

In this way, you can bundle assets (including prefab, music, sprite, etc.) and also scenes (can't have both assets and scenes in the same bundle) to download and use later in the game.
 
You can serve these bundles in different ways. In this article, we use Google's APIs to serve these bundles so that we have higher reliability and
don't have the trouble of setting up the server.

If you are using Unity 2019.4 and above, you can use Addressables to download assets.
The tutorials of this method along with examples are available on the website of this plugin.

In this article, we download the Google Asset Delivery package and add it to the project. Please note that at the time of writing this article, the latest version (1.8.2) requires Unity 2023, which is still in beta!!
 
You can find the previous versions of this package from This link. In this article, we use version 1.7.0.

1.1- Bundling assets and scenes

Depending on the way you developed your game, you might want to bundle assets, bundle the scenes, or both.
 
If you put most of the contents in the Resources folder, use the first method, and if you use assets directly in the scenes, use the second method.
If you have a significant section in both the Resources folder and the scene, you should create at least two different bundles, one for each.
 
To bundle assets, click on Asset Labels at the bottom of the Inspector window to open the preview window (if it's not open already), then set the AssetBundle field to the desired name. If you have added the Google package, at least two default bundles have been added.
Do not use these because Google's own example assets will also be included in the final build. In this article, we use "Instantbundle".

"Selecting an instantbundle name for a prefab"


Choose a suitable bundle for the scenes in the same way. Note that you cannot use the same name for assets and scenes. You can make several different bundles for different stages of the game and download them based on when they appear in order to play have a very smooth and without interruption experience.

1.2- Making a bundle

There are several different methods to build a bundle (Build asset bundle). In this article, we use the following piece of code to add the bundle creation option to the Assets menu.



 

Save the piece of code above with the name BuildAssetBundles.cs under a folder called Editor (it doesn't matter what depth it is under the Assets folder, for example, Assets/Scripts/Editor/BuildAssetBundles.cs is fine).
In Unity, open Assets from the top tab and click the Build AssetBundles button.

“Build AssetBundles option on the Assets tab”

The AssetBundles will take some time to build. When the build process is finished, the AssetBundles folder should be created under the Assets folder, where the bundles you specified are created in this folder.
 
Now select the Google menu from the top tab. A window similar to the one below should be opened.

 

"Google Asset Delivery window"

Now click the “Add Folder” button and select the folder created in the previous step. The list of bundles created with their dependencies (if you have several bundles that depend on each other), errors, and size will be visible here.
 
 
The default delivery mode of these packages is Do Not Package, which will not include
them in the final build. Set the packages you want to use on “On Demand”.

Please note that you can only use the On Demand mode for the instant version. If you use Asset Bundle for other purposes, you can use the Install Time or Fast Follow options so that the packages are automatically downloaded as soon as the game is installed.

Also, by installing the AssetBundle Browser package (Using the Package Manager), you can also view the list of bundles with their assets and scenes, take a build or edit a little.
"The AssetBundl
e Browser window shows the list of bundles and assets inside it. In this section, the items that were not directly bundled but were needed can also be seen.”

1.3- Use of bundles

As mentioned in section 1.1, there are two ways to use bundles (probably more than two ways, but we will focus on the same two ways here.)

1.3.1- Similar to the Resources folder

Similar to using the Resources folder to load assets, these assets can be loaded by downloading the bundle. For this purpose, we first create a request for the mentioned asset bundle and keep its reference.

Ad.Banner = true;
PlayAssetBundleRequest bundleRequest = PlayAssetDelivery.RetrieveA
ssetBundleAsync(assetBundleName);

This request can be used to track the status of the request:


bundleRequest.IsDone //To see if the request is done  
 
bundleRequest.DownloadProgress //To see how much is downloaded (between 0 and 1). This can be used to show a progress bar to the player. Must be checked in a loop, of course.



 
When downloading the bundle is finished (the bundle will be cached automatically and will be delivered immediately next time), request the bundle from the reference and keep it somewhere

 

(bundleRequest.Error == AssetDeliveryErrorCode.NoError)

Debug.Log("Asset bundle Downloaded with no error...");
instantBundle = bundleRequest.AssetBundle;



The following code snippet is a suggested process for downloading and showing a progress bar to the user (the code snippet is part of a larger system and has been scaled down for training, so it may not work way it is. If you have any problem, let us know, so we can fix it.
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

After that, we can load and use the assets like resources.
 

InstantBundle.LoadAsset<GameObject>("assets/address/to/asset.prefab");


The main difference is in the type of storage in the bundle. Assets are stored flat in bundles and we don't have folders, although their full addresses are stored in lowercase for each file. In the AssetBundle Browser's Inspect tab, you can see the addresses of all the files inside. Also, to load them (if you use the full address), you must add the file extension.                    

"Files inside the bundle and their full address"


After creating the asset bundle, if you delete these files, the files will not be visible in the mentioned window, but they still exist in the bundle. This happens because this tool can’t show them, thus, it is recommended not to use this tool to manipulate or create bundles.
 


1.3.2-Scene bundlings

If the assets are used (directly or referenced) in the scene in the scene, in order to reduce the size of the game, we need to bundle the entire scene and remove it from the build. In this method, like the previous method, download the bundle and then get the list of scenes in the bundle.

sceneBundle = bundleRequest.AssetBundle;
string[] scenePath = sceneBundle.GetAllScenePaths();

 

By using the name of the scenes, you can load the desired scene.
 

SceneManager.LoadScene(scenePath[0]);


Obviously, if you only have one scene in the game, you need to create a new scene to download the bundle and welcome the user. Do not forget to remove the main scene from the output from the Build Settings section, otherwise, the volume reduction will not affect build size.

 


1.4-Common problems

Before we start building the project, we need to fix some problems. Below is a list of the problems you may encounter. It is worth mentioning that you can go directly to section 1.5 and build the instant version and refer to this section when problems occurred and fix them. Also, if a problem was not mentioned or was fixed in the next versions of the google asset delivery, let us know so we update article accordingly.
Note that using a bundle is like taking a snapshot of assets. If these assets are in the Resources folder, are referenced in the scene, or are still included in the output of the scene in the Build Settings section, they will still affect the final build size. More importantly, after changing these assets and scenes, the snapshot will not be updated and you have to build the bundles again.

1.4.1- java.lang.ClassNotFoundException error in AssetPackManagerFactory class when requesting bundle download

To fix this, open the asset_delivery.txt file
The file is located in the Assets/GooglePlayPlugins/com.google.play.assetdelivery/Proguard folder.
 

Find the rule for AssetPackManagerFactory and replace it with the more general rule as follows:
Default rule:

-keep class com.google.android.play.core.assetpacks.AssetPackManagerFactory {
  <init>();
 
  public static com.google.android.play.core.assetpacks.AssetPackManager getInstance(android.content.Context);

}


Replacement rule:

-keep class com.google.android.play.core.assetpacks.** {*;}


 
If you minify the project (which is recommended, as it can reduce the size of the project by up to 0.5 megabytes depending on the amount of scripts), you must add this rule to the ProGuard file in Unity.
To minify in the Project Settings section, open the Player tab of the Publishing Settings section (if this section does not exist, the target platform of your project may not be Android.), and at the end, under the Minify section, set both Release and Debug to Proguard mode. Then if you haven't checked “Custom Proguard File” check the box so that a file (proguard-user.txt) will be created for you under Assets/Plugins folder.

"Publishing Settings on the Player tab of the Project Settings window”

Now add the following rule to it.
 

-keep class com.google.android.play.core.assetpacks.** {*;}
-keep class com.goog
le.android.play.core.tasks.** {*;}



 


1.4.2- The problem of downloading status getting stuck in Pending mode

In some cases, it has been seen that the download status of the bundle is stuck in Pending mode, although closing the game completely and opening it usually solves this problem, but it cause very bad user experience.
To solve this issue, it is better to consider a condition for prolonging the pending status, and if that happens, cancel the request and try again.
 
This case is fully explained in this issue, but it has not been definitively solved for years.

 
To cancel the request, you can use the following code snippet in the iteration loop suggested in section 1.3.1. Before entering the iteration loop, set the startTime value (20 seconds is considered a suitable "wait" value):
 

 

if ((Time.realtimeSinceStartup - startTime) > 20 && bundleRequest.Status == AssetDeliveryStatus.Pending)
{
  bundleRequest.AttemptCancel();
  yield return new WaitUntil(() => bundleRequest.Error == AssetDeliveryErrorCode.Canceled);
  startTime = Time.realtim
eSinceStartup;
  bundleRequest = PlayAssetDelivery.RetrieveAssetBundleAsync(assetBundleName);
}

 
 


1.4.3- indirect_reference_table.cc:65 JNI ERROR (app bug): accessed stale Local 0x1  (index 0 in a table of size 0) error

This error means that you are accessing an area of memory that may no longer be available. Depending on the error, many Different Things can lead to this message (Read more). When you use scene bundling (in theory, it can also happen in the asset bundling method!) and you encounter this message when loading the scene from the bundle, it is most likely that a part of the program was created by Unity under the assumption that there is no need to It has been deleted and you are now trying to access it. This may happen even more if you activate the Strip Engine Code section in the Player tab of the Project Settings (It is recommended to activate this item as well, depending on the packages and libraries used and the amount of scripts, it may reduce the build size up to 0.5 megabytes.)

"Strip Engine Code Settings. It is suggested that if you have a significant amount of library and codes in the project, set the stripping level to the highest possible level and manage to remove the codes manually.”

To solve this problem, we need to tell the game engine in a way that the items that are not included in the build but are supposed to be used in the bundles are really needed.
Pay attention, by raising the stripping level, it is more likely to remove a chunk of code used in bundles, therefore the chance of occurring this error will increase!
To manage the functions, you can use the [preserve] annotation to keep the functions.
On this page of the Unity documentation, the removal rate for different levels of stripping and also various annotations are explained.

Important note:
Even by disabling this option, Unity and third-party packages such as Occlusion Culling, NavMesh, and Cinemachine may be removed. To fix this problem, it is better to use these items in the Intro scene (the small scene that is included in the build) as well.
Be careful that these items may take a lot of data with them if they are baked. These data is usually presented in the build log under “Level” category.

1.5- How to Build Instant version

In the first step, if you haven't installed the Google Instant package yet, download and install it. Then open Google from the top tab and select Build settings from the instant section.

 


 «Play Instant build settings»


 
In the opened window, set the Android Build Type to Instant and disable the Full "Instant play" game option. Although the goal is full instant play, this option does not work with AssetBundle and we need to submit a form for that.
 
 

 

 
 
 
 
 
 
 
 
 
"Full Instant Play conflict with AssetBundle"
 

 

After setting Build Settings, hit Google Build from the same menu, select the appropriate folder, and let the project build.
 

 

 

 

 

 

 

 


"Instant project creation"


 
The output should be a compressed .aab (Android App Bundle) file. Please note that the size of this file can be larger than the minimum set by Google (20 MB). To get the final output volume, open the file with one of the compression tools (eg Winrar), the base folder is the size considered by google. In this file, there should be a folder with t
he bundle name.

 

 

 

 

"The final aab file"


 
Congratulation! this file is your final output and can be used for uploading to Google Play.
 

 
 

1.6- Testing Instant Version

For the comprehensive test, it is better to upload this version to Google Play in internal test then open the game as an internal tester and make sure it works properly.
 
But considering the time-consuming nature of this process, it is better to test it locally first. For this purpose, first download and install Bundle Tool.
 
If you don't have Git installed, download and i
nstall it from here (we need it for git bash, assuming you are on windows. You can also use Windows cmd or Powershell, instead).
 
Now, use the bundle tool to generate the APKs file from the aab file obtained in the previous steps using following flag:

--local-testing=true


Then install it on a phone (or and emulator) which its developer mode is activated. The following code snippet takes the address argument of bundletool, the keystore key, the name used to sign the keystore alias, and also the aab file without the extension and produces the APKs output.
 

 

 
 

 

 

 

 

 

 

 

 

 


You can run the commands line-by-line in Gitbash (right-click to open Gitbash and select “Git Bash Here”) or save the file and extract and install the APK files with the command below. Instead of brackets, use their equivalent.
 
 

./BuildApksAndInstall.sh [Bunde Tool Address] [Keystore Address] [Keystore Alias]  [Keystore password] [Path to my awesome game]


 
Important note:
If you have already installed the same version of the game as Instant on your phone, you will not be able to download the bundle locally and you will encounter the following error.
 
Error Unity Failed to retrieve asset pack: Local testing directory '/storage/emulated/0/Android/data/com.funtory.monsterpet/files/local_testing' not found.
 
The above command will install the game as a standard file (not instant) on the phone so that you can test the bundl
e.

0- Assets and Final Output
1.1- Bundling assets and scenes
1.2- Making a bundle
1.3- Use of bundles
1.3.1- Similar to the Resources folder
1.3.2-Scene bundlings
1.4-Common problems
1.4.1-java.lang.ClassNotFoundException error in AssetPackManagerFactory class when requesting bundle download
1.4.2-The problem of downloading status getting stuck in Pending mode
1.4.3- indirect_reference_table.cc:65 JNI ERROR (app bug): accessed stale Local 0x1 (index 0 in a table of size 0) error
1- Using Asset Bundle
1.5- How to Build Instant version
SetAssetBundleName_edited_edited_edited.
BuildAssetBundles.png
GoogleAssetDelivery.png
AssetBundleBrowser-Configure.png
AssetBundleBrowser-Browser.png
minify.png
stripEngine.png
PlayInstantSetting.png
fullInstantConflict.png
BuildInsantBundle.png
Build_Log.png
AABFile.png
1.6- Testing Instant Version
footer games2.png
back2.png

Let’s Work Together

Get in touch so we can start working together.

  • LinkedIn
  • Twitter
  • Instagram

Thanks for submitting!

bottom of page