[Official] How Did Asset Bundle Variant Fail To Satisfy Your HD/SD Use Case?

Hello Friends.

Every since Unity 5, we have release a feature called Asset Bundle Variant. One of it’s goal is to make it easy for users to ship games that uses different sets of assets based on platform (screen resolution). This is commonly known as the HD/SD problem.

Few months has passed and it is clear that the idea has not taken off. And I want to know why…

For those who has tried it and given up, please tell us where the system came up short and/or any pain points. Hopefully we will take this and collaborate with the Asset Bundle Team to fix/improve the system.

I look forward to hearing from you.

Thanks for kicking off this thread, @ColossalPaul :slight_smile:

I think my team’s use case is relatively simple. We want to load a different set of art assets depending on the platform and/or resolution so that a low-end/low-resolution device isn’t wasting memory by loading large, high resolution art assets. Right now we want to deliver around 6 different sets of assets, each at different scales (low end art scaled to ~960x640, high end art scaled to ~5120x2880).

We aren’t thinking about downloadable content at this point. We just want to ship the game with the asset bundles already included in the package (although, since we’re making an art-heavy game and we want to support Apple TV, we have to deal with the On Demand Resources stuff :hushed: ).

I’ve tried the AssetBundleManager from BitBucket, but, for us, it’s not the best solution. Here’s why:

  • The Simulation Mode doesn’t support asset bundle variants, so we can’t easily/quickly test if our bundles are working correctly across multiple resolutions. Since multi-resolution support is the only reason why we need asset bundles in the first place, this is a big pain point for us.

  • The documentation is lacking. The ReadMe and this tutorial all focus on editor workflows, but there’s nothing to describe how to include asset bundles in my builds or how to load them locally afterwards (I’m assuming I need some kind of a custom build post processor that copies the platform’s asset bundles somewhere? And then I do a file:// request to that path at runtime?).

  • Following that, there’s very little documentation on how to work with On Demand Resources. The ReadMe claims that the AssetBundleManager handles that all for me, but then why does the sample project have a bunch of extra code for creating and loading those Resources objects? Will that be merged into the Manager logic at some point?

  • The AssetBundleManager and its dependencies generate a whole bunch of garbage whenever you interact with it. Some of that can’t be avoided, I’m sure… but we’re trying to build a high performance game with a streaming world, and we want to avoid hitting the garbage collector as much as possible.

  • It’s annoying to have to include scenes in asset bundles in order to make the asset bundle variants work. Because of that, scene loading is slower (making our performance/streaming requirements harder to meet), and we have to add that extra bit of boilerplate logic that loads a bootstrap scene to then load the scene we actually want. It’s just added complexity.

  • The dependency tracking and reference counting that the AssetBundleManager is decent, but I believe we’re still responsible for unloading our scenes from the AssetBundleManager, correct? This is another reason why it’s annoying to have to include scenes in asset bundles… I’d rather not deal with that :slight_smile:

  • The existing tools make it difficult to tell if there are duplicate assets across multiple bundles or if there are discrepancies between variants (the folder structure and filenames all have to match exactly, as far as I know. But the tools don’t help debug issues related to that). It’s also not obvious how the asset bundle system interacts with the sprite packer. Are my source sprites being included in the bundles in addition to the atlas?

  • It’s already a bit out of date with the latest 5.3 build of Unity (e.g., doesn’t use the chunked compression when building asset bundles, isn’t using the new SceneManager APIs…).

  • As a more general point, it just takes so much code and time to set everything up! I wish the tools were easy enough that a production artist could create and build the asset bundles for us. Apple’s @2x/@4x approach is so simple and easy to use… I understand the reasons why Unity chose not to go that route. But with all the complexity in the asset bundle system, it is so easy to make mistakes :frowning: What takes me 5 minutes to setup for Apple is taking me hours upon hours to setup in Unity (and I’m still not there!).

I apologize for the wall of complaints :slight_smile: I’ll add more feedback as it comes to mind, but these are my most immediate concerns :slight_smile:

I will say that the UI for tagging the asset bundle names + variants is super nice and simple! If only the rest of the system was that easy to use :smile:

7 Likes

True, it’s a real limitation. We do have some issues to support it for now. Will see if we can find a way to deal with it.

What kind of garbage are generated? We really want to avoid that if we can.

No, you don’t have to include scenes to use variant. You can definitely have a prefab in a normal AssetBundle which is using a material in a variant AssetBundle.

As above, you don’t have to use scene. If you use prefab or other assets, it will be easier to unload in this case.

Totally agree, we should make some useful tools.

For sprite packer, the original texture of the sprite won’t be added to the bundle. And you should add all the sprites in the same packer into the same AssetBundle, otherwise the atlas will be duplicated in each bundle.

True, we need update the demo.

And really appreciated your feedbacks.

2 Likes

To echo @bryantdrewjones #5, #6 and #7 were huge pain points for us. If there is no need to include scenes in the asset bundles in order for the variants to work, my experience has shown the complete opposite. Prefabs might work, but not everything that need variants are prefabs (main example would be UI).

I would like to believe Unity’s position that this is a solved problem, but my experience with Asset Bundles is that it is needlessly complicated and requires a ton of code and effort to get working.

I have no clue how Asset Bundles and Variants are implemented internally, but here is my suggestion:

  • Separate the variant system from asset bundles. Asset bundles solve an entirely different problem (getting downloadable / DLC content into a game). Asset bundles change the way you load content and they also incur a big memory cost during loading.

  • All I want to do as a developer is choose asset A or B based on some setting in the code. It is just a map from an original asset to an HD or SD specific asset. For each Object that has a variant associated with it, just throw its GUID into a map. As you load the Object into memory, check the active variant and load the specific asset at runtime (whether it is in a scene, a prefab, or loaded from code). That’s ALL this system needs to do. The extra complexity of bundling the assets should be removed.

Variants are the kind of thing you worry about near the end of your production cycle, so the system needs to be flexible and easy to use. If you have to jump through a bunch of hurdles which may or may not be compatible with all the work you put into the game so far, it’s no surprise that a lot of developers just skip the system altogether.

4 Likes

I haven’t done a deep profile on it, but just looking through the code there are tonnes of places that explicitly create new object instances (like the loading operation classes), perform string manipulations, and use coroutines. All of that generates garbage that can probably be avoided.

Can you please provide a deeper explanation of how to use asset bundle variants without needing to include scenes in the asset bundles? Like @deemen said, I haven’t had any luck with that at all. And not every object with a sprite renderer in my scenes are prefabs :sweat_smile:

I 100% agree with @deemen about this point. It’s too hard and frustrating to plug the current asset bundle workflow into an existing project that is already in production. And unfortunately that’s the boat I’m in right now :frowning:

Maybe I am missing something but once I tried to use Asset Bundles and new Variants I got the demos working fine and then after trying to use it on real project it failed at the very first moment → trying to build asset bundles.

It simply doesn’t allow me to create an asset variant that has two files with the same name but at different paths in one variant. All I got was error about hash collision:

Like so:

its not very uncommon to have background.png a couple of times at different path in the same bundle.

So my question is, was I missing something trivial or asset bundles and variants just dont support non-unique file names? I didn’t find anything in docs about that.

@bryantdrewjones @deemen . This has been posted many months ago. Check the original thread. But here it is a gain. Using prefabs + variants without scene in bundle.

I’m still listening/collecting all the pain points. Do keep them coming… while we try to see how it (variant system) could be improved.

2130027–140157–Variant2.zip (84.3 KB)

1 Like

Just to clarify – every game object that has a sprite renderer component that wants to use asset bundle variants needs to be a prefab for this to work?

For my purposes, that doesn’t help me out at all, unfortunately :frowning: My existing scenes have so many sprites in them already that aren’t in prefabs (I don’t want to pollute my project folder with prefabs for one-off things like decorative sprites). So I still have no choice but to put my scenes in asset bundles?

Yes, this is the only requirement for now. Not saying it’s ideal.

I get it. It should work for your case too. Let us brainstorm a bit on this.

@ColossalPaul do you know anything about the issue raised by @fokziu above? Because if it’s true that we basically can’t have folder structure inside Asset Bundles and files have to be named uniquely (as in DOS 1.0) that we’d have deeper problems which would make this solution unusable for anything serious.

Please say it ain’t so :slight_smile:

@ColossalPaul there was even ticket created some time ago on this issue and there has been 0 response to this issue.

Here is the link: Unity Issue Tracker - [AssetBundle] Collision when building AssetBundles

Can you clarify on that? Or are we expecting something that this has not been designed for?

The asset bundle hash collision problem was a showstopper for me. Even if I could get the variants to work, the bundles wouldn’t build without renaming a ton of assets. I voted on the issue you linked @fokziu

Edit: Also agree with @bryantdrewjones about the prefabs. The need to include prefabs / scenes into bundles before we can use variants is a major pain point. Especially since, like I mentioned, variants are something you implement very late in production.

1 Like

The number 1 reason this solution doesn’t work, is that it’s a big unnecessary time-sink, not only creating, bootstrapping and loading the varients is a hassle, but maintaining them as things change, it all costs time. And it’s all a complete waste, when all you want is the ability to support low-end / older devices.

Bundle varients are an awesome feature, and help provide a solution for many advanced use cases. But they’re total overkill for this issue.

What we are asking for is simple:

  • A way to automatically load reduced-size textures on low-res devices, reducing our memory usage and preventing the apps from crashing. Just half-sizing textures, reduces memory usage by 75%, and is essential for running on older mobile devices.

This is really simple and basic feature. It’s really just two steps:

  1. When packing textures, smaller versions should be automatically created. (TexturePacker can do this. 2dToolkit can do this. Unity should do this.)
  2. When the app loads it’s 2d textures, it chooses the correct atlas for the current screen size / dpi.

This could be achieved by adding a simple list to the Build Settings:

This would give the app all the information needed to generate the correct atlases at build-time, and select the appropriate one at runtime. It would give us the ability to create multiple sizing steps, and to determine at which DPI those sizes are loaded. Yes, it would have the disadvantage of bloating the packaged file size, but that’s a pretty minor issue, and can be solved with AssetBundleVarients, which you’d probably already be using if build size is a big concern for your project.

8 Likes

Hi All,

The asset collision bug is a known issue. Our guy is on it. I will post here when we find a solution for this.

1 Like

I’ll leave my feedback here, as kind of a continuation of the original thread:Working Multi-Resolution Sprite Sheets - Unity Engine - Unity Discussions

I did manage to get it working originally. But in the end i found my own workaround for multiple textures and scraped using the bundles.( i have a few ideas for it in the future though)
At the time the way the api was presented seemed simple. But i never understood a few things.
Originally you guys said that asset bundles handle dependencies on their own, yehi!
Execpt, clearly they don’t, or the manager wouldn’t need a dependency loading segment…
Also it leaves me wondering about situations like, what if an asset is on bundle A and it depends on another something on bundle B, will the system know to do that through whatever is written in the manifest? will it load the whole bundle B or just what’s needed?

That leads to reflection number 2, when loading a bundle you load it to memory, then you load, say the scene… does that mean that for a while you are using 2x the memory, until the bundle is unloaded? or is it reading from the ‘loaded’ stuff.(because 2x memory consumption even if for a second would kill the purpose for reducing the memory cost on low-end)

Overall what the bundles really are and how they work was not really properly explain from my pov, leading a more critical dev uncertain over how to properly use it, or if to use it. That said…

I’m gonna borrow gskinner’s comment and say that this is a huge time sink, I’ve said this before and was ignored, but i know asset bundles are going to continue being bloat, until you guys do as follows:
They have to be a GUI solution, period. They are basically zip archives with pronto unity integration, why is it so hard to have them be managed via visual interface? why dont we have the ability to see at least thumbnails and descriptions of whats inside, after they are created? Check here:https://feedback.unity3d.com/suggestions/editor-display-asset-bundles-in
For a suggestion made long ago on the subject, i expanded on it.

All in all we should be able to create, control, and view them in the editor by clicking on stuff, and all of this should be integrated into the engine for maximum performance, not made into c# scripts. Unity already does this sort of thing with the new gui system, and we have ready-made modules and whatnot for most use cases.
If a low level-ish api is also going to be made explicit, that’s great also, and better in some cases.

But, as he pointed out, for most scenarios it really shouldn’t be.
2DToolkit, has a bunch of checks that you can set(visually, read: through the inspector), for ratios, resolutions, youNameIt, and when that checks a certain variant is loaded, or whatever is done. You guys could go even more indepth on that sort of thing, reaching the corner cases. Unity at times seems reluctant to build tooling for us, but this type of tooling is rather essential.


Now, this is my latest experience with the current assetManager package you guys leverage:
1)I open the project and get:
Assets/AssetBundleSample/Scripts/Editor/BuildResources.cs(3,19): error CS0234: The type or namespace name iOS' does not exist in the namespace UnityEditor’. Are you missing an assembly reference?
Assets/AssetBundleServer/AssetBundleServer.cs(3,24): error CS0234: The type or namespace name Tasks' does not exist in the namespace System.Threading’. Are you missing an assembly reference?

