Tales from the optimization trenches: Saving memory with Addressables

Tales from the optimization trenches: Saving reminiscence with Addressables

Environment friendly streaming of property out and in of reminiscence is a key component of any high quality sport. As a marketing consultant on our Skilled Providers workforce, I’ve been striving to enhance the efficiency of many buyer initiatives. That’s why I’d prefer to share some tips about the best way to leverage the Unity Addressable Asset System to reinforce your content material loading technique.

Reminiscence is a scarce useful resource that you need to handle rigorously, particularly when porting a challenge to a brand new platform. Utilizing Addressables can enhance runtime reminiscence by introducing weak references to stop pointless property from being loaded. Weak references imply that you’ve management over when the referenced asset is loaded into and out of reminiscence; the Addressable System will discover the entire obligatory dependencies and cargo them, too.

This weblog will cowl a variety of situations and points you’ll be able to run into when establishing your challenge to make use of Unity Addressable Asset System – and clarify the best way to acknowledge them and promptly repair them.

Stock instance 


For this sequence of suggestions, we are going to work with a easy instance that’s arrange within the following method:

  • We have now an InventoryManager script within the scene with references to our three stock property: Sword, Boss Sword, Defend prefabs.
  • These property will not be wanted always throughout gameplay.

You may obtain the challenge recordsdata for this instance on my GitHub.

We’re utilizing the preview bundle Reminiscence Profiler to view reminiscence at runtime. In Unity 2020 LTS, you need to first allow preview packages in Undertaking Settings earlier than putting in this bundle from the Bundle Supervisor.

When you’re utilizing Unity 2021.1, choose the Add bundle by identify possibility from the extra menu (+) within the Bundle Supervisor window. Use the identify “com.unity.memoryprofiler”.

Stage 1: Laborious references, no Addressables

Let’s begin with probably the most fundamental implementation after which work our method towards the perfect method for establishing our Addressables content material. We’ll merely apply exhausting references (direct project within the inspector, tracked by GUID) to our prefabs in a MonoBehaviour that exists in our scene.

When the scene is loaded, all objects within the scene are additionally loaded into reminiscence together with their dependencies. Which means that each prefab listed in our InventorySystem will reside in reminiscence, together with all of the dependencies of these prefabs (textures, meshes, audio, and so forth.)

As we create a construct and take a snapshot with the Reminiscence Profiler, we are able to see that the textures for our property are already saved in reminiscence though none of them are instantiated.

Textures for our objects are saved in reminiscence though they aren’t but instantiated.

Drawback: There are property in reminiscence that we don’t at the moment want. In a challenge with numerous stock objects, this could lead to appreciable runtime reminiscence stress.

Stage 2: Implement Addressables

To keep away from loading undesirable property, we are going to change our stock system to make use of Addressables. Utilizing Asset References as a substitute of direct references prevents these objects from being loaded together with our scene. Let’s transfer our stock prefabs to an Addressables Group and alter InventorySystem to instantiate and launch objects utilizing the Addressables API.

Construct the Participant and take a snapshot. Discover that not one of the property are in reminiscence but, which is nice as a result of they haven’t been instantiated.

No stock merchandise textures seem in reminiscence; solely TextMeshPro textures.

Instantiate all of the objects to see them seem accurately with their property in reminiscence.

Drawback: If we instantiate all of our objects and despawn the boss sword, we are going to nonetheless see the boss sword’s texture “BossSword_E ” in reminiscence, though it isn’t in use. The rationale for that is that, when you can partially load asset bundles, it’s not possible to mechanically partially unload them. This habits can develop into notably problematic for bundles with many property in them, akin to a single AssetBundle that includes all of our stock prefabs. Not one of the property within the bundle will unload till the complete AssetBundle is now not wanted, or till we name the pricey CPU operation Sources.UnloadUnusedAssets().

The feel BossSword_E stays in reminiscence even after the boss sword has been launched.

 

READ  Out Now: ‘XCOM 2 Collection’, ‘Space Marshals 3’, ‘My Memory Of Us’, ‘Lamplight City’, ‘Iris and the Giant’, ‘Shadow Fight Arena’, ‘Sine the Game’ and Extra

