Combine Array of Sprite objects into One Sprite - Unity
Asked Answered
H

1

12

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.

Haberdashery answered 28/8, 2014 at 9:37 Comment(5)
have you tryed combining just the colliders? that would be my first try as they appear to be the problem. If the sprites are fairly simple just create the paths manually, if not read the paths from the original polygonColliders and Add them all to a new one or existing one and delete the rest.Halfblood
@Halfblood I tried but I couldn't find a way to combine the colliders. I wrote a code that gets all the points then I remove the duplicated points and I didn't get the result I wanted. When I looked at it, I realized that I need to find a way to determine valid paths. I have to ignore the path that closes every image. But how do I do that when my images vary in shape and sizes (consists of lots of points) could you point me to the right direction/better yet help me with it. Thanks.Haberdashery
depending on the number of paths you get from all colliders together you could just copy them without changing: Count the paths of all colliders together, then set the pathCount of your new collider to that number, then cycle through all paths and set them in the new collider with SetPath(). My guess would be <50-100 paths is still fine. I run into problems when an algorithm created 1000+ paths as it would take unity forever to make the mesh from the paths.Halfblood
Hi Tom, wouldn't getting all the paths still include the closing path of every image?Haberdashery
Every path is closed in itself, and a polygon collider can contain multiple paths that all have to be closed in themselves(i am not quite sure what you mean by closing path of an image). But i think the answer from nexx might be better suited for your problem anyway if you havent run into problems with it :)Halfblood
E
5

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>();
}
Enfeeble answered 1/9, 2014 at 11:8 Comment(3)
Thank you for this. I will try it out. How expensive is it going to be? Will it greatly affect the performance of my game? If yes, then I think I will just use this as a tool so that I can generate the polygon collider for my object and just save it as a prefab. But either way, you are awesome. thanks.Haberdashery
Saving as prefab will better I think since the method uses n cubed nested loop it may cause you some trouble if you are making big textures. You have to test and find what's best for your situationEnfeeble
Yah. I just decided to use it as a tool and save it as prefab. I noticed that it can't create big textures. But, this worked and thank you for that. At least it would be easier for me to create the polygon collider. Thanks.Haberdashery

© 2022 - 2024 — McMap. All rights reserved.