Originally i had the server script in there also, i deleted that, and deleted the BuildResources, which was only good for iOS anyways.

2)Not my first time using this, but i forgot i had to turn on simulation mode, and to me, the readme didn’t do a good job at telling me to. Then i got this:

Development Server URL could not be found.
UnityEngine.Debug:LogError(Object)
AssetBundles.AssetBundleManager:SetDevelopmentAssetBundleServer() (at Assets/AssetBundleManager/AssetBundleManager.cs:180)
LoadVariants:InitializeSourceURL() (at Assets/AssetBundleSample/Scripts/LoadVariants.cs:92)
c__IteratorB:MoveNext() (at Assets/AssetBundleSample/Scripts/LoadVariants.cs:121)

3)Later on i remembered, oh yeah simulation mode, so set that and now it worked, but i still had consistent issues:
Failed AssetBundleLoadAssetOperation on canvas from the AssetBundle banner.
UnityEngine.Debug:LogError(Object)
c__Iterator9:MoveNext() (at Assets/AssetBundleSample/Scripts/LoadTanks.cs:179)
UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator)
c__Iterator6:MoveNext() (at Assets/AssetBundleSample/Scripts/LoadTanks.cs:108)

There is no asset with name “canvas” in banner
UnityEngine.Debug:LogError(Object)
AssetBundles.AssetBundleManager:LoadAssetAsync(String, String, Type) (at Assets/AssetBundleManager/AssetBundleManager.cs:554)
c__Iterator9:MoveNext() (at Assets/AssetBundleSample/Scripts/LoadTanks.cs:176)
UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator)

