Asset Bundles - Unity-Technologies/EndlessRunnerSampleGame GitHub Wiki

This project showcase how to use Asset Bundles, to potentially allow for external distribution of new assets.

Architecture

Characters and Themes are assets bundles, meaning they are self contained archives that are loaded asynchronously in the game at runtime & not part of the assets built with the game. This can allow to have low/high resolution package of each and just load the right one depending on the device, or download new one without having to distribute an entirely new version of the applications.

For the sake of simplicity and time, that project only have a single version of each and only work with bundles that are shipped with the project (i.e. it does not implement grabbing packages from internet).

When the game load, it will fetch all bundles placed in the StreamingAsset folder (through AssetBundlesDatabaseHandler) to add them into Databases (CharacterDatabase and ThemeDatabase). When an operation need information or data for a specific character or theme, it just fetch that from those database.

Modify to use external package

One way to modify the project so it can get external package without having to rebuild & ship again the application would be:

  • Make it contact an external server that give it a list of the bundle (+ their versions) the server have
  • Make the game compare that list with its local one
  • Download/Replace all bundles that are new or more recent.
  • Fetch all bundles from the StreamingAssets & the downloaded cache to fill the database.

That way you could add new character/theme without the need to rebuild and resubmit your application.

Audio Mixer Special Case Study

The Audio Mixer interaction with bundles is a bit specific but allow to highlight one point to be careful about with Bundles and references.

If prefabs in our bundles reference the main AudioMixer as their output, this will cause those prefabs to have a dependency to this mixer. Which will make a copy of the AudioMixer to be put in each bundles (as the bundles don't know if the AudioMixer will be present in the game that will load that bundle).

If we have an objects in a scene (not in a bundle) reference the Audio mixer, and use that reference to set some value on it (e.g. volume in a setting popup) the bundles prefabs won't use those new values, as they are using their own copy of the mixer.

We have two solutions to fix that.

Assign the group on the bundled prefab at runtime

This is the solution we used in Trash Dash

Every objects that need to have the output of their AudioSource set to a group of the Audio Mixer have a script attached to them with the name of the group. On Awake, the script find the mixer (in our case, through our global music player instance), find the given group and assign it. That way we are sure everything is routed to the same unique mixer and not a copy in the bundle.

It also avoid copy of the mixer to be bundled as nothing in the bundle reference it now.

Make the mixer part of its own bundle

If we put the mixer in a new separate bundle (e.g. called base or common) then copies won't be put in each bundles, but instead each bundle will register a dependency to the "common" bundle (so it need to be shipped with the game or downloaded first).

This is good to share thing between bundle without copies, but lead to one limitation : our game (i.e. everything shipped with the executable outside of bundles) need to never reference the mixer. Otherwise we recreate the same problem : 2 audio mixers, one in the game, one in the "common" bundle.

We can then have a script that will load the Mixer from the common bundle and assign thing to objects in our game (like the 1st solution, but the other way around).