Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Combine Array of Sprite objects into One Sprite - Unity

I have an array of Sprite objects in Unity. Their size vary depending on the image loaded. I want to combine them side by side like a tiled map into one image. I want them to be layout like your are forming a line of images, one after the other. (note: NOT one on top of the other) How may I be able to do this?

The reason why I'm combining (just for those who want to know) is because I'm using a polygon2D Collider. Since there are some weird behaviors happening when I use multiple colliders side by side, I decided to just combine the images before adding one big polygon collider. Note that these things happen during runtime. I can't just create a big image and load that because the order of the images is only determined at runtime.

I hope to receive some help with this. Thanks.

like image 468
cessmestreet Avatar asked Aug 28 '14 09:08

cessmestreet


1 Answers

There is PackTextures method in Texture2D class, but since it makes your atlas square you can't make a line of sprites, so there is another way to do it by reading pixels of images and setting them to new image,it's really expensive to do in runtime but gives you the result.

// Your textures to combine
// !! After importing as sprite change to advance mode and enable read and write property !!
public Sprite[] textures;

public Texture2D atlas;    // Just to see on editor nothing to add from editor
public Material testMaterial;
public SpriteRenderer testSpriteRenderer;

int textureWidthCounter = 0;
int width,height;
private void Start () {
    width = 0;
    height = 0;

    foreach(var  t in textures) {
        width += t.texture.width;
        
        if (t.texture.height > height)
            height = t.texture.height;
    }
    
    atlas = new Texture2D(width,height, TextureFormat.RGBA32,false);
    
    for (int i = 0; i < textures.Length; i++)
    {
        int y = 0;

        while (y < atlas.height) {
            int x = 0;

            while (x < textures[i].texture.width ) {
                if (y < textures[i].texture.height) 
                     atlas.SetPixel(x + textureWidthCounter, y, textures[i].texture.GetPixel(x, y));  // Fill your texture
                else atlas.SetPixel(x + textureWidthCounter, y,new Color(0f,0f,0f,0f));  // Add transparency
                x++;
            }
            y++;
        }
        atlas.Apply();
        textureWidthCounter +=  textures[i].texture.width;
    }
    
    // For normal renderers
    if (testMaterial != null)
        testMaterial.mainTexture = atlas;

    // for sprite renderer just make  a sprite from texture
    var s = Sprite.Create(atlas, new Rect(0f, 0f, atlas.width, atlas.height), new Vector2(0.5f, 0.5f));
    testSpriteRenderer.sprite = s;

    // add your polygon collider
    testSpriteRenderer.gameObject.AddComponent<PolygonCollider2D>();
}
like image 56
nexx Avatar answered Sep 16 '22 11:09

nexx