Resource file has already been unloaded.


This came from the tank scene in particular.
Also, on the variants scene, i haven’t gotten the sd to load.
In my own script, back in the day, in the post i mentioned, it was very small and simple, based on what mike geig and others posted back in the day, everything just worked, and i got it to work based on any resolution i choose to filter from. So anything lower then X&Y rez. would load sd instead, all of that exposed in the inspector, perfect.

Which is why, if you guys want this to be a script based solution, its better to give us an outstanding documentation, with load of comments, pink poneys, and happy pokemons, explaning how to implement things in 10k diferent ways, than giving us a ready-made script.
That’s just my opinion though, i wasnt satisfied with the material that we had at the time, and had to do my own research to figure it out… time-sink.

So this manager that you guys made, it seems to work, i guess, i didn’t fully push it. It’s certainly a move in the right direction, and its better than leaving us alone with a feature that only exists for the devs who created them.
But, my official feedback remains in line with what gskinner, and frankly anyone, would say: we need a GUI solution, that is straight forward, essentially a no-brainer, something that hopefully even the dumbest art guy can handle, and that just works for most use cases in the end of the day.
Having the api is great for people that really need it.

I hope that along with the new cinema/director tools, and revamped 2d animation system that are coming, unity realizes, that coupling proper tooling with the editor is more essential to the engine’s success than services like cloud build or whatnot.