Stage 3: Smaller Bundles

To repair this downside, we should change the best way that we set up our AssetBundles. Whereas we at the moment have a single Addressable Group that packs all of its property into one AssetBundle, we are able to as a substitute create an AssetBundle for every prefab. These extra granular AssetBundles alleviate the issue of enormous bundles retaining property in reminiscence that we now not want.

Making this alteration is straightforward. Choose an Addressable Group, adopted by Content material Packaging & Loading > Superior Choices > Bundle Mode, and go to Inspector to alter the Bundle Mode from Pack Collectively to Pack Individually.

Through the use of Pack Individually to construct this Addressable Group, you’ll be able to create an AssetBundle for every asset within the Addressable Group.

The property and bundles will appear like this:

Now, returning to our unique take a look at: Spawning our three objects after which despawning the boss sword now not leaves pointless property in reminiscence. The boss sword textures at the moment are unloaded as a result of the complete bundle is now not wanted.

Drawback: If we spawn all three of our objects and take a reminiscence seize, duplicate property will seem in reminiscence. Extra particularly, this may result in a number of copies of the textures “Sword_N” and “Sword_D”. How might this occur if we solely change the variety of bundles?

Stage 4: Repair duplicate property

To reply this query, let’s contemplate every part that goes into the three bundles we created. Whereas we solely positioned three prefab property into bundles, there are extra property implicitly pulled into these bundles as dependencies of the prefabs. For instance, the sword prefab asset additionally has mesh, materials, and texture property that should be included. If these dependencies will not be explicitly included elsewhere in Addressables, then they’re mechanically added to every bundle that wants them.

Our Asset Bundles for the Sword and BossSword include a few of the similar dependencies.

Addressables embrace an evaluation window to assist diagnose bundle structure. Open Window > Asset Administration > Addressables > Analyze and run the rule Bundle Structure Preview. Right here, we see that the sword bundle explicitly contains the sword.prefab, however there are a lot of implicit dependencies additionally pulled into this bundle.

In the identical window, run Examine Duplicate Bundle Dependencies. This rule highlights the property included in a number of asset bundles based mostly on our present Addressables structure.

Evaluation reveals that we have now duplicate textures and meshes between our sword bundles, and all three bundles duplicate the identical shader.

We are able to stop the duplication of those property in two methods:

  1. Place the Sword, BossSword and Defend prefabs in the identical bundle in order that they share dependencies, or
  2. Explicitly embrace the duplicated property someplace in Addressables

We wish to keep away from placing a number of stock prefabs in the identical bundle to cease undesirable property from persisting in reminiscence. As such, we are going to add the duplicated property to their very own bundles (Bundle 4 and Bundle 5).

The duplicate textures are explicitly positioned in their very own bundles.

Along with analyzing our bundles, the Analyze Guidelines can mechanically repair the offending property through Repair Chosen Guidelines. Press this button to create a brand new Addressable Group named “Duplicate Asset Isolation,” which has the 4 duplicated property in it. Set this group’s Bundle Mode to Pack Individually to stop every other property now not wanted from persisting in reminiscence.

Stage 5: Cut back Asset Bundle metadata measurement in massive initiatives

Utilizing this AssetBundle technique can lead to issues at scale. For every AssetBundle loaded at a given time, there’s reminiscence overhead for AssetBundle metadata. This metadata is prone to eat an unacceptable quantity of reminiscence if we scale this present technique as much as tons of or 1000’s of stock objects. Learn extra about AssetBundle metadata within the Addressables docs.

View the present AssetBundle metadata reminiscence price within the Unity Profiler. Go to the reminiscence module and take a reminiscence snapshot. Look within the class Different > SerializedFile.

1,819 bundles are at the moment loaded with SerializedFile reminiscence, with a complete measurement of 263 MB.

There’s a SerializedFile entry in reminiscence for every loaded AssetBundle. This reminiscence is AssetBundle metadata moderately than the precise property within the bundles. This metadata contains: 

  • Two file learn buffers
  • A kind tree itemizing each distinctive sort included within the bundle
  • A desk of contents pointing to the property

