Search Unity

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

Discussion in '2D' started by ColossalPaul, Dec 23, 2015.

  1. ColossalPaul

    ColossalPaul

    Unity Technologies

    Joined:
    May 1, 2013
    Posts:
    174
    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.
     
  2. bryantdrewjones

    bryantdrewjones

    Joined:
    Aug 29, 2011
    Posts:
    147
    Thanks for kicking off this thread, @ColossalPaul :)

    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 :eek: ).

    I've tried the AssetBundleManager from BitBucket, but, for us, it's not the best solution. Here's why:
    1. 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.
    2. 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?).
    3. 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?
    4. 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.
    5. 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.
    6. 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 :)
    7. 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?
    8. 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...).
    9. 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 :( 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 :) I'll add more feedback as it comes to mind, but these are my most immediate concerns :)

    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 :D
     
  3. Deleted User

    Deleted User

    Guest

    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.
     
    ZeFirestarter and theANMATOR2b like this.
  4. deemen

    deemen

    Joined:
    Dec 29, 2013
    Posts:
    17
    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:
    1. 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.

    2. 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.
     
  5. bryantdrewjones

    bryantdrewjones

    Joined:
    Aug 29, 2011
    Posts:
    147
    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 :oops:

    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 :(
     
  6. fokziu

    fokziu

    Joined:
    Apr 10, 2015
    Posts:
    7
    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.
     
  7. ColossalPaul

    ColossalPaul

    Unity Technologies

    Joined:
    May 1, 2013
    Posts:
    174
    @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.
     

    Attached Files:

    ZeFirestarter likes this.
  8. bryantdrewjones

    bryantdrewjones

    Joined:
    Aug 29, 2011
    Posts:
    147
    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 :( 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?
     
  9. ColossalPaul

    ColossalPaul

    Unity Technologies

    Joined:
    May 1, 2013
    Posts:
    174
    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.
     
  10. DarekRusin

    DarekRusin

    Joined:
    Nov 15, 2013
    Posts:
    47
    @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 :)
     
  11. fokziu

    fokziu

    Joined:
    Apr 10, 2015
    Posts:
    7
  12. deemen

    deemen

    Joined:
    Dec 29, 2013
    Posts:
    17
    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.
     
    DarekRusin likes this.
  13. gskinner

    gskinner

    Joined:
    Aug 28, 2014
    Posts:
    43
    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.
     
    Last edited: Jan 8, 2016
    LilGames, chrismarch, NeilW and 5 others like this.
  14. ColossalPaul

    ColossalPaul

    Unity Technologies

    Joined:
    May 1, 2013
    Posts:
    174
    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.
     
    Last edited: Jan 5, 2016
    DarekRusin likes this.
  15. Kiori

    Kiori

    Joined:
    Jun 25, 2014
    Posts:
    161
    I'll leave my feedback here, as kind of a continuation of the original thread:http://forum.unity3d.com/threads/working-multi-resolution-sprite-sheets.274683/

    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)
    <Initialize>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)
    <InstantiateGameObjectAsync>c__Iterator9:MoveNext() (at Assets/AssetBundleSample/Scripts/LoadTanks.cs:179)
    UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator)
    <BeginExample>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)
    <InstantiateGameObjectAsync>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.
     
    bryantdrewjones likes this.
  16. mdrotar

    mdrotar

    Joined:
    Aug 26, 2013
    Posts:
    377
    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/sugges...unning-custom-editor-code-before-build-begins)
     
  17. gskinner

    gskinner

    Joined:
    Aug 28, 2014
    Posts:
    43
    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.
     
  18. orb

    orb

    Joined:
    Nov 24, 2010
    Posts:
    3,037
    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.
     
  19. 39thstreet

    39thstreet

    Joined:
    Jan 30, 2012
    Posts:
    104
    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.
     
    shaderop and Kiori like this.
  20. SimteractiveDev

    SimteractiveDev

    Joined:
    Jul 9, 2014
    Posts:
    97
    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.
     
  21. ColossalPaul

    ColossalPaul

    Unity Technologies

    Joined:
    May 1, 2013
    Posts:
    174
    FYI, I'm reading this whenever there's a new reply. So keep it coming.

    As a quick update. I'm hard at work prototyping a solution that does not require Asset Bundle. Not sure if it will make it in the end, but it is worth knowing all the challenges.

    Stay tuned for more info.
     
  22. fokziu

    fokziu

    Joined:
    Apr 10, 2015
    Posts:
    7
    If thats the case I will, instead of pouring another bucket of my grief at unity, try to hint what we did while we were still developing our in-house engine for 2d development - maybe it will shed some light and influence you to come up with better ideas.

    In terms of HD/SD variants its _not_ the best solution as some people are describing to have only @2x @3x variants - also guys, really I know UnityEditor is appealing but having to plug something in editor everywhere you need fallback variants for lower-end devices is not the most productive way to go. It works in case of Apple as they have very specific hardware with very specific resolutions but in terms of Android there is much higher variety of resolutions and stuff gets slightly more complicated.

    What we did have was something similar to virtual filesystem for assets that was arranged in a chain-of-command way to handle loading (not only) sprites. The game should look for assets and it was trying to get a particular asset from first source, if it didn't find it, there was another asset source in chain of command that was tested against existance of a given asset.

    This worked fine, on low end devices we mounted lowres data source (it could be anything starting from some .zip package, or regular directory) on top of common data. So anything that had to be downgraded in resolution for lowres version could be put there. The same could go with localizations. You prepare very thing storage that has lang specific overrides and plug it in with top priority. So maybe the sane way would be to actually let us create 'storages' (like the Resources folder) that would have special meaning and apply order to them or mark what should get in what build flavor. While development it would be as simple as directory on disk, and in build - well you can do whatever you like to do it. Bundle it in some kind of internal pack storages or whatnot.

    There was no 'asset@2x' 'asset.ru' or anything like that. There was always asset. In most cases that was enough.

    I believe this was something variants tried to solve yet they seem somewhat complicated to use and are lacking in terms of usability (the name collision issue I raised).

    Also in terms of asset resolution - it should be handled automaticaly by Unity because in majority of cases we really don't need to have different texture in lowres and different in highres. Most of the time Its all about density and sizes in terms of diskspace and memory space on low end devices.

    What we had was something like Atlas Packer in unity that gathered all sprites that met special requirements (in Unity there is only packing tag and it what is worse it doesn't work at all with sprites in Resources folder) but we did it somewhat different. We defined packing scripts that created groups of sprites that should be packed together defining also scale from the source assets. Therefore we could have default packing rules that said "make bundle X using this packing rules that takes source asset and scales them down by a factor of for example 0.8". Another package would be build using another rule set etc. You could also mix stuff defining one Ruleset that had higher-resolution GUI stuff (because you don't want to downscale that much) and lower scale non relevant background stuff.

    Finally we ended up with packages that could be bundled together with one build or split in variants. On iPad it was most often one app with bundled two packages (HD/SD) but on Android we did a 3-way split and each apk had its own obb with required assets.
     
  23. Kiori

    Kiori

    Joined:
    Jun 25, 2014
    Posts:
    161
    @ColossalPaul
    Whatever you do please don't forget about asset bundles, we barely have data containers as it is.
    Scriptable objects pass by as such, but are really just classes. Wanna save something? you have to roll out your own solution as there is no standard .uSave holder data holder. Asset bundles really are great and fill in a huge gap to allow us have different packs as a whole.

    The thing is, currently they are like the old gui, and they need to be like the new uGUI. If for instance they leveraged the eventSystems currently in pace, you could have built-in modules to handle: at start, when resolution/dpi X happens, do this 'event'; For people that bundle variants together, and other cases that might pop up.(like 2dtk already does...)
    Just a minor example.

    The whole system right now is just too focused on online usage(look at the assetManager you guys provide), granted loading a bundle that is in the StreamingAssets folder is simple, but what else does it have to offer?

    I also talked about how it would be great if we could visualize(thumbnails to the rescue), and even link assetbundle content without loading it. Imagine working with artists in the long distance, this type of feature would be very handy.

    I personally would like to type: bundleSystems -> the bundles are in that folder, with subfolders - get me scene or sprite X, and it would do the job of looking for it, getting dependencies, etc on its own. And perhaps this needs editor/GUI support, but maybe that's a tad much.
    One of the things that make gameObjects great is you can drag and drop them anywhere, what can you do with bundles?

    If you add the other comments people made, there are a few hints as to how we need the system to improve.

    Bottom line is bundles are not ready, they need GUI/Editor support and an offline focus, this may require a re-design, which it seems to me is being avoided.
    Everything that was said by the others can be added as an extra feature of the asset bundle system, this way we keep/gain the ability to reliably use a package system that just works, for designers, artists -and programmers.

    Best of luck Paul.
     
  24. DarekRusin

    DarekRusin

    Joined:
    Nov 15, 2013
    Posts:
    47
    @ColossalPaul wow, I've just noticed that the name collisions in asset bundles (a.k.a. "no support for folders") is fixed in 5.4. Good news and thanks for having this handled, Paul!

    But is there a chance of this fix making it to branch 5.3? I'm wondering since so far our move from internal tech to Unity is mainly filled with regrets and working around bugs and issues. The whole 5.2 branch was unusable because of performance regressions on iOS. 5.3 started the same (performance regressions on newer Androids) but 5.3.1 is starting starting to look like maybe finally there could be some potential in there. But I'm afraid 5.4 will bring its own bag of hairy issues and the sad story will start again.

    So any chance of making 5.3 a stable, production ready branch and including this fix in it too? :)
     
  25. 99thmonkey

    99thmonkey

    Joined:
    Aug 10, 2012
    Posts:
    525
    @ColossalPaul For me personally I need a better example. For instance, if there was a current Unity Project that incorporated the use of AssetBundles. I'm having a very hard time wrapping my head around how to use this. My thought is that it would be nice to have specific models for certain devices and then use other models for other devices. Maybe I have a multiplayer game where everyone is in the same scene but people on the PC can select fantastic (Highest quality meshes and textures), Good (Highest quality meshes and low quality textures), Fast (Average quality meshes and low quality textures), but iOS or Android would have maybe StylizedLowPoly (like flat sided), Fast (Low poly, low res textures), Good(low poly, higher res textures), Fantastic (probably crash - average quality with high res textures).

    I'm just not grasping how to do this. I think this is what AssetBundles are for, but alas I need a better example. I also don't understand how I can have a Holiday version versus a regular version without having a full updated game. Same with allowing for multiple weapon textures or character textures (for same models).
     
    theANMATOR2b likes this.
  26. Kiori

    Kiori

    Joined:
    Jun 25, 2014
    Posts:
    161
    Back in the day Paul told me that the recommended way was to put the bundles in the StreamingAssets folder. Its as if they were downloaded, but they are always there(this folder works similarly to the Resources folder, in the sense that you have to create it).

    MY suggestion based on experience is that you divide the bundles by texture and mesh, for instance, low, mid, high, textures, and the same with meshes, then you can combine them on load as you wish. That should give you an idea to start.

    Check these entries:http://docs.unity3d.com/Manual/AssetBundlesIntro.html
    http://docs.unity3d.com/Manual/LoadingAssetBundles.html
    http://docs.unity3d.com/Manual/AssetBundleInternalStructure.html
    There is lots of stuff in that part of the manual.

    google turn up this video:

    Havent fully analyzed it though, but it seems ok.

    Basically,with the files locally,i think you just gotta hand it over to a variable, assetbundle bundle=wheretheyare
    Then call the bundle.whatyouwant functions/methods.

    That said, we do need more in depth tutorials focused on offline use, as I stated earlier.

    Hope this gets you started, if you got other questions feel free to pm me, i don't know it all yet, but i do have some experience with it.

    I'm gonna try to set something up for my own use later. The other system i had was based on earlier tutorials, which later i realized were fully focused on downloading form a web server...
    (I think the only surviving resource is here:https://unity3d.com/pt/learn/tutorials/topics/scripting/assetbundles-and-assetbundle-manager)

    Best of luck.
     
    DarekRusin and theANMATOR2b like this.
  27. ColossalPaul

    ColossalPaul

    Unity Technologies

    Joined:
    May 1, 2013
    Posts:
    174
    I'm not sure it's the same thing. The collisions is between variants. AFAIK, it is still a known issue.
     
  28. Kiori

    Kiori

    Joined:
    Jun 25, 2014
    Posts:
    161
    @ColossalPaul
    I was testing a few ideas on how to handle local asset bundles, and as far as I could muster the only way to use/open bundles is by using the WWW class with LoadFromCacheOrDownload.
    But that brings the question:
    If the bundles are already in the StreamingAssets folder, are they going to be cached somewhere, or will they simply be opened?
    So, does StreamingAssets count as a cache?

    I tried doing it without WWW, nothing worked.
     
  29. Miguel-Ferreira

    Miguel-Ferreira

    Joined:
    May 8, 2015
    Posts:
    90
    Any news about the asset bundle variant hash collision? Is there any workaround that we can apply while we wait for the official fix?

    I'm using Unity 5.3.1p4 and I'm having hash collision problems on a sd variant
     
    Last edited: Jan 27, 2016
  30. andsee

    andsee

    Joined:
    Mar 20, 2012
    Posts:
    88
    Asset bundles are great for more complex use cases however for our apps we have always ensured that textures are sufficient for high resolution devices and for the lower resolution devices a half size texture is fine and would be happy for this to occur across all textures. Note that this has no effect on ui size or layout which is dealt wth separately by many systems. Instead we are just interested in the number of texels needed to populate the physical screen's pixels.

    We do not wish to ever create or see half size textures, they need to be managed automatically, when an artist edits a texture they only wish to create / edit one.

    For our current apps we make use of mipmaps to achieve this, which actually results in a good interpolation between hd and sd (and lower should you decide to scale graphics).

    Mipmaps actually appear to work well, in that for low end devices we set unity's quality settings to half size textures and it skips loading of the high resolution mipmap, (Although the profiler lies about how much memory is used showing the full size, but testing on hardware shows it's not really used)

    Fortunately Unity's sprite packing allows you to setup padding and as long as you pad your sprites by 4 or 8 pixels you get no interference. Ideally the packer would allow you to specify a common divisor (see Texture Packer Pro)

    Now when we came to create a tvOS build we could not have the HD assets in the build, this was a real pain because I had to go through every texture source file and halve it's size, after that the game worked on tvOS with no bundles required. Now I have to maintain two branches of the game, one with half size assets and one with full / mip maps.

    If Unity looked at the Quality settings at build time and noticed that they were all set to halve texture size it would be great if it took this into account and stripped the larger textures from the build.

    Now for those who do not wish to use mipmaps (many think they are just for 3d) and hence save the space taken by the even smaller levels it would be nice if unity simply stored two resolutions (or n) for every texture in the build. Then when loading looked at the quality setting to work out which one should be loaded. Obviously there's already some nice magic in there coping with reporting the original HD size back to the game so that sprites and UI do not change physical size.

    All in all there should be a simple way to reduce build size or allow switching texture resolution with a couple of tick boxes.

    If you were to take it further it would be great to see some of the settings exposed on a per texture / sprite atlas level, perhaps just a check box saying it's size can be halved. In engines I've written in days gone past every texture could specify rules as to how it's size changed depending on the vram available, the majority of code referenced the texture with UV's and the original texture's size. (Only when creating copies of textures etc did we need to know the actual texture size).

    For more complex use cases people can fall back to bundles, or even use both systems but I'm sure for a huge percentage of people this whole thing can be automated completely!
     
  31. Miguel-Ferreira

    Miguel-Ferreira

    Joined:
    May 8, 2015
    Posts:
    90
    I'm dealing with the automatic SD variant creation by using this script

    Code (CSharp):
    1. public class AssetBundleTextureSDVariantGenerator : MonoBehaviour {
    2.  
    3.         [MenuItem("Tools/Asset Bundles/Create sd variant")]
    4.         public static void CreateSDVariant() {
    5.  
    6.             CreateFolderSDVariant ("Assets/vitor/Textures/Catalog");
    7.             CreateFolderSDVariant ("Assets/vitor/Textures/Planet");
    8.             CreateFolderSDVariant ("Assets/vitor/Textures/Shared");
    9.             CreateFolderSDVariant ("Assets/vitor/Textures/Surprisery");
    10.             CreateFolderSDVariant ("Assets/vitor/Textures/Surprise Machine");
    11.  
    12.             AssetDatabase.Refresh (ImportAssetOptions.ForceUpdate | ImportAssetOptions.ImportRecursive);
    13.         }
    14.  
    15.         private static void CreateFolderSDVariant(string folderPath) {
    16.  
    17.             AssetImporter assetImporter = AssetImporter.GetAtPath (folderPath);
    18.  
    19.             assetImporter.assetBundleVariant = "hd";
    20.  
    21.             EditorUtility.SetDirty (assetImporter);
    22.  
    23.             string assetBundleName = assetImporter.assetBundleName;
    24.             string variantFolderPath = folderPath + "_sd";
    25.  
    26.             AssetDatabase.DeleteAsset (variantFolderPath);
    27.             AssetDatabase.CopyAsset (folderPath, variantFolderPath);
    28.  
    29.             AssetImporter duplicatedAssetImporter = AssetImporter.GetAtPath (variantFolderPath);
    30.             duplicatedAssetImporter.assetBundleName = assetBundleName;
    31.             duplicatedAssetImporter.assetBundleVariant = "sd";
    32.  
    33.             var appAssetsRootPath = Application.dataPath.Substring (0, Application.dataPath.Length - 6);
    34.             var variantFolderFullPath = appAssetsRootPath + variantFolderPath;
    35.             string[] pngFullPaths = Directory.GetFiles (variantFolderFullPath, "*.png", SearchOption.AllDirectories);
    36.  
    37.             foreach (string pngFullPath in pngFullPaths) {
    38.  
    39.                 var pngAssetRelativePath = pngFullPath.Replace (appAssetsRootPath, "");
    40.  
    41.                 TextureImporter pngAssetImporter = AssetImporter.GetAtPath (pngAssetRelativePath) as TextureImporter;
    42.  
    43.                 if (pngAssetImporter.textureType != TextureImporterType.Sprite)
    44.                     continue;
    45.  
    46.  
    47.                 //Resize texture to half size
    48.  
    49.                 Texture2D tex = new Texture2D(4, 4);
    50.                 tex.LoadImage(File.ReadAllBytes(pngFullPath));
    51.  
    52.                 var halfWidth = tex.width / 2;
    53.                 var halfHeight = tex.height / 2;
    54.  
    55.                 if (halfWidth == 0 || halfHeight == 0) {
    56.                     continue;
    57.                 }
    58.  
    59.                 TextureScale.Bilinear (tex, halfWidth, halfHeight);
    60.                 File.WriteAllBytes(pngFullPath,tex.EncodeToPNG ());
    61.  
    62.                 string spritePackingTag = pngAssetImporter.spritePackingTag;
    63.                 if (spritePackingTag != "") {
    64.                     string newSpritePackingTag = spritePackingTag + "_sd";
    65.                     pngAssetImporter.spritePackingTag = newSpritePackingTag;
    66.                 }
    67.  
    68.  
    69.                 float spritePixelsPerUnit = pngAssetImporter.spritePixelsPerUnit;
    70.                 float newSpritePixelsPerUnity = spritePixelsPerUnit / 2.0f;
    71.                 pngAssetImporter.spritePixelsPerUnit = newSpritePixelsPerUnity;
    72.  
    73.  
    74.                 int maxSize = pngAssetImporter.maxTextureSize;
    75.                 int newMaxSize = maxSize / 2;
    76.                 pngAssetImporter.maxTextureSize = newMaxSize;
    77.  
    78.                 Vector4spriteBorder=pngAssetImporter.spriteBorder;
    79.                 //X=left,Y=bottom,Z=right,W=top.
    80.                 spriteBorder.x=Mathf.Floor(spriteBorder.x/2.0f);
    81.                 spriteBorder.y=Mathf.Floor(spriteBorder.y/2.0f);
    82.                 spriteBorder.z=Mathf.Floor(spriteBorder.z/2.0f);
    83.                 spriteBorder.w=Mathf.Floor(spriteBorder.w/2.0f);
    84.                 pngAssetImporter.spriteBorder=spriteBorder;
    85.  
    86.                 EditorUtility.SetDirty (pngAssetImporter);
    87.             }
    88.  
    89.             EditorUtility.SetDirty (duplicatedAssetImporter);
    90.         }
    91.     }
    that is being called in Unity Cloud Build's Pre Export method.

    Not only this ensures that the SD png's are always in sync with the HD ones, it also prevent us from having to have all of the sd images on our repo, saving space and time.
     
    Last edited: Feb 25, 2016
  32. Miguel-Ferreira

    Miguel-Ferreira

    Joined:
    May 8, 2015
    Posts:
    90
    Also, I've noticed that Unity 5.3.2p1 fixes the following issue:
    • (716166) - AssetBundle: Fixed the hash collision when building AssetBundles.
    I've downloaded it but the HD/SD collision still happens. So I'm assuming that the variant collision is a different bug. Does anyone know its bug id?
     
    Last edited: Jan 29, 2016
  33. TobyKaos

    TobyKaos

    Joined:
    Mar 4, 2015
    Posts:
    214
    Hello,

    When I started my game in march 2015 I have write a HD/SD texture loader. My loader need to be feed by a manifest file that I preprocessed with a simple unity script.
    I used Texture Packer from codeandweb to generate Atlas. Then my script read in Texture Packer config files and look at unity Resources folders. Then in runtime I have a function GetSprite(string name) that return the sprite in the good variant.

    This was simple but not well integrated to unity. Then I have decided to use assetbundle variant with unity Sprite Packer. this allow me to create asset bundle that I can download at runtime and then save a lot of memory space (great).
    Indeed we need prefab to works, then I have an empty scene I called bootstrap and another scene that is an assetbundle. The scene is included in an asset bundle in the StreamingAssets folder. That works for you to @bryantdrewjones

    In a nutshell:
    . 2 folders variants (or more) with asset bundle and variant assigned
    . all your prefab that need to be instanciated need to be in an assetbundle (named prefabs in my project)
    . a unity scene that is in an unique assetbundle (all your scene that need variant must be in asset bundle) I have a scene principal in asset bundle called principal
    . a bootstrap scene to load principal asset bundle and other asset bundle that must be in the StreamingAssets folder
    . load the good assetbundle variant

    With this simple system I can load local asset bundle variant for my UI and load additionnal asset bundle variant from server.

    But it is right that sometimes it is not easy to test (must create asset bundle, start from bootstrap and check in the profiler that sometimes have in memory different variant ...) not easy. And we must take care of folder structure for each variant(but it is true for my previous way to do).

    I have added in my ResourcesManager a public properties to force load HD or SD variant when I want to test (very usefull).

    Now the last things I wait it is a fix with Atlas packing and ETC1 + alpha support that does not work.
     
  34. ColossalPaul

    ColossalPaul

    Unity Technologies

    Joined:
    May 1, 2013
    Posts:
    174
    What is wrong with this? Please provide more details! Thanks.
     
  35. ColossalPaul

    ColossalPaul

    Unity Technologies

    Joined:
    May 1, 2013
    Posts:
    174
    We are prototyping how this can be done. But thanks for the feedback.
     
  36. TobyKaos

    TobyKaos

    Joined:
    Mar 4, 2015
    Posts:
    214
    @ColossalPaul there are an issue with Sprite Packer and ETC1 + Alpha but it is not related to Asset Bundle.
     
  37. Miguel-Ferreira

    Miguel-Ferreira

    Joined:
    May 8, 2015
    Posts:
    90
    @ColossalPaul Do you know what is the id for the SD/HD variant asset bundle collision bug? I'm still having it in Unity 5.3.2p4

    EDIT

    I finally found where the problem was for the hash collision. I had a folder with a given asset bundle name and variante and inside of it I had a texture with the same name/variant. Only the folder should've had the asset bundle name/variant and not the texture itself.

    So, yeah, no problems with asset bundle collisions anymore!
     
    Last edited: Feb 24, 2016
  38. mml

    mml

    Joined:
    Mar 29, 2015
    Posts:
    11
    @ColossalPaul
    I just started looking at using AssetBundle Variations for a new mobile project. Mostly using SpriteRenderers, so I need to swap sprites of different resolutions and I definitly need the functionality to map AssetBundle Variants to iOS App Slicing.
    After some research and trials I found this post, which strengthens my feeling that the whole system is overly complicated to setup. So I'm wondering what the status of your refactoring of the Variant system is. Are you working on a more streamlined process for this specific purpose and if yes do you have an ETA?
     
  39. ColossalPaul

    ColossalPaul

    Unity Technologies

    Joined:
    May 1, 2013
    Posts:
    174
    Yes we are working on a prototype. But we need to make it sure it is technically viable. More time is needed but we are definitely addressing this. We will have more info on when you will be able to see this in the 2D Preview builds soon. Stay tuned.
     
    pep_dj, orb and 39thstreet like this.
  40. 39thstreet

    39thstreet

    Joined:
    Jan 30, 2012
    Posts:
    104
    Looking forward to it! Currently kicking off a new project and have to make the decision over whether we can finally use Unity 2d or stick with the asset store plugins we've been using (2dtoolkit). Without a way to swap 2d assets based on platform *easily* it's kind of a non-starter.
     
    orb likes this.
  41. mml

    mml

    Joined:
    Mar 29, 2015
    Posts:
    11
    Thanks for the info! I did get it working with the current system, but it's tedious and slow, so definitly looking forward if you guys can improve it.
     
  42. justdizzy

    justdizzy

    Joined:
    Mar 8, 2016
    Posts:
    89
    Hey all, I am still working my way though this, but I was wondering about the custom entry options in the Variant Map in Player Settings. I could not find any information about how to use them, so what I would like is to have a minimum true pixel size to use the HD variant (say 1024x1024) and everything else use the SD variant. This way the iPhone 6+ and all retina iPads would use HD, and other iPhones and the iPad 2 would use SD. Can this be done with several custom entry options?
     
  43. justdizzy

    justdizzy

    Joined:
    Mar 8, 2016
    Posts:
    89
    A follow up question, once I have my SD and HD asset bundles, if I want to include them in the app in StreamingAssets so that they are downloaded with the app, how to I tag in Xcode which one is for which device, or is that taken care of for me by adding the variant maps under player settings?
     
  44. justdizzy

    justdizzy

    Joined:
    Mar 8, 2016
    Posts:
    89
    I think I have an answer to my follow up question, which I will put here for anyone else thats trying to do the same (or if I forget). My goals are (A) to generate variant bundles so lower resolution devices use the scaled down assets (see #31), and (B) take advantage of iOS 9 app slicing by only including the variant bundle for that specific device.

    Once the variant map is setup in player settings and Resources BindVariant setup wherever you choose to do that, building in Unity creates a UnityData.xcassets file in Xcode. Prior this building, make sure to put your variant bundles in the Assets/StreamingAssets/ folder so that they are copied over properly to the Xcode project.

    In Xcode, expand the path to your variant bundles (for me its Data/RAW/AssetBundles/iOS), then select the UnityData.xcassets (not in that folder) and drag your asset bundles to the corresponding file drop spot (for me sprites.sd goes to Universal-Any/Any and sprites.hd goes to iPad-1GB/Any), you can right-click on the xcassets file to "Show In Finder" to verify that the bundles were copied over. This step is what makes the provided bundle load when called with:
    Code (CSharp):
    1.             assetBundle = AssetBundle.LoadFromFile("res://sprites");
    Now delete the source bundles from their folder (Data/RAW/AssetBundles/iOS), other wise they will still get copied in to the IPA, defeating goal B. Once you build in Xcode you can open the product to verify that neither bundle is in the Data... folder, instead at the root is an "Assets.car" file, which will contain the bundles that are required for the build device.


    DISCLAIMER: I've only barely tested this so I admit that there might be some issues. Please post if you find any or a better way.
     
  45. SimteractiveDev

    SimteractiveDev

    Joined:
    Jul 9, 2014
    Posts:
    97
    Is there any progress being made on improving AssetBundle system? Even just supporting simulate mode for variants would be a real time saver.

    Currently with variants, to test any change to an asset in a bundle, you need to build the assets for the target platform, then build the assets for the platform the editor is in (which forces a reimport of all assets to the editor platform and reimporting all assets again to the target platform once the bundles are finished). For large projects, you can be staring at a loading bar for up to a hour.
     
  46. pep_dj

    pep_dj

    Joined:
    Nov 7, 2014
    Posts:
    179
    2D experimental preview is released... any news about this issue?
     
  47. pep_dj

    pep_dj

    Joined:
    Nov 7, 2014
    Posts:
    179
  48. justdizzy

    justdizzy

    Joined:
    Mar 8, 2016
    Posts:
    89
    I strongly suggest running the Asset Server, even just on your local machine if you are a single dev. For me, switching between iOS and Android is faster by 10 fold since I started it. As a note, since it caches the imported assets, it will take a switch to each platform to start that cache, but then subsequent switches are faster.
     
  49. SimteractiveDev

    SimteractiveDev

    Joined:
    Jul 9, 2014
    Posts:
    97
    Hey, can you elaborate on this more? Do you mean Local AssetBundle Server, as we area already using that. Thanks.
     
  50. justdizzy

    justdizzy

    Joined:
    Mar 8, 2016
    Posts:
    89