Good luck Paul, i know you are making the effort.

PS: also i have a question, now with the whole multi scene functionality, i saw you guys made a scene that had sub scenes in it, with certain relevant game objects that were organized and coupled together. Is this the recommended approach to scene building from now on? are there any performance penalties on using multi scenes, versus simply having your typical buncha objects in a single scene?
I also noticed, and then read in the docs, that now dontDestroyOnLoad creates its own, scene, but that using it is not recommended anymore…
In the case we do it the recommended way(wtih a manager scene), the docs state:
“Cross-scene references are not supported but also not prevented.” Isnt this a serious issue, that defeats the purpose of a multi-scene form factor? Would that lead to any problems for a manager being used in endless ways by scripts on other ‘scenes’? Maybe its better to stick with DDOnLoad, and a single scene setup after all?
Or maybe that comment is there to avoid something specific, and that reason is not made clear.

You guys should make a blog post on recommended usage and the possible pros and cons, performance evaluations, etc., of the new system.
It seems that unity hardly ever makes a point at further explaining these core features when they get implemented, and they are way more essential than “Updated webgl benchmarks” or most blog posts for that matter.

Thanks again.

1 Like

The HD/SD problem is something every mobile developer is going to have to deal with. I liked that Unity considered the case where assets will be downloaded and used, rather than assuming they’re built into the package. In that way, it makes sense the variant system should work well with Asset Bundles. And even better, I only have to download the SD assets for devices that are only going to display SD assets. But the problem with basing variants on Asset Bundles is that, now, any issues I may have with Asset Bundles are also now issues in the way of solving the HD/SD problem. Asset Bundles come with too much complexity and too many limitations/bugs/gotchas to solve a problem as common as the HD/SD problem. I like @deemen 's idea of somehow separating the variant system from asset bundles.

