Search Unity

Converting sprites to Textures at Runtime

Discussion in 'Scripting' started by Studio_Akiba, Aug 18, 2020.

  1. Studio_Akiba

    Studio_Akiba

    Joined:
    Mar 3, 2014
    Posts:
    1,422
    Due to using Unity's built-in Sprites editor for atlasing, I am limited to using Sprites for my editor-level work, and would like to continue doing so, but this presents a problem.

    I am using these for billboarding, and need to be able to apply them to standard materials, so I'm trying to convert them to Texture2D's at runtime so I can assign them easily to the MeshRenderer.

    Little problem here.

    For the most part, this seems to work, except for the first sprite, which rarely if ever converts. and When it does. it only does around a quarter of the sprite.

    Code (CSharp):
    1. public Sprite[] sprites;
    2. public List<Texture2D> textures;
    3.  
    4. void Start()
    5.     {
    6.         //Convert Sprites to Texture2Ds & populate List
    7.         for(int i = 0; i < sprites.Length; i++)
    8.         {
    9.             Texture2D t2d = new Texture2D((int)sprites[i].rect.width, (int)sprites[i].rect.height);
    10.  
    11.             t2d = ConvertSprites(sprites[i]);
    12.  
    13.             textures.Add(t2d);
    14.         }
    15. }
    16.  
    17. static Texture2D ConvertSprites(Sprite sprite)
    18.     {
    19.         Texture2D tex = new Texture2D((int) sprite.rect.width, (int) sprite.rect.height);
    20.         Color[] pixels = sprite.texture.GetPixels((int)sprite.textureRect.x, (int)sprite.textureRect.y, (int)sprite.textureRect.width, (int)sprite.textureRect.height);
    21.  
    22.         tex.SetPixels(pixels);
    23.         return tex;
    24.     }
    Why is my code struggling to convert the first sprite so much? I've gone over this many times over the last week or so and still can't work out what's going wrong, and why the result is inconsistent.
     
  2. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    First of all: if you are "unpacking" your atlas to create individual textures of each sprite at runtime, you are presumably destroying any efficiency gains that you got from using an atlas in the first place, and then also wasting memory storing duplicate pixels and wasting CPU cycles to do at runtime a conversion that in principle could've been done at build time. So you should make sure you have a really, really good reason for using that atlas--so good that you're willing to pay a significant performance penalty to continue doing so--and if not, then you should stop, and this code becomes irrelevant.



    Line 9 is doing nothing but creating garbage and should be removed (though this shouldn't affect your main problem).

    You might try processing your sprites in a different order (e.g. loop backards from sprites.Length-1 down to 0) to test whether the bug is timing-related (affects the first sprite you process) or is something special about one particular sprite.

    The documentation for the Sprite class seems pretty unclear about the relation between rect, textureRect, textureRectOffset, bounds, packingMode, and packingRotation, so I can't figure out the theoretically-correct unpacking algorithm just from what it says, but I notice on lines 19-20 that you are creating a texture whose size is based on rect and then trying to fill it with an array of pixels whose size is based on textureRect, which seems pretty suspect (I expect those need to be the same size, and thus ought to be using the same variable--though I don't know what variable they ought to be using).
     
  3. Studio_Akiba

    Studio_Akiba

    Joined:
    Mar 3, 2014
    Posts:
    1,422
    Alright, I've read through the Sprite documentation, as well as what little I could find online about runtime conversions and efficiency, and haven't really made much headway.
    Can you reccommend a better way of handling this situation, where I need to break up an atlas into it's component images?