Packaging content with Addressable Assets | Open Projects Devlog

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
When creating a game, a solid content loading  strategy is a key part of the development process. Starting the game fast, streaming assets  in and out of memory, all of this has a fundamental role in providing the player with a smooth playing experience. In this 4th devlog, we’re going to take a look at the techniques we  employed to package the content of “Chop Chop”, an open-source action-adventure game demo we are making as part of the Open Projects initiative. As usual, the whole game is available for  you to explore on the Github repository, and you will find the link in  the description of this video. Before we talk about the way we  packaged content for Chop Chop, let’s take a small step back to understand  the problem we were trying to solve. In Unity you structure a game by breaking it down into scenes. When not using AssetBundles, scenes are then listed one by one in the Build Settings which defines what ends up being packed into the build. If a Prefab, a texture, or a material is referenced into one of those scenes, it will end up in the game build. We call these “direct references”. This doesn’t give much control over memory since when we load a scene, we also load all of its direct references. In addition to that, all assets that sit in  the folders named Resources are also included in one big compressed file included in the build. Even though we decide when to load these assets, we have limited control on when to unload them. In addition to this, this file cannot be bigger than 4GB. Moreover, there can be a hiccup at the beginning of the game when the information about this big archive is first loaded. This might be imperceptible on a PC, but on a console it can make a difference between succeeding or being rejected during a certification process. On mobile, it could mean a frustrated player  who uninstalls the game - and a bad review! For all these reasons, we decided to use  AssetBundles to pack our content and load it at runtime, only when needed. On top of that, we use the Addressable Assets package to easily configure, pack, build, and load these bundles. So the first step is defining the content strategy. In Chop Chop, the game begins with a main menu scene. From there, we can reach the gameplay phase which happens in scenes that we call Locations, always loaded one at a time. In addition to these, there are special scenes that we use for global managers, in charge of running cross-scene operations like saving and loading progress, playing music, and loading other scenes. So we decided that every scene mentioned so  far is going to be packed into bundles. This way, we ensure that the initial loading of  the game is very short. To do this, we simply have to mark scenes and their assets as Addressable and make sure they are in the right group. Groups are a functionality of Addressables that  allows to divide assets into logical units, to be then packed into  AssetBundles when building content. One important note: assets in the same Group can be built into multiple AssetBundles by choosing Pack Separately, so that they are as independent as possible from each other. However, Unity always requires at least one  scene in the build, which is designated as the entry point of the whole game. For this reason, we introduced a new, almost-empty scene called Initialisation which, as you can notice, is the only scene in the Build Settings. Initialisation is a one-use scene. Its only function is to load another scene called PersistentManagers, which is in charge of loading other scenes such as the main menu or Locations. At this point, Initialisation can unload itself and PersistentManagers takes over. From here, we’re in AssetBundle territory. Every new scene loading request will automatically find and load the correct AssetBundle that contains the scene and all of its dependencies. To reference these scenes we use a tool coming from the Addressable Assets package called “AssetReference”. AssetReference is a special type of field, which looks a lot like a direct reference, but it’s more like… the promise of a reference. This way we can have a reference to any asset which can be fulfilled at a later stage, when we actually need that asset. You can think of AssetReference fields as weak links that are not immediately connected. We have control over when to connect them, and when we need to, the Addressable system will find all of the necessary dependencies and load them too - if they’re not already loaded. It’s quite convenient. When you remove these links by unloading references, the asset and its dependencies can be unloaded, freeing memory up. Now let’s talk about an important topic that can be confusing at first: asset duplication. While dividing the content into bundles, we ran into a potential issue - as noted by some of the project’s contributors. Our game heavily relies on some ScriptableObjects  to carry messages across-scenes. If we packed our content the wrong way, these ScriptableObjects would get duplicated in two or more different bundles. If that happened the messages wouldn’t travel anymore, because at runtime the sender and the receiver would be effectively communicating over different objects in memory! What happens here is that these ScriptableObjects  are being packed in the build implicitly, meaning that while not initially marked as Addressables,  they were pulled into bundles due to them being a dependency. This can cause duplication if multiple objects in different bundles are referencing these ScriptableObjects. So the solution in this case was to just explicitly declare these assets as Addressables. The Addressable system will track the dependencies, realise that the needed assets are already in a bundle, and not pack them again. This avoids the duplication, and solves the problem with our event system. Just a side note. Duplication might be wanted in some instances. Consider the case of two characters  using the same gradient texture, and let’s assume these two characters  never appear in the game at the same time. In this case, it might be OK to pack the texture twice in the same bundles as the characters, so that they are available without having  to load an additional, shared, AssetBundle. So ultimately, look at the structure and gameplay  of your game, and design the packing and loading strategy that makes sense for you. As for us, the next step is to better structure the Addressable Groups in a way that allows us to load a level, and its dependencies, without pulling in unnecessary assets. This might be something we will do closer to the end of the project, since - luckily - the Addressables system doesn’t care where an asset is located, so we can move assets between Groups later on  and we won’t need to change anything in our code. The development of Chop Chop continues, and it’s not too late to join us on this journey. To get up to speed, check out the forums and the wiki on the Github repository, linked below. Thanks for watching, and we hope you are enjoying  following the development of Open Projects!
Info
Channel: Unity
Views: 34,140
Rating: undefined out of 5
Keywords: Unity3d, Unity, Unity Technologies, Games, Game Development, Game Dev, Game Engine, content loading, addressables, addressable assets, addressableassets, DLC, downloadable content, mods, modding, asset bundles, assetbundles, in-app purchases, iap, in app purchase, content delivery
Id: XIHINtB2e1U
Channel Id: undefined
Length: 6min 35sec (395 seconds)
Published: Tue Apr 27 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.