Search Unity

Unity 4.5 Sprite Packer does not pack images inside Resources folder

Discussion in 'Editor & General Support' started by iPicnic, May 27, 2014.

  1. iPicnic

    iPicnic

    Joined:
    Apr 8, 2014
    Posts:
    6
    Hi!

    I'm trying to use the new Sprite Packer tool, but it doesn't work if I put the imagens inside Resouces folder, but inside any other folder it works.

    is it a bug?
     
  2. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    7,338
    It's pretty sensible. The main reason to use Sprite Packer is to save space in your build. If your textures are in the Resources folder, they will always be included in the build no matter what. So, why waste space in the texture atlas storing them twice?
     
    zombiegorilla likes this.
  3. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,225
    It's not a bug, it's intentional.

    --Eric
     
  4. iPicnic

    iPicnic

    Joined:
    Apr 8, 2014
    Posts:
    6
    Thanks Man!

    So, where does Unity put the texture atlas? is it inside Resources folder?

    Can I get this textures in run time?

    if you can answer that, I thank you.
     
  5. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    7,338
    I don't know where it stores the atlas texture (probably in the Library somewhere?), but it's intended to be abstracted away so that you never actually need the atlas texture. e.g., dragging a sprite into the game area will use the packed atlas texture seamlessly.

    Do you have a reason to need the atlas specifically?
     
    renman3000 likes this.
  6. iPicnic

    iPicnic

    Joined:
    Apr 8, 2014
    Posts:
    6
    I have sprite animations. So my sprite must have the same size for each frame, but I have different animations with different frame sizes in the scene. I created one multiple sprite for every animation. So I have 3 or more multiple sprites. it creates more drawcalls.
    I want to make one atlas with all sprites, so I tried to use Sprite Packer to make it.
    I really need it to be in Resources folder because I can't set the sprites in the Animation clip. I'm using AssetBundle to manage resources.

    But I think what I want is not possible, so I'll leave it as it is.

    But now I don't know why i'll use Sprite Packer if I can't load it inside resources. And I think that sprites in other folders are also included in the build.
     
    Last edited: May 27, 2014
  7. andsee

    andsee

    Joined:
    Mar 20, 2012
    Posts:
    88
    It seems overly restrictive though. I want to dynamically load and unload sprites for use in a specific scene which is image heavy and should not have them all loaded at once. The sprites need to be packed onto atlases for common reasons:

    - Draw Call reduction (packing sprites reduces the number of textures and hence draw calls used in a scene)
    - Memory (If you have several NPOT textures packing them into a power of two atlas allows texture compression)
    - Abstract link to atlas (code only references sprites which can change which atlas they are on)

    Obviously we don't want the sprite texture it's self stored in the build though, just the resulting atlas and 'sprite definition'.

    I had hoped that by adding the sprites to the resources folder the relevant atlas textures would be created and when a sprite was loaded from the resources folder it would ensure the relevant atlas texture was loaded and return the sprite. Release all sprites on an atlas and the atlas texture would be unloaded.

    So it seems that I will have to use an external sprite packer and import the atlas it's self into the resources directory. This is not ideal as the code then has to know which atlas to load and the best feature of Unity's sprites is that it abstracts away which atlas texture is used by a sprite allowing you to move sprites between atlases and the game to continue to run unchanged.

    Hopefully at some point Unity will add support for packing textures in the resources directory or a work around will be discovered.
     
    YerasiReddy, mangax, Zinov and 3 others like this.
  8. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    Packing sprites that are in the resource folder makes no sense, because they would end up being two times in the final build. Everything from the resource folder is part of the final build and most likely you use the texture atlas as well.

    Edit: Dumb post, please don't read...
     
    Last edited: Aug 21, 2014
  9. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    7,338
    Here's my understanding of the way the sprite packer works: when it packs the sprites into atlases, it creates a specialized 2-D mesh whose UVs reference the atlas. When you drag a Sprite into a SpriteRenderer component, in the editor it contains references to both the original image (since the images are still present even when the packer has not yet been run) and to the atlas; when you build the player, it strips out the references to the original image, leaving only the atlas references and saving space.

    I don't see how being in Resources changes this. When you have an object of type Sprite, it contains a special mesh and a reference to an image, and whether that image is an atlas or a standalone image has little to no impact on a SpriteRenderer. The Resources folder would simply contain the mesh part of the sprite data; it just now refers to the atlas, and the raw image is stripped from the build, just like when there's a direct reference to it. When I call Resources.Load<Sprite>("foo"), it should give me a sprite that has a mesh and references the atlas.

    At least that's how it should work...
     
    Dantus likes this.
  10. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    You can get the texture at runtime:
    http://docs.unity3d.com/ScriptReference/Sprite-texture.html

    To display the frame correctly, you also need to know where on the atlas the sprite is:
    http://docs.unity3d.com/ScriptReference/Sprite-textureRect.html

    Could you explain what exactly you are doing? How do you use asset bundles? Are all the sprites in the asset bundle or are they in the resources folder?
     
    ow3n likes this.
  11. andsee

    andsee

    Joined:
    Mar 20, 2012
    Posts:
    88
    Exactly how I see it too. I can see however why it may be misleading and people may expect the sprite texture to also be in the build but I would only expect that if the texture type was not set to sprite or the sprite was not packed. As far as the actual texture data goes it would effectively in the build but in the packed atlas texture, there is no reason I can think of why it would appear twice. As StarManta puts it above loading the sprite from resources would return the sprite referencing the atlas texture.
     
  12. TimK_personal

    TimK_personal

    Joined:
    Jul 30, 2014
    Posts:
    18
    In hindsight, that makes sense, but it's not super obvious. I was going nuts trying to figure this out before I found this thread. It really ought to say something about this at http://docs.unity3d.com/Manual/SpritePacker.html
     
    almo and Starya like this.
  13. maltadirk

    maltadirk

    Joined:
    Mar 12, 2014
    Posts:
    43
    Cool post. Just one thing wanna get my head around. So I'm creating a system that would load either SD sprites or HD sprites, depending on the tag they have. All the sprites are stored directly in Resourced. The reason I'm doing this is that depending if its an iPhone5, iPad Retina or iPhone6 I want specific sprites tags to be loaded. If I created folders for each Scene in the game that have different sprites directly in Resourced, I would using be able to use:

    Resources.Load<Sprite>("scene1/foo@HD")

    This will only load the sprite named "foo@HD" which is in Folder named "scene1". Don't see nothing wrong why this can't work. So Sprite Packer (PRO Only) still can't be used in Resources folder?? Honestly that's one of the main reasons I wanted to buy the PRO version but not gonna be useful in this case. Any suggestions I'm up for
     
  14. andsee

    andsee

    Joined:
    Mar 20, 2012
    Posts:
    88
    Yep the following would be nice

    Resources.Load<Sprite>("scene1/foo@HD")

    It would load the atlas texture with the sprite on it along with the actual Sprite object. Any further loads of other sprites would use already loaded atlases or load them as needed.

    It should all just work but supposedly the current implementation is 'intentional'. I really hope someone at Unity thinks about this and comes up with a solution that allows sprites in the resources folder, I can't see a technical reason why it couldn't be supported. I certainly can't see the reasoning that a sprite in the resources folder should not be atlased, why not? As long as it has an atlas tag then it can be put into the relevant atlas texture(s), the rest of the APIs should just work.
     
  15. maltadirk

    maltadirk

    Joined:
    Mar 12, 2014
    Posts:
    43
    Yeah apparently the new sprite packer in Unity 5 is suppose to solve a lot of problems.

    Also wanted to add that if you have later scenes in the game that no longer use the previous sprites loaded in the Resource folder, the following line can be used to unload stuff accordingly:

    Resource.UnloadUnusedAssets()
     
  16. Newcomma

    Newcomma

    Joined:
    Feb 10, 2015
    Posts:
    68
    I agree this is an issue. My main problem right now is I can't figure out how to enumerate all sprites in a Texture atlas at runtime, is it possible? I tried to use the Resources folder as you *can* enumerate assets at a path (so if these assets were all packed then I also get all sprites in a texture atlas for free) however as sprites in a Resources path don't pack this isn't possible.

    This is all Unity5 as well.
     
    TheSePo likes this.
  17. sysameca

    sysameca

    Joined:
    Mar 2, 2013
    Posts:
    99
    +10 to have that feature
     
  18. ericvids

    ericvids

    Joined:
    Nov 20, 2014
    Posts:
    1
    I've just discovered that you can still put sprites in the Resources folder into an atlas if you do the following steps:

    1. Temporarily move the folder that contains your sprites outside of the Assets/Resources folder
    2. Change the packing tag on all of the sprites
    3. Select Pack from the Sprite Packer
    4. Finally, move the folder back into Resources

    * it is necessary to do all of these steps every time a sprite is changed, *including step 2*, or else the Unity editor will not consider all sprites for packing

    The reason why I need to do this in my project is because I need a way to load individual UI sprites at runtime by name (for example, context-sensitive user actions may require different sprites on the same logical button, and the exact nature of the action might only be determined at runtime) and at the same time I want to apply rendering optimizations by batching similar sprites in a single SetPass call. Individual sprites loaded via Resources.Load<Sprite>() creates individual SetPass calls for EACH sprite, unless they were all in the same atlas. Making prefabs for each individual sprite just to replace that simple Resources.Load<Sprite>() call is overkill.

    Unity, please remove this skip-Resources-folder restriction for the sprite packer. As other posters have already said above, the implementation need not store the atlas-ed textures twice.
     
    ecesis_llc and DomDom like this.
  19. iPicnic

    iPicnic

    Joined:
    Apr 8, 2014
    Posts:
    6
    Hi again!

    Has someone figure out how this unity's sprite packer thing works?

    I haven't been able to figure it out...I really don't know how I can call the sprites from this "logical atlas" in my code. How to load it. there's no tutorial to how load sprite by code using this unity's sprite packer.

    Please someone from unity team teach us how to use this thing please!!!
     
  20. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,225
    Gives sprites a packing tag, and all sprites with that tag are packed into an atlas. You don't have to do anything else; it's all automatic and you refer to sprites the same way as always. As far as your code goes, it's all the same whether sprites are part of an atlas or not.

    --Eric
     
  21. ForceMagic

    ForceMagic

    Joined:
    Feb 27, 2015
    Posts:
    36
    I encounter the exact problem for the same reason of @ericvids and we are having problem to save the packed atlas.
    @Eric5h5 Nop, sorry to say so, but this is not true.

    If you change settings on the packed images, even if they have the same tag, you might loose the performance enhancement.

    You have to do exactly what @ericvids said when you add, modify or remove one sprite in an atlas. Including step two even if they have already the same tag, for instance you have to set them to "packed1" then back to "packed". Then repack them all.
    But even that, since there is no file to save, I don't see how I can submit it to my perforce server to make it effective for all of my coworkers.

    This is far from ideal, to my point of view, this is also a bug.

    At this point, I am wondering if this isn't a local thing stored somewhere in a temp folder and the one who does the build will have to ensure every scene are properly batching the draw calls.

    Have anyone found a way to "save" the packed atlas?

    EDIT: I also found this related question on answer.

    EDIT2: @ericvids I just found out that the manupilation that we are doing works until I restart unity.

    Then, since I moved back the sprites into Resources (while keeping the atlas tag), it looks like the Atlas is not re-created and thus it looses it every time too.

    EDIT3: The root problem have been posted in Feedback which is to access the sprites by name in the atlas.
     
    Last edited: May 20, 2015
    ericvids likes this.
  22. zombiegorilla

    zombiegorilla

    Moderator

    Joined:
    May 8, 2012
    Posts:
    8,052
    Don't put them in the resources folder. The point of the resources folder is specifically to be able to load assets by their path, so they of course will be included in the build. Everything in those folders will be. As Eric said, that is the intended behavior.
     
  23. ForceMagic

    ForceMagic

    Joined:
    Feb 27, 2015
    Posts:
    36
    We realized now that when in Resources folder, they are not part of an atlas anymore even if they do have an atlas tag.

    We agree on that, but the root problem is that we cannot access those atlas sprite by name to assigned them dynamically.

    This is a major flaw to the system, we just cannot afford to use the arrays without knowing which sprites are at which index.

    Thus, we voted on this one, but I fear this might not be fixed soon...

    P.-S. Thanks for your quick reply.
     
  24. zombiegorilla

    zombiegorilla

    Moderator

    Joined:
    May 8, 2012
    Posts:
    8,052
    You don't need to reference them by index, that kinda defeats the purpose of the system. ;) You reference them directly like you would any other asset. The atlas is designed that way, to use normal references.
     
  25. ForceMagic

    ForceMagic

    Joined:
    Feb 27, 2015
    Posts:
    36
    Yep, that's what we realized, but we need to reference them by name at runtime and there is no way right now to get the atlas at runtime since it's internal to Unity.

    So we have to put the sprite we need at runtime in the Resources folder and thus it cost more draw calls, it's about 32 extra drawcalls in our case for one of our UI menu...
     
  26. zombiegorilla

    zombiegorilla

    Moderator

    Joined:
    May 8, 2012
    Posts:
    8,052
    I guess I am a little confused, why do you need to reference the atlas? If you reference the sprite directly, under the hood it returns the asset from the atlas instead of pointing to the source. Are you swapping content in the resources folder post build/deploy or something funky?
     
  27. ForceMagic

    ForceMagic

    Joined:
    Feb 27, 2015
    Posts:
    36
    No, my goal is to build an Atlas to be able to make reference of the containing sprite by name at runtime.
     
  28. zombiegorilla

    zombiegorilla

    Moderator

    Joined:
    May 8, 2012
    Posts:
    8,052
    Sure, so like just like every asset you would use in a game. ;). Sprites are no different. If you want to reference them by name (string) you can use a dictionary or create a manifest, or class to tracks the refs. If you have a lot and don't want to do it by hand, just script it to update by folder, or use the packer to get all your sprite names and populate an array somewhere (editor). ScriptableObject is a great way to store large amount of references, I have started finding all kinds of uses for it. If you have only a handful, just drag them in the editor to an array on whatever class is using them.

    Basically there are tons of ways to do it depending on your projects needs. All that use proper references and won't break in all the ways that loading by path can (resources). The resources.load option, seems convenient, but it is really only for special cases. Swapping images in a UI, is very common. Using resource.load creates dependencies that editor doesn't correct for, make things more fragile, more overhead, builds content you may not use, creates possible ambiguation among assets, and leads to larger sizes. For all the normal tasks, use reference. Definitely Resource.load has a purpose, this just ain't it. ;)
     
    Last edited: May 22, 2015
  29. zombiegorilla

    zombiegorilla

    Moderator

    Joined:
    May 8, 2012
    Posts:
    8,052
    That would break the usage of files in the resource folders.

    For example you place a texture in resources, and pack in a sprite sheet. If the case was that was now a reference, and you wanted use that image as a material texture or manipulate it or whatever, it would be pointing a spritesheet instead of the image. The spriterenderer knows how to deal with atlases, others do not.
     
  30. ForceMagic

    ForceMagic

    Joined:
    Feb 27, 2015
    Posts:
    36
    This is precisely my case and I really thought this should have been a basic feature included with the Unity Sprite Packer.

    However, I honestly wish to thank you because I never heard of ScriptableObject before and you made me understand the potential of it. This is a really cool feature of Unity.

    I will try to use it to build a sort of "Atlas mapper" for my sprites.
     
    Last edited: May 22, 2015
  31. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,225
    The point of the sprite packer is to be invisible. That is, it "just works" and you don't have to be concerned about whether a sprite is part of an atlas or not. So what zombiegorilla wrote about references is completely correct; in general (not always) you'd stay away from Resources.Load and just use references whether you're using the sprite packer or not.

    --Eric
     
    zombiegorilla likes this.
  32. zombiegorilla

    zombiegorilla

    Moderator

    Joined:
    May 8, 2012
    Posts:
    8,052
    I really only learned about it couple of months ago, and even then for some reason I thought it was only an editor class. I'm starting to find it really useful!

    Also, odd timing, just last night at work, I was pinged about this exact topic. We want to automate sprite referencing based on atlases, to replicate the similar functionality that's in ngui. Heh. I'll probably take a crack at doing it with the packer class.
     
  33. Disastercake

    Disastercake

    Joined:
    Apr 7, 2012
    Posts:
    314
    I'd like to add to this and say that it's a bit silly that Unity couldn't take a look at great Sprite Packer systems like NGUI or 2D Toolkit and figure out what developers actually need for dynamically creating UI.

    I have 100+ skill icons that appear when certain skills are on the skillbar. Only about 8 are shown at a single time. When the player swaps out skills, the icons change. The way I've dealt with this with NGUI is to Resources.Load("atlasName") then get the sprite from the atlas. This allows me to decouple my resources from my code so all I have to do is throw things in the Resources folder to get them without having to maintain physical references via prefabs.

    However, Unity 5's "New GUI" doesn't have a way to access sprite via a simple line of code like this. From what I can tell, everyone is recommending you make a script that manages this for you, and this script has drag and drop references to your sprites. This is really silly that this has to be done this way. In the example I stated above, I would have to go through and drag and drop 100 icons into the gameobject reference. If the point of the sprite packer is to be invisible, that's great, but then it should allow us an intuitive way to get the resources without having to maintain reference links ourselves.

    I understand that Resources.Load() is suppose to be for only loading at runtime and not for packed atlases. That's fine. Then we need something else that can get the sprites for us so we don't have to maintain direct references and don't have to create our own Sprite management classes. For example: a static getter method like PackedSprites.Get("spritename") or something like that would be what I would expect from a system like this.

    As it stands, this "New GUI" sprite packer system is a step backwards from other sprite packing systems that have been available for years on Unity's own Asset store, but all it needs is an intuitive way to access the atlased sprites via code and it will be as good as the rest!
     
    Last edited: May 28, 2015
    Menion-Leah and Ox_ like this.
  34. zombiegorilla

    zombiegorilla

    Moderator

    Joined:
    May 8, 2012
    Posts:
    8,052
    With ngui, you should not be using resources load either. (again, shouldn't be used for common/trivial usage). All you need is a single reference to the atlas or any sprite (then ref up to AtlasListData). In fact the most optimal way for ngui is store your resource images outside of the asset folder altogether, only storing the compiled asset (atlas) in the project.
    But the Unity packer is much more advanced then the others in both its optimization and mesh building. That alone makes is far more superior.

    Resoucres.load() is NOT for "loading at runtime". It is for loading assets from a specific file path, (not managed by references). Sure you can use, but you lose many of befits of doing it properly. Sure there are lots of simple ways to do to things. In fact, it would be much simpler to just dump all the images in the resources and forget about altlas all together. It is extra steps after all, right? All that extra hassle who needs it. The simple reality is you can do things the quick and dirty way (fine for prototyping), or you can do things the proper way, often the proper/performant/efficient does take more time. You almost never get simple and optimal in the same process.

    Yes that is one way, and the simplest if you have minimal experience with more advanced coding techniques. But of course you realize that when you "go through and drag and drop 100 icons into the gameobject" you are talking about less than one second of work. Sure if you have 2000 sprites, it make up to a full second. Still less steps than doing resource load even. If you don't have a full second to spare, write a script that updates it for you, 5-6 lines of code, depending how you want to do it. It is absolutely trivial to do it the proper way, and dramatically more robust. By doing it this way, you can change sprite names, locations, atlases (or not atlases) and never have to update your code.

    So technically the proper way is faster, more efficient, easier and more robust. Oh, and superior packing results to other options.

    It is invisible, you have the exact same way to use the assets as every single asset in Unity ever. How do you load textures, gameobjects, prefabs, materials, etc...? (hopefully not resources.load, no win there) sprites load exactly the same way as all those. It is invisible because the knowing and dealing with the atlas has nothing to do with utilizing game assets. You reference and load the sprite. You don't care or need to know where it comes from, you don't even really need to know the name. Separately that you can move that sprite to whatever atlas you want, or even make it separate from any atlas all without affecting game logic. If you go the resources route you are locked in, locked in to location, atlas and name, ambiguous and fragile and hard on memory. A minor tweak means you may have to update in several locations.

    Again, it works like every other asset in Unity, forget that sprites are anything different. Pretend they are textures or gameobject or particlesystems or whatever. Forget about the atlases, that is optimization when you get to that stage. Binding/referencing the sprites to atlases not part of your game logic. Don't overthink or preoptimize. And most importantly use things the way they were built, fighting the process just loses many of the benefits.
     
  35. Disastercake

    Disastercake

    Joined:
    Apr 7, 2012
    Posts:
    314
    Thank you very much for your opinion, zombiegorilla. It seems you are very passionate about this subject. I appreciate the thought you put into it.

    Unity disagrees: http://docs.unity3d.com/Manual/LoadingResourcesatRuntime.html

    The biggest maintenance hassle comes when removing sprites from the game. If you want to remove the sprites from entering your game, you now need to manually maintain this link, when it should just be as simple as taking it out of the atlas. All we're looking for is a way to reduce this manual maintenance, and reduce the chance for user error through automation.

    Since there seem to be several people in this thread with this problem, perhaps you'd like to assist us and share this editor script template that can increase our workflow performance by automatically placing the asset links. I'm sure everyone would be greatly appreciative.

    No one here (that I read) is trying to preoptimize. We are trying to find the most simple and decoupled way to handle the situation. We have had extensive experience for years using a system that worked well, and now this new system seems less intuitive in hindsight. We've simply given feedback and were not looking for an argument.

    The script you mentioned earlier would be great for removing the grunt work of manually linking to files that everyone in this thread is concerned about. Could you please share this with us?
     
    Last edited: May 28, 2015
    Ox_ likes this.
  36. zombiegorilla

    zombiegorilla

    Moderator

    Joined:
    May 8, 2012
    Posts:
    8,052
    It is not the primary way for loading assets at runtime, it alternate way, specifically to load from file path. And it the entry in the manual also indicates the downsides of using that method.

    No matter what method you use, you are going to have remove them in two places. Ultimately that is the responsibility of the developer depending on the needs of the project (or aspect). If you have code calling "dog_front" sprite, whether by reference or load.resources, simply removing the sprite won't change the code reference, no matter how you approach it.

    I cannot post code, but I'll show a couple examples to get you started. Obviously the simplest is
    Code (csharp):
    1.  
    2.     public Sprite[] sprite_list;
    3.  
    Just drag all your sprites on the that in the inspector, and query by name. You can make it global by wrapping it in a static class (or build a service). Overly simplified, but illustrates the concept, dial it in as needed.

    However I'll provide a more practical example. A while ago, I built an asset swapping framework for localization of images in the UI. (it was later modified to but a UI skinning system, and in part, gear/armor swapping for a 2d fighting game.) The basic structure is built on 3 parts:
    First, here is my general project structure (the relevant parts)
    Code (csharp):
    1.  
    2. Assets
    3.  __scene
    4.  _code
    5.  _prefabs
    6.  _gui
    7.   _shared
    8.   locale
    9.    en
    10.    es
    11.    fr
    12.    de (etc..)
    13.  _textures
    14.  
    1. Asset import script. Using AssetPostprocessor, any texture dropped into the project, settings are applied based on its location. For example, dropped into textures, it will get the default texture2d settings. Dropped in _gui/locale/en, it will be given my default settings for 2d/UI assets, along with the packing tag "locale_en", dropped in _gui/locale/es will get tagged "locale_es", etc. --This just saves a lot steps normally done by hand.

    2. Asset assignation script. This is where a big chunk of the automation happens. This is a editor script that can be run manually, or just hooked into a startup script (InitializeOnLoad) (usually the later when working directly with this part of the project.) I runs through each sub-directory of locale, and assigns each texture to a scriptibleObject asset (or creates if needed) called "en_sprites.asset", "fr_sprites.asset", etc. This is really just a simple class that contains an array of the sprite assets. When run it wipes the refs and re-adds them all. So this object only contains actual sprite-gameobjects that exist in those folders.

    3. GUI swapper/loader. This is where it is actually put into use. The main UX controller has method that walks the existing hierarchy looking for all spriterenderer instances, if the global locale flag is anything other than "en". If it is, it checks if the sprite name it finds it listed in the replacement list (from the loaded localized sprite bundle), and swaps any it finds. There are additional methods that extend the instantiation for the gui, that applies the same logic to any new content added to the core UX.

    USAGE:
    These three elements make the usage almost entirely automatic.
    Add a new localized image: just drop it in the right folder, hit play/build.
    Remove an existing one: delete it, hit play/build.
    Add a new element to the UI that has the ability to be swapped: just add it, the UX will override automatically any sprite that has a localized variant.
    Spritesheets, automatic. By bundling the object that references it, it will contain the atlas, so by loading that asset bundle, you get the references and the atlas of only the localized version you need.

    It all uses provided Unity tools and designed to work the way Unity works. The first iteration didn't use atlaes as they weren't fully implemented at the time. Once they were, that all pretty much came free because altas work invisibly. All based entirely on on how Unity has worked for a long time. The trick is understand the system and work with it rather than fight it.
     
    Ox_ likes this.
  37. renman3000

    renman3000

    Joined:
    Nov 7, 2011
    Posts:
    6,490
    EDIT:
    IGNORE:
    SLOVED.
    This new system is the bomb. So easy!




    Newb on the scene
    This Sprite Packer is crazy confusing. I get what is supposed to happen, but I am not getting the results.

    A) Sprites packed produce an image/atlas different from what it should be (odd shapes, background lines, or nothing at all).
    B)Upon packing, and packing and packing again, trying to get it right, a test shows no drops in batching. If I remove 5 of 8 sprites (which should all be on the same atlas from scene), the Batching number drops by that amount. Seems fishy.

    ??
     
    Last edited: Jun 29, 2015
  38. Ox_

    Ox_

    Joined:
    Jun 9, 2013
    Posts:
    93
    Great insights, thank you.

    I have two questions about your scheme:
    * how exactly do you use ScriptableObject for references? I usually use MonoBehaviors for it and they're sitting in scene hierarchy.
    * have you tried to create @1x/@2x sprite sets with Sprite Packer? Resolution-based sprite collections are working invisibly in 2d Toolkit plus it's super easy to remove @2x from web builds. It keeps me on using it for my mobile projects.
     
  39. MaxEden

    MaxEden

    Joined:
    Jun 22, 2013
    Posts:
    73
    The single global ScriptableObject with references on all sprites will load every single atlas in memory the very moment it has been deserialized and will keep them in memory until ScriptableObject is destroyed i.e. forever, won't it?
    I believe there should be more optimal way to do that.
    I mean I can write my own packing policy, my own asset generator based on this policy, my own streaming resource loader of these assets. But wouldn't it be more convenient to have such native function written by the developers themselves, who have access to all the needed data?
     
  40. ecesis_llc

    ecesis_llc

    Joined:
    Aug 3, 2015
    Posts:
    58
    Ok, how would one use an atlas if use are using a single prefab as a base for many different objects. I have a lot of different units that are placed on a board. I don't want to make a tons of prefabs for each unit. Sure they use a single unit script but a unit has sub components. If I have to change something I'd have go back and change all the prefabs. So, I have a single prefab and when I instantiate a unit it needs to grab a sprite to load into the sprite renderer.

    I see examples of people creating a game object with an array and dumping sprites into. Which seems like too much work. It is much more simple to load a folder path. Currently I just load a sprites folder from resources and stuff the sprite by name into a dictionary on my own sprite manager. Instead of the three step process of.... adding image to project folder, adding image to gameObject array, calling object from array.

    If I were to change to an atlas how do I call a sprite from an atlas at run time? Preferably by name.

    For example...
    Code (CSharp):
    1. //All of this is in a unit class, the data for the class is loaded from JSON
    2.  
    3. string charPortrait;
    4.  
    5. //my custom sprite manager
    6. portrait.sprite = SpriteAssets.GetSprite(charPortrait);
    7.  
    8. //how would I access Unity's sprite atlas?
    9. portrait.sprite = MysticalUnitySpriteAtlas.GetSprite(charPortrait);
     
    Last edited: Feb 27, 2016
  41. Disastercake

    Disastercake

    Joined:
    Apr 7, 2012
    Posts:
    314
    Someone give @MaxEden a cookie, because this guy gets it! His comment echoes the design mentality that made Unity successful, and it's important to the product's own health that customers can freely give feedback to remind them of the spots that don't follow that methodology, like this situation with atlased sprites not being read by Resources.Load().

    @ecesis_llc - You never access the atlas in the code. It's just something that happens automagically. So just accessing a sprite that is assigned to something in the scene already (like a container object with a sprite array) will get you the atlased sprite, but no reference to the atlas (unless they've changed it recently). All this means is less draw calls for you if there are atlased sprites on the screen at once.

    So all you need is this and it works as if it weren't even packed (but still actually is packed behind the scenes):
    Code (csharp):
    1. string charPortrait;
    2. //my custom sprite manager
    3. portrait.sprite = SpriteAssets.GetSprite(charPortrait);
    You're right, it would be easier to maintain the common way in a folder path. Unfortunately you can't do that with the way it currently is IF the sprites are atlased. If they're not atlased, then you can just call Resources.Load() normally, but the whole point to get anything to run well is they need to be atlased. You also can't access or load the atlas either to then get a sprite from it (like NGUI does). That's where the whole confusion is coming from.

    If manually linking the sprites seems like a headache to you (because it is), the other option you have is to make an editor script that will automatically read the folder path at Editor time and assign / link everything in that folder to the array object, but again it's a step back from the decoupled and designer friendly methods Unity generally has in place.

    You can watch several official tutorial videos on editor programming here if you want to pursue that option:
    https://unity3d.com/learn/tutorials


    I do hope Unity fixes this in the future and allows the atlas system to work as expected with the common Resource Loading methods.

    The common user expectation seems to be: It doesn't need to reload the entire atlas each time a sprite in the atlas is loaded, it should be able to just read that its part of the already loaded atlas and just work seamlessly as normal.
     
    Last edited: Feb 29, 2016
  42. zombiegorilla

    zombiegorilla

    Moderator

    Joined:
    May 8, 2012
    Posts:
    8,052
    It's effectively the same, but you don't need to have them in the scene or the overhead of monobehaviors. They exist in the project. Only they don't instantiate when you reference them, so they are very effective if you have a lot of data.
    Sure, all the time, our projects are mobile and rely on them. That is what assetbundles are for. You have separate bundles for each resolution (or whatever). and only load the ones the device or platform needs.
    No. That is the point, they are references, it is just a pointer to the asset. The sprite (and required assets) will be loaded into memory when you instantiate it.
    Yes, they are called AssetBundles. You can skip the other stuff mostly if you use assetbundles.
     
  43. zombiegorilla

    zombiegorilla

    Moderator

    Joined:
    May 8, 2012
    Posts:
    8,052
    They are. The whole resources folder is going away. The reason it existed was as a development connivence for constantly changing content. It's not intended to be used in production. But since the whole assetbundle process and pipleline is being improved, you don't need to have something like to resource folders to speed things up in development, you can use local assets and the bundles are handled at build.

    Asset and resource management is a very critical part of any game, more so for platforms with limitations like mobile. Magic folders and "easy" solutions like load or load from folder, trade developer ease for performance. Sure they work, but they work in the same way as using a hammer to drive in a screw. The solution isn't to "fix the hammer" it is to use a screwdriver.
     
  44. ecesis_llc

    ecesis_llc

    Joined:
    Aug 3, 2015
    Posts:
    58
    Yeah, I've built my own editor tools. I've moved over from the Starling game engine. I understand how an atlas works, I just don't understand how Unity's functions for dynamically created prefabs that do not already reference a sprite asset.... other than jamming all the sprites into an array (manually or with an editor script) on prefab or scriptable object.

    I'm a bit astounded that there is no access via script to textures (by name) within an atlas. The Starling game engine atlas system allows pulling a texture by name. Seems like a pretty standard feature. As other have mentioned you can vote on the feature here: https://feedback.unity3d.com/sugges...rite-packer-atlas-to-retrieve-sprites-by-name
     
    Last edited: Mar 1, 2016
  45. ecesis_llc

    ecesis_llc

    Joined:
    Aug 3, 2015
    Posts:
    58
    Ease of development allows us to focus on important features. Even the Starling atlas system allows you to pull a texture by name. Managing game performance (related to textures) in Starling is as easy to swapping in and out texture atlases for specific scenes. And determining which textures could reside in a shared atlas that is always loaded. You can then pull the textures needed from the atlas.
     
  46. zombiegorilla

    zombiegorilla

    Moderator

    Joined:
    May 8, 2012
    Posts:
    8,052
    Sure, but with starling, you pretty much need that, as the starling doesn't actually create atlases, they are generated by external tools, so you need to be able to see what is in them. With Unity, since you are building them in Unity, from assets in your projects, you have all that information already. Moreover, by decoupling atlas from the asset it makes much easier to manage your assets independent of packing/packaging (and vice versa).
    For example, if I have a sprite called Monkey, and it is on the stage or referenced by a script, I can rearrange my atlases a thousand times and everything still works.
    With starling/ios/cocos/anything that uses and externally built asset, if you are relying on an asset being bound to an atlas, and that that atlas changes... (or your artist inadvertently changes leg_front to leg_fornt), you have to go back and fix/update it.

    However, if you want to the flow and functionality of an externally built atlas with an accessible list of names, that is very easy to do as well. Just select the sprites and put them in a assetbundle. bundle.GetAllAssetNames(); or bundle.LoadAsset(name); And you can easily swap "atlases" in and out as well, and much more.
     
  47. ecesis_llc

    ecesis_llc

    Joined:
    Aug 3, 2015
    Posts:
    58
    Bundles sound great, but the documentation is horrid. I'm checking out the tutorial.

    I'm still not sure if this will really solve the issue of loading a texture by name. For those that haven't found the asset bundle tutorial you can find it below.

    https://unity3d.com/learn/tutorials/topics/scripting/assetbundles-and-assetbundle-manager

    It really seems this issue of getting a texture from an atlas revolves around Unity serialization vs other forms of serialization. My objects are serialized to JSON which just works, it also supports dictionaries and a few other handy types. But I can't save an image reference, I have to save a string. When dynamically generating a unit there is no way to get that texture easily.

    You will need the tutorial script that actually exports a bundle, as the default Unity interface doesn't create a file from what I can tell. Yet the default interface allows you to set assets to bundle names. o.0
     
    Last edited: Mar 2, 2016
  48. Disastercake

    Disastercake

    Joined:
    Apr 7, 2012
    Posts:
    314
    I'm curious to know why you feel you're speaking on behalf of Unity, because the documentation from Unity themselves does not reflect your opinion regarding this. There's no warnings that state "Never use this in a production build". In fact it specifically states

    Also...

    Which would lead one to believe that its meant for a compiled build, not just editor builds.

    There's even further information on how to optimize the Resources folder for the webplayer, which would be unnecessary if it was never meant for production.

    I understand that you feel that referencing every possible asset in the project in a custom asset manager is more performant, but that doesn't change that there are many people that are expecting a certain functionality that logically ties in to how the rest of the default Unity API works.

    After all these years of its existence, Unity would have posted a warning in the documentation if Resources.Load() was never meant to be used that way. It's known that there's a performance hit, but this goes back to your previous comment that people shouldn't be concerned with pre-optimization until it matters anyways. For the things that do matter, they can use direct references as suggested.

    I'm assuming that your comments are not really the words of Unity, but are just your own suggestions as someone that uses Unity for mobile games, where every tweak of performance matters, and where you don't have a huge amount of assets per project anyways. If that's the case, then I think you should be more careful in the wording of your feedback to make sure it doesn't sound like you're echoing official opinion. It can be misleading to others (especially new devs).

    If you feel your comments do echo Unity's own opinion, references to documentation or official blog posts would help support your comments. I would actually really like to read them if they exist.

    I'm also curious to know where you read they'll be removing the Resources folder. I sincerely hope its not true, because it seems like a very bad idea on their part to do so. Manually managing local asset bundles would be quite a headache unless they're completely overhauling asset bundles to be somehow reasonable to manage now.

    But even if they switch to some sort of local asset bundle system, I can't see how it would be any more performant that the current system if you're only dealing with a single compiled build and not downloading bundles. You'll still be looking for an asset bundle, then loading that entire asset bundle, then finding an asset inside of that asset bundle. It seems like a few more steps than things currently are.


    I thought it was weird at first too, because NGUI required an atlas then a sprite reference and I was use to that for years. However the Unity system technically works fine and you just don't ever need to reference the atlas. There's just never a need to deal with the atlas itself. The only problem is the sprites are not able to be accessed via a Resources folder.
     
  49. zombiegorilla

    zombiegorilla

    Moderator

    Joined:
    May 8, 2012
    Posts:
    8,052
    They do. They are from forth coming documentation from unity. Specifically, Resource Management in Unity 5 : The Definitive Guide. It is an extensive, full overview of all aspects of resource/asset management in unity 5. (~70 pages in the draft version). It should be available soon, as well as some resources/guides.
     
  50. zombiegorilla

    zombiegorilla

    Moderator

    Joined:
    May 8, 2012
    Posts:
    8,052
    http://forum.unity3d.com/threads/end-of-the-resources-folder.363800/#post-2355110

    Every Unity engineer I/we have discussed it with (or where it has come up), has strongly recommend against using resources folder except for very rare and specific cases (or as a convenience during development but not during production). In fact, their best practice recommendation for using the resources folder is : "Don't use it."

    The current docs in a lot of areas (and as @ecesis_llc pointed out with regards to assetbundles) are not great. Some out dated, some just difficult to parse out the key points. Unity is aware of this, and are building some great new/supplemental documentation to address this.
     
unityunity