从texture2d / sprite获取像素的世界位置

时间:2019-03-23 13:17:41

标签: c# unity3d

我正在设置一个自动系统以能够附加一个精灵,它将收集其所有颜色和每个精灵的世界位置。已经建立了所有使用的颜色的列表/类别,但是如何获得所有这些精灵的位置?

我已经尝试过用数学方法进行此操作,例如获取精灵的完整大小,然后确定每个像素的大小,然后从中确定位置。但这似乎是有缺陷的,因为精灵的位置可能会发生变化。

Sprite ColouredSpriteTexture = ColoredSprite.GetComponent<SpriteRenderer>().sprite;
        Texture2D ColouredTexture = ColouredSpriteTexture.texture;
        float XsizeF = ColoredSprite.transform.localScale.x;
        int Xsize = (int)XsizeF;
        float YsizeF = ColoredSprite.transform.localScale.y;
        int Ysize = (int)YsizeF;
        List<Color> TempList = new List<Color>();

    //Could spawn pixels by getting x and y size and dividing them by 100 50/100 = 0.50f
    //if the tile has a color then spawn pixel if not 0.50 += 0.50
    //TODO test if this logic will work

    float PixelSize = XsizeF / 100;
    float currentPos = PixelSize;

    for (int x = 0; x < Xsize; x++)
    {
        for (int y = 0; y < Ysize; y++)
        {
            int listAmount = TempList.Count;
            Color ColoredTex = ColouredTexture.GetPixel(x, y);
            float TextureAlpha = ColoredTex.a;

            if (!TempList.Contains(ColoredTex) && TextureAlpha != 0)
            {
                TempList.Add(ColoredTex);
                ColorByNumber tempColor = new ColorByNumber();
                tempColor.Color = ColoredTex;
                tempColor.ColorNumber = listAmount;
                ColorOptions.Add(tempColor);

            }

            if(TextureAlpha == 1)
            {
                GameObject ColorPixel = Instantiate(PixelPrefab);
                ColorPixel.transform.localScale = new Vector3(XsizeF, YsizeF, 0);
                ColorPixel.transform.SetParent(this.transform);
                ColorPixel.name = "Pixel (" + x.ToString() + "," + y.ToString() + ")";
            }

        }
    }

我需要做的就是每个像素返回其位置,以便我可以存储数据并能够在此像素上方生成任何东西。

1 个答案:

答案 0 :(得分:1)

我还没有机会测试这个数学,所以可能有一些错误:

Unity中的每个图形图像都有一个PPU,这和对象比例将成为一个很大的因素。为了论证,我将为1个对象明确定义这些。

  • 图片尺寸:128x128
  • PPU:64
  • 比例:1,1,1
  • 对象边界:将 来自渲染器,我不确定是否已经限制 考虑比例(最有可能),但是在这种情况下 无法使用您可以计算ObjectBoundsWidth或height 只需将纹理的宽度或高度除以PPU。 这应该使您可以了解世界空间中的纹理。

我们还将假设我们仅在X和Y轴上工作而忽略Z轴,如果要使用Z而不是Y,则只需进行必要的更改即可Z缩放和Z位置和Z界限。

位于2,10处的像素的世界位置。根据文档,像素坐标从左下角开始,这意味着0,0是左下角,而2,10是左2像素,向上10像素。

编辑: 所以我将所有这些都插入了Google工作表,并确定我提供的先前算法有误,这里是伪代码格式的正确算法

// This function takes in either the x or y, and the width or height of 
// the bounds, then the x or y position of the object attached to.

// It also assumes the pivot is the center of the sprite.
float CalculateWorldPosOfPixelCoordinate(int coord, float boundsSize, float position, float scale)
{
    float PixelInWorldSpace = 1.0f / PPU;
    float startPos= position - (boundsSize* 0.5f * scale);

    return startPos + (PixelInWorldSpace * coord) * scale;
}

这是使用objectBounds来确定的,这就是我们乘以比例的原因。

这将使世界位置为-0.97,-0.84

我认为算法与Y相同,只是将坐标替换为Y位置,将边界替换为高度而不是宽度。

就像我说的那样,这可能是错误的,因为我没有机会对其进行测试,这也不能解释轮换情况。