首页 > 解决方案 > 如何获取我在 Unity 中单击的像素的颜色?是否有适用于浮点数的 GetPixel 替代方案?

问题描述

我正在使用 Texture2D 来显示地图,我需要获取单击的像素的颜色。我使用 Input.mousePosition 来获取浮点坐标,但是使用 GetPixel 来获取颜色需要坐标是整数。

我无法让 GetPixel 找到我点击的坐标。

当使用浮点数并单击纹理的最右侧时,我会得到一个类似 27.xxx 的数字,但是当我将其转换为整数时,它会显示距离纹理最左侧 27 像素的坐标。浮点数表示像素的方式让我很困惑,也许澄清这会有所帮助。

public class ProvinceSelectScript : MonoBehaviour {
    public Material SpriteMain;
    public Color SelectedCol;
    public Color NewlySelectedCol;
    public Texture2D WorldColMap;
    Vector2 screenPosition;
    Vector2 worldPosition;

    void Start()
    {
        WorldColMap = (Texture2D)SpriteMain.GetTexture("_MainTexture");
        NewlySelectedCol = Color.blue;
    }


    private void OnMouseDown()
    {
        screenPosition = new Vector2(Input.mousePosition.x,Input.mousePosition.y);
        worldPosition = Camera.main.ScreenToWorldPoint(screenPosition);

        
        SelectedCol = WorldColMap.GetPixel(((int)(worldPosition.x)+(WorldColMap.width/2)) , (int)((worldPosition.y)+(WorldColMap.height / 2)));
        

        SpriteMain.SetColor("_SelectedProvince", SelectedCol);
        SpriteMain.SetColor("_NewlySelectedProvince", NewlySelectedCol);

    }
}

标签: c#unity3d2d

解决方案


worldPosition如果您使用透视相机或者如果您的相机指向任何方向但直接向前,则问题中的计算方式不会有用。

要找到点击的世界位置,最好的方法是在Camera.ScreenPointToRay与精灵位置及其局部前向形成的平面相交时计算点击的位置。

无论哪种方式,世界位置对精灵都没有任何意义,精灵可以定位在世界空间的任何地方。您应该使用transform.InverseTransformPoint来计算您单击的本地位置。此时,您可以使用 spriterenderer 的边界转换为规范化形式(0-1 源自左下角,而不是源自中心的世界单位长度)。

但是,一旦您以标准化形式表示了点击的局部精灵位置,您可以尝试使用GetPixelBilinear来获取点击的 (x,y) 的 UV 处的颜色。如果精灵超级简单,这可能会起作用。如果它是动画的或九切片的,或者其他任何它可能不会,并且您必须对鼠标实际悬停的 UV 进行逆向工程。

    Camera mainCam;
    SpriteRenderer sr;

    void Start()
    {
        WorldColMap = (Texture2D)SpriteMain.GetTexture("_MainTexture");
        NewlySelectedCol = Color.blue;
        mainCam = Camera.main; // cache for faster access
        sr = GetComponent<SpriteRenderer>(); // cache for faster access;
    }


    private void OnMouseDown()
    {
    Plane spritePlane = new Plane(transform.position, transform.forward); 
    Ray pointerRay = Camera.main.ScreenPointToRay(Input.mousePosition); 
    if (spritePlane.Raycast(pointerRay, out distance))
    {
        Vector3 worldPositionClick = pointerRay.GetPoint(distance);
        Vector3 localSpriteClick = transform.InverseTransformPoint(worldPositionClick);

        // convert [(-extents,-extents),(extents,extents)] to [(0,0),(1,1)]
        Vector3 localSpriteExtents = sr.sprite.bounds.extents;
        localSpriteClick = localSpriteClick + localSpriteExtents ;

        localSpriteClick.x /= localSpriteExtents.x * 2;
        localSpriteClick.y /= localSpriteExtents.y * 2;

        // You clicked on localSpriteClick, on a very simple sprite (where no uv magic is happening) this might work:
        SelectedCol = WorldColMap.GetPixelBilinear(localSpriteClick.x, localSpriteClick.y);      

        SpriteMain.SetColor("_SelectedProvince", SelectedCol);
    }

推荐阅读