Of those three objects, file learn buffers occupy probably the most house. These buffers are 64 KB every on PS4, Swap, and Home windows RT, and seven KB on all different platforms. Within the above instance, 1,819 bundles * 64 KB * 2 buffers = 227 MB only for buffers.

Seeing because the variety of buffers scales linearly with the variety of AssetBundles, the straightforward answer to cut back reminiscence is to have fewer bundles loaded at runtime. Nevertheless, we’ve beforehand averted loading massive bundles to stop undesirable property from persisting in reminiscence. So, how can we scale back the variety of bundles whereas sustaining granularity?

A stable first step can be to group property collectively based mostly on their use within the software. If you may make clever assumptions based mostly in your software, then you’ll be able to group property that you already know will at all times be loaded and unloaded collectively, akin to these group property based mostly on the gameplay stage they’re in.

Then again, you is perhaps in a scenario the place you can’t make protected assumptions about when your property are wanted/not wanted. In case you are creating an open-world sport, for instance, then you definately can not merely group every part from the forest biome right into a single asset bundle as a result of your gamers may seize an merchandise from the forest and carry it between biomes. The complete forest bundle stays in reminiscence as a result of the participant nonetheless wants one asset from the forest.

Luckily, there’s a approach to scale back the variety of bundles whereas sustaining a desired stage of granularity. Let’s be smarter about how we deduplicate our bundles.

The built-in deduplication analyze rule that we ran detects all property which can be in a number of bundles and effectively strikes them right into a single Addressable Group. By setting that group to Pack Individually, we find yourself with one asset per bundle. Nevertheless, there are some duplicated property we are able to safely pack collectively with out introducing reminiscence issues. Contemplate the diagram beneath:

We all know that the textures “Sword_N” and “Sword_D” are dependencies of the identical bundles (Bundle 1 and Bundle 2). As a result of these textures have the identical dad and mom, we are able to safely pack them collectively with out inflicting reminiscence issues. Each sword textures should at all times be loaded or unloaded. There may be by no means concern that one of many textures may persist in reminiscence, as there’s by no means a case the place we particularly use one texture and never the opposite.

We are able to implement this improved deduplication logic in our personal Addressables Analyze Rule. We’ll work from the present CheckForDupeDependencies.cs rule. You may see the total implementation code within the Stock System instance.

On this easy challenge, we merely decreased the full variety of bundles from seven to 5. However think about a situation the place your software has tons of, 1000’s, or much more duplicate property in Addressables. Whereas working with Unknown Worlds Leisure on a Skilled Providers engagement for his or her sport Subnautica, the challenge initially had a complete of 8,718 bundles after utilizing the built-in deduplication analyze rule. We decreased this to five,199 bundles after making use of the customized rule to group deduplicated property based mostly on their bundle dad and mom. You may be taught extra about our work with the workforce in this case story.

That could be a 40% discount within the variety of bundles, whereas nonetheless having the identical content material in them and sustaining the identical stage of granularity. This 40% discount within the variety of bundles equally decreased the scale of SerializedFile at runtime by 40% (from 311 MB to 184 MB).

Conclusion

Utilizing Addressables can considerably scale back reminiscence consumption. You will get additional reminiscence discount by organizing your AssetBundles to fit your use case. In any case, built-in analyze guidelines are conservative with a view to match all functions. Writing your individual analyze guidelines can automate bundle structure and optimize it to your software. To catch reminiscence issues, proceed to profile typically and examine the Analyze window to see what property are explicitly and implicitly included in your bundles.

Try the Addressable Asset System documentation for extra greatest practices, a information that can assist you get began, and expanded API documentation. 

When you’d prefer to get extra hands-on assist to learn to enhance your content material administration with the Addressable Asset System, contact Gross sales a few skilled coaching course, Handle Content material with the Addressable Asset System. We’re at the moment providing this coaching by way of scheduled dwell public periods, although will probably be accessible on-demand as nicely. 

Leave a Reply

Your email address will not be published. Required fields are marked *