I also like that Unity’s variant system considered that I may want to swap assets based on a variety of conditions, not just resolution. But since the HD/SD problem is so common, it would be nice if they created a concrete implementation of resolution mapping that we can use out of the box, with a simple configuration interface like Android, iOS, 2D Toolkit, etc.

Even better would be if we only had to supply the HD asset and Unity would automatically scale the size down for the SD assets before building, so we don’t have to manage all the asset sizes. Too bad we can’t do that ourselves since there is no pre-build hook (https://feedback.unity3d.com/suggestions/pluggable-build-pipeline | https://feedback.unity3d.com/suggestions/editor-pre-build-script | https://feedback.unity3d.com/suggestions/attribute-for-running-custom-editor-code-before-build-begins)

5 Likes

Agreed. We should just have to supply the HD texture, and have Unity automatically create SD textures for us, with the ability to set dpi mappings & scale factors for each device, in the build settings.

Variant bundles are great, but supporting downscaled textures should be a basic feature implemented out of the box.

4 Likes

This is the real answer. Make a feature of texture a checkbox to indicate it has variants. Let the variants be a custom list of resolutions you prefer, with some sane defaults to choose and add, or a project setting where you tick 1x, 2x, any number of custom scalings, and your default textures become the largest variant. The asset bundle system above makes me want to retreat back to writing server code, because it seems so much less complex. Imagine what an artist thinks of it!

I think the system should take some cues from Apple (automatically recognise @2x files as variants of the same name without @2x), but also generate those when missing (and multi-resolution support is enabled). We’re starting to get to the point where mobile isn’t the only place where we can benefit from different resolution art assets.

5 Likes

Unity Staff should download 2dtoolkit and see how they do it, from a user interface perspective it’s exactly what you’re describing. It’s clear and flexible. It has other issues, but the way collections are created is basically exactly right.

This is a basic requirement of multiplatform 2d game development, it should not be something we have roll on our own or hack together using asset bundles and post processing scripts.

2 Likes

I’ll echo the previous sentiments, it seemed overly complex to just use different resolution textures. It also seems to have too many limitations.

An example of this is that the variant architectures need to be exactly the same, even in size. This doesn’t appear to be a problem when using Unity’s Sprite Packer, but if you use another program to pack your assets (such as TexturePacker), it doesn’t work. For example, sprite 1 in HD atlas would have a rect of [0,0,100,100], in the SD atlas it would be [0,0,50,50]. But when the variant loader switches to the SD, it seems to use the slicing information from the HD bundle ([0,0,100,100]), and not the from the SD bundle.

So, at least when using TexturePacker to pack you atlases (which is much better than Sprite Packer in my opinion), you can’t have different sized variants, which kinda defeats the point of it really. In the end, we have been forced to use same sized sprite sheets for both SD and HD, but just have the SD sprites compressed more than the HD sprites, which is frustrating as it has all the information there to use different sized atlases.