将 Sprite 对象数组合并为一个 Sprite - Unity

Posted

技术标签:

【中文标题】将 Sprite 对象数组合并为一个 Sprite - Unity【英文标题】:Combine Array of Sprite objects into One Sprite - Unity 【发布时间】:2014-10-22 02:54:48 【问题描述】:

我在 Unity 中有一组 Sprite 对象。它们的大小因加载的图像而异。 我想像平铺地图一样将它们并排组合成一个图像。 我希望它们的布局就像你正在形成一行图像一样,一个接一个。 (注意:不是一个在另一个之上) 我怎样才能做到这一点?

我组合的原因(仅供那些想知道的人)是因为我使用的是多边形 2D 对撞机。由于当我并排使用多个对撞机时会发生一些奇怪的行为,我决定在添加一个大多边形对撞机之前只组合图像。请注意,这些事情发生在运行时。我不能只创建一个大图像并加载它,因为图像的顺序仅在运行时确定。

我希望得到一些帮助。谢谢。

【问题讨论】:

你尝试过只组合对撞机吗?那将是我的第一次尝试,因为它们似乎是问题所在。如果精灵相当简单,只需手动创建路径,如果不从原始多边形碰撞器中读取路径,然后将它们全部添加到新的或现有的,然后删除其余部分。 @Tom 我试过了,但我找不到组合对撞机的方法。我编写了一个获取所有点的代码,然后我删除了重复的点,但我没有得到我想要的结果。当我查看它时,我意识到我需要找到一种方法来确定有效路径。我必须忽略关闭每个图像的路径。但是,当我的图像的形状和大小不同(由很多点组成)时,我该怎么做?你能否指出我正确的方向/更好地帮助我。谢谢。 根据您从所有对撞机获得的路径数量,您可以直接复制它们而不进行更改:一起计算所有对撞机的路径,然后将新对撞机的 pathCount 设置为该数字,然后循环通过所有路径并使用 SetPath() 将它们设置在新的对撞机中。我的猜测是 嗨,Tom,不是所有路径都包含每个图像的结束路径吗? 每条路径本身都是封闭的,多边形对撞机可以包含多个路径,这些路径都必须自己封闭(我不太清楚你所说的关闭图像路径是什么意思)。但我认为,如果您没有遇到问题,nexx 的答案可能更适合您的问题:) 【参考方案1】:

Texture2D 类中有PackTextures method,但是由于它使您的图集成为正方形,您无法制作一行精灵,因此还有另一种方法可以通过读取图像的像素并将它们设置为新图像来做到这一点,它是在运行时做起来真的很昂贵,但会给你结果。

// 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>();

【讨论】:

谢谢你。我会试试看。会有多贵?它会极大地影响我的游戏性能吗?如果是,那么我想我将把它作为一个工具来使用,这样我就可以为我的对象生成多边形碰撞器并将其保存为预制件。但无论哪种方式,你都很棒。谢谢。 我认为保存为预制件会更好,因为该方法使用 n 立方嵌套循环,如果您制作大纹理可能会给您带来一些麻烦。您必须测试并找到最适合您情况的方法 是的。我只是决定将它用作工具并将其保存为预制件。我注意到它不能创建大的纹理。但是,这行得通,谢谢你。至少创建多边形对撞机对我来说会更容易。谢谢。

以上是关于将 Sprite 对象数组合并为一个 Sprite - Unity的主要内容,如果未能解决你的问题,请参考以下文章

Sprite Sheet自动检测单个Sprite界限

CSS:使用 .Less 管理 Sprite 图像

ps_cc:制作sprite拼贴图片

unity5中怎样实时更换Sprite Renderer中的Sprite

调整 Sprite Flex/ActionScript 的大小

以一定速度在屏幕上移动对象。(Sprite Kit)