Search Unity

  1. Unity 2019.2 is now released.
    Dismiss Notice

[OFFICIAL] Feedback request: API to Access Sprites in Atlas

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

  1. ColossalPaul

    ColossalPaul

    Unity Technologies

    Joined:
    May 1, 2013
    Posts:
    169
    Hi Friends,

    I'm talking about this: https://feedback.unity3d.com/sugges...rite-packer-atlas-to-retrieve-sprites-by-name
    So we could do this:
    Code (CSharp):
    1.  // get specific sprite by name
    2. var sprite = myAtlas.GetSprite("oneOfTheSprites");
    3. // or iterate them
    4. foreach(var sprite in myAtlas)
    5. { /*do something*/ }
    Trying to understand this request since it keeps coming up persistently. The point of a the SpritePacker is to group related textures to reduce draw calls.

    Say you have AsianFurnitures tag and all your Asian style furniture go into there. In all likelihood you will render an Asian room with Asian chair, table and couch. This is efficient.

    What you wouldn't do is to group all the couches into a Couch atlas so it would contain the AsianCouch, VikingCouch, MayanCouch. By doing this, rendering the Asian room will require the CouchAtlas, TableAtlas, ChairAtlas. This is not efficient and defeats the purpose of SpritePacker.

    But you might want to have a list of all couches for your in-game store so you could let the user browse through and buy the couch.

    My question to you is: Do you want to iterate the list of Asian furnitures or do you want to iterate the list of all couches?

    If all you want is a list of all couches for logical use, the SpritePacker is IMHO the wrong tool to help you build that list. It is really meant for optimization.

    Please help me understand your needs. Thanks!
     
  2. hawken

    hawken

    Joined:
    Aug 22, 2013
    Posts:
    480
    (a nice feature would be to be able to name sprites quicker, right now it takes ages to click on each one in the sprite editor, also you end up accidentally moving some when you click on them. Would be nice to have arrowkey navigation here or be able to name them in the Project window rollout triangle)

    Basically, I have given up on naming sprites individually, as it is a laborious process.

    Tags as I understand it, are to help you load sprites by theme, and negate loading textures into memory that you won't be using.

    So Asian Furniture would make sense, if you are in the asian house on the asian level. I guess this also leads to the assumption that you could say "tag name"."sprite name" to get a sprite. If you can't do this already?

    To be fair the current process is to make some public fields on a prefab, drag in some sprites and reference sprites by var name / array index using enums OR put prefabs with sprites on them in the Resources folder if I want a sprite change in code, which negates the tag process entirely.
     
    Last edited: Dec 14, 2015
    Makri907 likes this.
  3. iwaldrop

    iwaldrop

    Joined:
    Sep 3, 2012
    Posts:
    9
    I haven't used atlases or multi-type spite imports yet, but it seems to me that the use case for being able to get sprites by name out of an atlas is to be able to use them as though they were not part of an atlas. Being able to assign things in the inspector is great, but you have to be able to address things in code too imho. If you can already do this then I am missing the point of the request.

    Having looked through the unity scripting docs I did not find a SpriteAtlas class, which I honestly expected to find after finding Packer.atlasNames. I don't understand what the atlas name would be for if you can't then address an atlas with it.

    Anyway, if we can't get references to individual atlases and then sprites within them then, yeah, I would think this should be implemented. I was considering using them to grab assets out of such that an atlas of like things could be loaded via asset bundle and addressed via names taken out of a json manifest where the names of the sprites would only be known at runtime.
     
  4. superpig

    superpig

    Quis aedificabit ipsos aedificatores? Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,194
    @iwaldrop: I don't think "use them as though they were not part of an atlas" makes sense though. Atlasing is supposed to be done based on usage patterns - sprites that are on-screen at the same time as each other sharing an atlas - so, trying to pretend that the sprites are not atlased is sorta directly opposed to that. If you're accessing sprites completely randomly then you may even be better off not atlasing them at all; atlasing sprites badly might still save you a couple of draw calls but it wastes a ton of memory.

    Could you give a more concrete example of what you mean by 'like things' for your game?
     
  5. isidro02139

    isidro02139

    Joined:
    Jul 31, 2012
    Posts:
    71
    I am one of the up-voters for this feature request. Chiming in here...

    Yes, atlasing should be done based on the expected usage pattern of the sprites in the game, i.e. collecting sprites that will show up in the same area / at the same time into the same atlas; it's up to the developer to assign appropriate packing tags to achieve this. Ostensibly the goal is to keep as few atlases as necessary loaded in the graphics card at a time for faster lookup by the GPU (please correct me if I'm saying something wrong here I'm no graphics expert).
    - - -
    This issue is about being able to access and assign/switch sprites at runtime. Normally (?) this dynamicism is achieved in code by placing sprite assets into the Resources folders and calling Resources.Load("path_including_folders") but when they are auto-packed with Unity's sprite packer you can't grab the sprites anymore by name unless you store a reference to them via a prefab, etc.

    For example, in order to use the atlases auto-generated by Unity I made a prefab with a few lists of UI.images exposed to the editor (I have multiple list to for organization's sake, it's akin to how I would use subfolders in a Resources folder to organize sprites and deal with name collisions). I have to drag and drop each image into a slot which is a very manual process as opposed to keeping the images organized in Resources folders and subfolders. I have this singleton (ugh) manager script on my prefab to then get the images in code and work with them as I see fit::https://gist.github.com/anonymous/d3387c93983b12628264

    It would be nice to have access to the atlases/sprite directly, although perhaps there is some black magic there to cover cases where you have more images with the same packing tag then will fit in your minimum atlas size (actually I would love some clarity on what exactly these 'pages' are in the sprite packer editor window, are there multiple atlases under the hood the get pushed into the GPU together if possible?)

    Hope this is clear but if not, @ColossalPaul please follow up directly with me in the Unity slack channel my nick is arun02139.

    Cheers!
     
  6. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    949
    One of my concerns with this feature is it essentially makes sprite lookups a dynamic process... scripts could do things like "atlas.GetSprite(a + b + c)" making it impossible to determine whether a sprite is being used by the project or not.

    If I understand things correctly, the current sprite packer will literally tear an atlas to pieces; so that the individual pieces can be put back together into a more efficient atlas (using packing tags). A dynamic lookup mechanism would surely make it impossible for Unity to determine whether or not a sprite asset is being referenced... and thus you would be forced to pack ALL sprites, even the ones that are not actually being used.

    I am not sure how much of an issue this would be; but, there are almost certainly projects out there where people are taking advantage of the existing feature.

    When it comes to asset files, Unity generally determines which things are in use and which aren't based upon references made in other assets or scenes (or just being inside a "Resources" folder).

    Given the above; my vote would be against complicating things.

    If people are looking for named sprite lookups, then perhaps the better answer is to just create a data asset which maps sprite assets to unique keys. I created an open source asset called Ordered Dictionary Asset for Unity (available from Bitbucket) which makes this very easy to accomplish:



    With this approach it also becomes trivial to create multiple aliases of the same sprite; this can be extremely useful for the prototyping stage where you just want to block things out using the same sprites. It becomes effortless to remap all the sprites without any clunky fussing around in the sprite editor.
     
    Peter77 and isidro02139 like this.
  7. isidro02139

    isidro02139

    Joined:
    Jul 31, 2012
    Posts:
    71
    Ah I hadn't thought about the aspect of not-including unused assets in the build, you make a good point. But wouldn't this kind of solution require dragging and dropping the images into the editor slots? If I have 150 small images that I want to be able to dynamically assign to different UI.Images (which I do) I really don't wanna have to do this.. ^^;
     
  8. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    949
    My list implementation allows you to drag and drop a whole selection of sprite assets from the project window and drop onto the list control. The keys are automatically grabbed from the sprite sub-asset name.

    Aside: Of course, my list control isn't JUST for sprites; it can be used for any assets or non-assets! The key and value of each entry of the ordered list can be anything that Unity's serializer can understand.
     
    isidro02139 likes this.
  9. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    Accessing the sprites by name is not my primary wish. I would like to have some kind of an atlas asset, which allows me to get all the sprites in it, so a list or array of sprites would make me very happy :)

    I would like to use sprites for my Decal System. The idea is that the user selects a Decal System, picks an atlas asset that is supposed to be used for it and can place decals based on the sprites. This has the advantage that the user can only pick sprites from a certain atlas to keep the draw calls as low as possible.
    If I create an application where the user can place decals at runtime, I need a way to iterate through the sprites to show the user what is available. This is not trivial to achieve at the moment, but with an array or list of sprites within an atlas asset, it would become very simple.

    For the sake of simplicity, I consciously avoided things like what should happen if a sprite is removed from an atlas or moved to another one.
     
  10. ortin

    ortin

    Joined:
    Jan 13, 2013
    Posts:
    221
    As I understand it's requested mostly to avoid adding sprites manually to some serialized field before building, when you want to set sprites dynamically by name in runtime (like smiles etc).
    Sprite packer is adding all sprites with tag to atlas anyway, either they used or not, so it looks redundant to save sprite names additionally.
     
  11. IntDev

    IntDev

    Joined:
    Jan 14, 2013
    Posts:
    152
    I just need to be able to swap spritesheet at runtime.
     
  12. bryantdrewjones

    bryantdrewjones

    Joined:
    Aug 29, 2011
    Posts:
    147
    I completely agree with numberkruncher's post. I personally do not want these new atlas APIs if it means changing the sprite packer to be something *other* than a memory/draw call optimization tool.

    I use ScriptableObject assets to organize sprites for things like sprite animations or other contexts that require dynamic lookups. Super simple and works like a charm :)
     
    splucas likes this.
  13. ortin

    ortin

    Joined:
    Jan 13, 2013
    Posts:
    221
    Sprite packer doesn't check if a sprite being referenced or not - it just packs everything which has a packing tag set. And looking at how it works now (completely independent of the build process where unity "resolves" assets usages) I don't think it's going to be changed.
     
  14. ColossalPaul

    ColossalPaul

    Unity Technologies

    Joined:
    May 1, 2013
    Posts:
    169
    Hi,

    Thanks for all your feedbacks. To be honest, this is not the first time I've ask this questions to users, but it is the first time I've ask this forum.

    So help me check my understanding.

    What I seem to be getting consistently is -
    In wanting that, a lot of uses will immediately gravitate to the first and most obvious implementation which is

    So my question is, do you really care that the list of sprites came from the atlas? What if there is a tool that could automatically help you manage your lists of sprites automatically? Would that be enough?

    If you actually don't care about how it is implemented, but you really just want an automated list management system, would you consider using a different solution, something like this:

    (Labels as described in here http://docs.unity3d.com/Manual/ProjectView.html)

    Now this idea doesn't work yet obviously. All i'm trying to get at is to find out the root of your request. So is it really accessing the atlas or you want an automated sprite list management system? Please share...
     
  15. isidro02139

    isidro02139

    Joined:
    Jul 31, 2012
    Posts:
    71
    Ok so, I will just describe a simple use case that hopefully illustrates my issue with Unity's sprite packing solution:

    I have a game where when a unit is active, a ugui widget appears showing a detailed portrait of the character. This fairly high-resolution portrait (512x512) is based on the unit's 'job' and sex (think Final Fantasy Tactics). What I am used to doing is dynamically assigning the correct sprite to the widget's UnityEngine.UI.Image.sprite string field in code with the enum JobType.ToString(). I use texture packer to make my atlases now and it's worked out great – with Unity's sprite packing solution, I need to use a prefab and an extra script (see the gist from my *first* post in this thread) to keep the references and assign the portrait dynamically. I don't want to do that; it's extra manual work and what if my enums / job names change?

    - - -
    This is really an aside to the main point of the thread, but there are lots of different possible combinations of jobs, and in the future I plan to build the atlases on the fly (i.e. in the scene before the battle scene after the troop configuration is determined) to minimum the number of atlases needed in memory during battle. It's also likely that additional portraits will be downloaded on demand in the future without requiring an app update. If I do this, I will need a way to dynamically grab the right portrait in runtime – any ideas on what the code flow might look like?

    Thanks in advance ;)
     
  16. ColossalPaul

    ColossalPaul

    Unity Technologies

    Joined:
    May 1, 2013
    Posts:
    169
    That's what I understood as well, you are mostly interested in an automatically maintained list. It's not really about what's in the atlas. Yes?

    Because I could think of many reasons why a sprite could appear (logically) in multiple lists. Like shoes.png for a character that could appear in the character's list AND also the in-game store list.

    But with "get assets from atlas", this could only come from one of the list. How would you satisfy the need for an interable list that serves both your character AND you in-game store.

    But, if you imagine with my Label idea, you could apply 2 labels to the 'shoe.png'. You could put a "character_clothes" and a "store_item" labels on them. You could then use some API to get at the shoe.png by querying for sprites with either character_clothes or store_item. Doesn't this match your gameplay/logical use cases for automated list management better than atlas could ever hope to?
     
  17. rubeng

    rubeng

    Joined:
    Apr 20, 2013
    Posts:
    37
    When we make our games (Kingdom Rush series) in order to fit in low memory devices we sometimes need to make custom atlasses for some levels.
    So for example, in levels 1 to 5 we are using the "WoodsEnemies" atlas, and on levels 6 to 10 we use the "DesertEnemies" atlas.

    but then after that we make an expansion, that happens in the frontier of those terrains, and have a few enemies from the woods, and a few enemies from the desert. Loading both atlases wont fit into memory, so we need to make an "EpansionEnemies" atlas that cointains a few enemies of each.

    so we cant just point at one sprite in our enemy prefab, we need to reference the animations by name, that means referencing the sprites by name, and we dont want something solved at build time to map our enemy to the atlas or sprites needed. We want to just be able to load the proper sprites, and if we did our work right, then the needed sprites will be available for the enemy to be animated.

    We were able to hack 2dtoolkit to get that working in one of our projects (loading texturepacker sprites, and hacking the 2dtoolkit sprite component to run in editor and at runtime, and load by name the sprites).

    This behavior is the exact thing you get when using something like cocos2d, or libgdx, the developer is responsible for loading the atlases (this means that now there are a number of sprites available to be queried by name), then you define the animations as a set of sprites, and then you just use the sprites. There is a king of late binding of sprites to atlases that allows us much more control over our game.

    In another of our games, we have text files in a key value format to define skills for units, and one of the things we define there is the name of the Icon that the ability will have. Being able to just do sprites.load(iconname) and have that just work as long as I loaded the proper atlases would be ideal.

    Hope anything of this makes any sense, and feel free to ask for more info if needed

    Rubén
     
    isidro02139 likes this.
  18. Kiupe

    Kiupe

    Joined:
    Feb 1, 2013
    Posts:
    524
    In my case I don't care where a sprite come from - having a list that would allow me to query a sprite by name or by label as you suggested would be great ! If applying label could be done on a single Sprite or Sprite packed into an Atlas then it would be perfect ;-)
     
  19. ColossalPaul

    ColossalPaul

    Unity Technologies

    Joined:
    May 1, 2013
    Posts:
    169
    not sure how I feel about this. It makes some sense but also it makes it unintuitive to use for people that are not as resource strapped. Having to know what to load in order to use something is creating a an extra coupling. You will inevitably create a sprite<->atlasToLoad table and writing a lot of loading/unloading code.

    This is just a generic list use-case not a atlas specific one.

    I would still like to hear more use cases if anyone care to share... Not just in Unity but also in other engines or previous projects...
     
  20. superpig

    superpig

    Quis aedificabit ipsos aedificatores? Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,194
    It sounds like the main clear use case that has emerged so far is 'being able to swap a whole load of Sprites in one go,' for character reskinning and so on.

    The way you guys are used to doing it is to name all your sprites in a predictable way (e.g. 'walk_down_1' and 'walk_down_2' in the base skin, 'walk_down_1_blue' and 'walk_down_2_blue' in the blue skin) so you can easily loop through all the sprites, calculate the name for them, and bind the new Sprite through looking it up by name in a 'per-skin' atlas.

    Does that sound about right?

    It sounds very much like a use case that is not exclusive to sprites and needs to be easily solvable in Unity in general. I think the way I'd do it at the moment is to use AssetBundles, but the experience there is not yet as smooth as it needs to be yet...
     
  21. rubeng

    rubeng

    Joined:
    Apr 20, 2013
    Posts:
    37
    I completely agree that having everything work automatically by default is the best, and what makes it easier for beginners, but not having control for the loading and unloading of resources in an engine doesn't feel like a good idea. Mobile development in general is a resource strapped business. People already have to manage lists and lots of loading and unloading code to manage pools of objects, precache prefabs, etc, in order to get their game to perform in an acceptable way on mobile.

    Maybe there is a super smart solution that is not made around how atlases work, but having the ability of loading /unloading the atlases, and then being able to query sprites by name seems like something easy to support and gives everyone a way to get their solution as complex as they need without being constrained by the engine.

    This also would allow a simple solution for loading different resolutions of assets like support for retina/non retina graphics, you just load the proper atlases and the rest of the game would just work because the binding is by sprite name, not the atlas itself.
     
    mh114 and isidro02139 like this.
  22. ColossalPaul

    ColossalPaul

    Unity Technologies

    Joined:
    May 1, 2013
    Posts:
    169
    Hi,

    Thanks for all the great feedbacks. To summarize my understanding.

    Primary reason would be what @superpig said. Which is a late/runtime binding to sprite using naming convention. While this is technically feasible by packing sprites (and its atlas) into an asset bundle, the experience of doing so and using it is suboptimal. In short this is what you want:
    • Load the atlas that I need
    • Reconnect SpriteRenderer to the sprites inside this atlas manually by name

    Other interesting points raised that are not directly related to this but related to Sprite Packer
    • No manual way to unload an atlas
    • Can't pack a sprite into more than 1 atlas

    Let me work with the AssetBundle team to see what could be a better workflow before we write bespoke custom solution that only works for atlas and sprite. Stay tuned and if anyone has more to share, please do.
     
    isidro02139 likes this.
  23. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    949
    Not to forget the issue of animated sprites; how would this work with asset bundles?
     
    McMayhem likes this.
  24. shawnblais

    shawnblais

    Joined:
    Oct 11, 2012
    Posts:
    214
    The primary reason, is just plain flexibility. With the ability to load things by name, you can come up with any number of schemes around naming convention, that might be flexible and easy to use for your artists (re-skinning characters, swapping ui skins, swapping sprites on the fly, etc).

    And it's just sort of a common sense feature. If a sprite is present in the scene, it seems like it should be loadable by name. I think it's fine if a sprite comes back as null, it's the developers job to make sure the atlas is used in the scene.

    Also, I should mention, I feel as if the whole Asian Couch example has a very 3d-centric viewpoint. In a 2d game, I may have all my "in-game" sprites in just a few atlases, and they could easily all be loaded at once. In this case, we're not worrying too much about usage cases, we're mainly focused on optimizing draw calls by grouping them in visual layers, (ie BgSprites, UnitSprites, ProjectileSprites etc) they're all renderered in the same scene together,
     
  25. McMayhem

    McMayhem

    Joined:
    Aug 24, 2011
    Posts:
    443
    One of the most simple things you can do with a Sprite is sprite sheet animation. Being able to do this from code is very important for me (and from my numerous searches on google and this forum, a lot of other people as well). Currently, you cant do it from code, because there is no way to access the individual sprite in a sprite atlas (at least that I could find).

    Sure, you can declare public variables and set the sprite references in the inspector. That is a bad solution. That solution is a lazy approach to what should be a quick and easy process. If I have an 8x8 sprite sheet, you really expect me to sit there and manually drag 64 sprites into a list of variables? No.

    Animation with Mechanim is another common retort I hear, but again, that requires prior setup and cannot be modified on the fly. What if I want to tie the sprite animation speed to a variable other than what Mecanim can provide?

    Ideally, there would be a public function on Sprite that would allow you to either cycle forward/backward through a spritesheet, or set the current sprite to the desired cell number.

    If that's something you can already do, please let me know. Oh, and then freaking document it.
     
    MaxEden likes this.
  26. ColossalPaul

    ColossalPaul

    Unity Technologies

    Joined:
    May 1, 2013
    Posts:
    169
    Hi All,

    Thanks for the feedbacks on this feature. Keep them coming.

    We are discussing how this could be achieved. More later, stay tuned.
     
    McMayhem, MaxEden and isidro02139 like this.
  27. ZimM

    ZimM

    Joined:
    Dec 24, 2012
    Posts:
    945
    @ColossalPaul
    My request is somewhat parallel, but still very much related. In our project, we use reflection mapped sprites. This means that for each sprite, there is a second corresponding sprite in a separate file. We use MaterialPropertyBlock and a special shader to make this work, and it does indeed work well, even batching is working correctly. But, as you might have guessed, this technique relies on texture coordinates of the sprites being exactly the same. Thing is, this works only if sprites are not packed in atlas. As we have no control over how atlases are generated, there is no way to guarantee that texture positions of the "main" sprite and the "reflection map" sprites do match in atlases, making atlases unusable:
    upload_2016-3-11_15-33-22.png
    You can see that the bucket sprite is in completely different position. Other sprites do match, but by a complete accident.

    Again, this technique works without any downsides if atlases are not used. For now, we just don't use atlases at all, but that's very inefficient. The solution would be an editor API to manually control the atlas generation, so we could just copy the positions of sprites from one atlas to another. Currently, we are only able to control high-level stuff like what sprite into which atlas (using IPackerPolicy), but not the actual atlas generation.

    I guess this is a good example when it does matters that sprite is packed into atlas.
     
    Last edited: Mar 11, 2016
  28. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    8,192
    To be fair, it's really not as bad as all that. You can select and drag all 64 sprites in one go. Unity will mess up the order (that's a separate long-standing bug/limitation), but a simple context menu on the script can sort them out again by name (assuming you have a sensible naming convention).

    Code (CSharp):
    1. [ContextMenu ("Sort All Frames by Name")]
    2.     void DoSort() {
    3.         foreach (Anim anim in animations) {
    4.             System.Array.Sort(anim.frames, (a,b) => a.name.CompareTo(b.name));
    5.         }
    6.         Debug.Log(gameObject.name + " animation frames have been sorted alphabetically.");
    7.     }
    This is the approach I use with my SimpleAnimation script, which I use in a number of projects now quite happily.
     
    McMayhem likes this.
  29. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    8,192
    ...But @McMayhem raises a very good point I haven't seen raised here. A "sprite sheet" is not necessarily the same as an Atlas, is it?

    To me, an atlas is an internal optimization. Fine, Unity, go crazy optimizing things internally however you need to, and hide the details from me — that's a good thing, so you can optimize even more next year.

    But a sprite sheet is not an internal optimization detail. It's an organization of asset data. The sprite sheet comes from my art pipeline as a single file; I see it in the Project view as a folder containing a bunch of sprites. So it seems perfectly sensible (to me) to want to access that organization in code, too. So then I can switch from SummerTiles to WinterTiles in one go, and all my code that's looking for sheetName + "/Roof1" can find such a sprite in either sheet.

    Apologies if I have completely missed the point, but this is what I would want, at least.
     
    MV10 and McMayhem like this.
  30. McMayhem

    McMayhem

    Joined:
    Aug 24, 2011
    Posts:
    443
    That's a very good point. You don't have to do it one at a time and for what it's worth, I haven't had issues with Unity messing up the order of the sprites when moving it over.

    I think the bit that frustrated me the most is that there isn't a function you can call from code to access the individual sprites of a sprite sheet without declaring it as a public variable to be used in the inspector.

    Sure, using the inspector works just fine for me as I'm developing, but what if I want users to be able to drop in sprite sheets of their own or override sprites used in game? If I'm trying to dynamically load sprites at run-time, a public inspector variable does me no good at all.

    I'd just like to see functionality on this reflect that of pretty much every other object Unity handles.

    (I'm really hoping I'm just completely wrong on this, and that there's some alternative way to load sprite assets and access their individual sprites without having to use public variables. If so I apologize for the rant and will happily concede the point.)
     
    rakkarage likes this.
  31. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    8,192
    I think that's a tougher nut to crack — because what a user would drop in (unless you're bringing Asset Bundles into it) is just an image. How would Unity know where the actual sprites are? I guess if sprite sheets at runtime were a thing, we could say "make a new sprite sheet just like that one, but using this texture." Or, perhaps, "replace this sprite sheet's texture with this other texture."

    That would be kinda cool.

    But in the meantime, I'm pretty sure you can do this yourself; it's just a fair bit of work. Sprite is a class you can inspect, and also Create at runtime. So, if you had a bunch of built-in sprites from a spritesheet, but then wanted to grab the "same" sprites from some different (possibly dynamically loaded) texture, you could create a new sprite based on the coordinates of the original (for each sprite in your set).

    Incidentally, I've been playing with the RPG Map Editor asset, and it does something like this for character sprites. You give the script a 3x4 sprite sheet containing the walk frames in each of 4 directions, which are imported into Unity as a single sprite. It iterates over the rows and columns and carves this up (using Sprite.Create) into individual sprites at runtime, loading them into a simple data structure it uses for animation. So adding a new character, or even swapping out the sprite sheet at runtime, is pretty trivial.

    But I agree, it'd be nice if Unity made all this easier.
     
    Last edited: Mar 29, 2016
    McMayhem likes this.
  32. McMayhem

    McMayhem

    Joined:
    Aug 24, 2011
    Posts:
    443
    Okay, so THAT is the thing I've been looking for this whole time. I'm not sure how I missed it since I'm pretty sure I did some rigorous searching and saw a few posts where someone asked how to "create" sprites at run-time with no reply.

    With this method, since you can load texture files outside of the resources folder and turn them into Texture2D objects, you could essentially have a folder in StreamingAssets that would contain your images to be loaded as sprites. Then your loading method could get those images, convert them into Texture2D objects and use the Create method to convert them into sprites afterward.

    Huge, big, awesome thank you to @JoeStrout for revealing what I was simply incapable of getting at.

    The only question I'd have beyond that is, will the Sprites created using this method be batched like the others? I know Sprites in the Resources folder don't get batched and you have to keep them in your Assets folder somewhere, but I'm not sure if that applies to Sprites loaded at run-time as well.
     
    JoeStrout likes this.
  33. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    8,192
    That's a very good question. I suspect that the sprite packer runs at compile time only. This would mean that the sprites within a sprite sheet (texture) would get batched (all drawn in one draw call), but they would not get batched with other sprites from other sprite sheets, because those would use a different texture (thus different material). But I'm only guessing.
     
    McMayhem likes this.
  34. superpig

    superpig

    Quis aedificabit ipsos aedificatores? Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,194
    Correct. If you're loading your own Texture2D instances at runtime and then creating Sprites from them, you're responsible for packing sprites into those textures.
     
    McMayhem and JoeStrout like this.
  35. McMayhem

    McMayhem

    Joined:
    Aug 24, 2011
    Posts:
    443
    @JoeStrout
    I just tested it out and this works! I was able to use a folder in my StreamingAssets/Data/ directory to store custom icon images and load those images into Texture2D objects (nothing remarkable there). I then used the Texture2D.PackTextures method to create a single atlas, and then created the Sprites to reference each member of the atlas. I loaded it up in a test scene and had them populate a Grid Layout.

    The result was only one draw call! That's so great! @superpig super ROCKS! Thank you sir.

    I know, it's probably not that big of a deal to others, but this was a huge breakthrough for me. If anyone's interested, I 'd be happy to post my loading method as a new thread. I'm sure I could use some pointers on the efficiency of it anyway.
     
    JoeStrout likes this.
  36. cecilcruxis

    cecilcruxis

    Joined:
    Sep 17, 2013
    Posts:
    92
    As someone that enjoys seeing how other people tackle programming problems I would definitely be interested in hearing about your proccess.
     
    McMayhem likes this.
  37. McMayhem

    McMayhem

    Joined:
    Aug 24, 2011
    Posts:
    443
    Happy to do it! I've posted the thread here. Hope it helps at least one person :p
     
  38. RavenTravelStudios

    RavenTravelStudios

    Joined:
    Oct 15, 2015
    Posts:
    54
    I'd like also to access the single texture property of the sprite. Now i have some static spriteRenderers in my scene and they are working fine with packed sprites because they are pointing to the atlas directly in the scene. But at runtime, i need to access a single sprite from the atlas to retrieve his texture (not the whole atlas texture, just the embedded texture, as it works for single sprites) and slice it in several other parts, and that seems not possible because the texture property of a packed sprite refers to the entire atlas texture.

    Something quite like SpriteUtility.getSpriteTexture outside the editor would be nice.
     
    Last edited: May 20, 2016
  39. Johaness_Reuben

    Johaness_Reuben

    Unity Technologies

    Joined:
    Jan 27, 2016
    Posts:
    253
    isidro02139 likes this.
  40. imaginaryhuman

    imaginaryhuman

    Joined:
    Mar 21, 2010
    Posts:
    5,628
    Does it include (or could it) a simple way to mass-name all the sprites that belong in a 'group' together, e.g. all the frames from a walk animation get named Walk01 Walk02 etc separate from like Idle01 Idle02 etc, all from the same sprite sheet... instead of like 100 sprite with all the same name.
     
  41. Johaness_Reuben

    Johaness_Reuben

    Unity Technologies

    Joined:
    Jan 27, 2016
    Posts:
    253
  42. SoftwareGeezers

    SoftwareGeezers

    Joined:
    Jun 22, 2013
    Posts:
    506
    Here's my use case. Characters are made of pieces. At the moment I'm using a texture for each character and cut the sprites out at run time. Just discovered the dynamically spawning, this is horrifically slow so unusable. The alternative is to use individual sprites assigned at runtime. If I create individual sprites and use them in Unity's atlases for convenience, I'm having to manually catalogue and reference hundreds of sprites. If I'm not using Unity's automatic atlassing, I'm having to manually design and create dozens of spritesheets with hundreds of sprites!

    So it's not about saving drawcalls for me, as everything can fit in a few textures. It's about having the convenience of Unity's automatic sprite atlassing with the automation of Resources.LoadAll() etc. I think the fundamental issue is Unity see the Atlas as a draw call optimisation, whereas in reality we're needing it just as much as a production optimisation to get lots of sprites in an automated fashion.

    The intuitive, expect use would be as per the OP, atlas.getSprite(name). When it comes to worrying about draw calls, I'd say let the devs worry about. In some games, like mine, having an atlas for weapons, another for clothes, another for character pieces, may make more sense than a muddled atlas of assorted pieces.
     
  43. MuHaGames_Avee

    MuHaGames_Avee

    Joined:
    Feb 25, 2013
    Posts:
    25
    Hi Shifty, does my answer at: https://feedback.unity3d.com/sugges...rite-packer-atlas-to-retrieve-sprites-by-name solve your problem?
    I made this script to load by name one of the ~1000 sprites by name, I simply allow unity to cut my sprites into atlases and then use script to reference all the sprites in them and then call them by name XD

    Edit: yeey my Forum skills just grow form level 0 to level 1... this part of the forum allows for file upload... I will copy instructions as well for convenience

    There comes two files.
    Install:
    - put AtlasManagerEditor file in Editor folder, and AtlasManager somewhere else ;P
    - update: "/Zmey/Textures/" to the path where you have your sprites in "multiple" mode (they work as atlasses);
    - apply AtlasManager to some game object
    - use inspector "Load" button
    - at runtime access sprites by: AtlasManager.GetSprite("spriteName");
     

    Attached Files:

    isidro02139 likes this.
  44. Robin90

    Robin90

    Joined:
    Dec 21, 2016
    Posts:
    4
    Thanks for sharing!!;)
     
  45. joshcamas

    joshcamas

    Joined:
    Jun 16, 2017
    Posts:
    818
    I hate to bump an old thread, but is there any information on this? Adding this feature would make a lot of people happy, myself included. No rush, just wondering if this is a planned feature. :)
     
  46. ColossalPaul

    ColossalPaul

    Unity Technologies

    Joined:
    May 1, 2013
    Posts:
    169
    Ah, yes, we have the info now! This feature landed in 2017.1. It is also out now in our Experimental Preview 4.

    Have a go at it in the 2017.1 beta or the preview. Please write your feedback at preview forum
     
    isidro02139 and JoeStrout like this.
  47. Asse1

    Asse1

    Joined:
    Jan 9, 2013
    Posts:
    77
    I try to get a specific Sprite from the SpriteAtlas at runtime. Now the manual says that we should write a Component which holds the SpriteAtlas so we can retrieve the Sprite from that.

    The problem is that we use assetbundles and the atlas is included in every AssetBundle which holds a GameObject with the attached Component and the assigned SpriteAtlas. Even so the SpriteAtlas asset has an assetbundle tag and is exported as an assetbundle on its own.

    Is that a bug?
     
  48. Asse1

    Asse1

    Joined:
    Jan 9, 2013
    Posts:
    77
    Ok, https://forum.unity3d.com/threads/about-include-in-build-behaviour.481433/

    (I have a prefab that has a uGUI Image that refers a packed sprite in an Asset Bundle. The packed sprite atlas is also in the Asset Bundle. In this situation, even If I instantiate the prefab, the sprite doesn't be shown on screen) https://docs.unity3d.com/2017.1/Documentation/Manual/SpriteAtlas.html
    Regret to tell you that, late binding via the callback is currently not supported on our uGUI front. We will look into the possibility of making this happen, can't promise though. Try to work around the situation with the GetSprites() API I mentioned above, it's trickier, but hopefully it does the trick for you.
     
  49. ColossalPaul

    ColossalPaul

    Unity Technologies

    Joined:
    May 1, 2013
    Posts:
    169
    The asset bundle system will pull in anything in the reference chain.

    When it comes to asset bundle, we need to take extra care to pack and load them properly.
    - Ensure that the assets in the bundle are not duplicated elsewhere (unless that's what you want).
    - Ensure that we load the assets explicitly via assetBundle.LoadAsset(name). Except when you are using Asset Bundle Variant.

    It is a powerful and complex feature. It is not one-click system that just works yet.
     
  50. hectorSBM

    hectorSBM

    Joined:
    Feb 4, 2017
    Posts:
    15