c# - 如何获取我在 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);
}
}
解决方案
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);
}
推荐阅读
- ruby-on-rails - Rails Action Mailer - 为邮件收件人创建电子邮件通知
- javascript - 条带/重定向结账有问题
- opencv - 从地面 3D 点估计相机方向?
- python - 为什么单击 add_command 不起作用?
- angular - 将角度代码拆分为不同的组件
- r - 在 tibble 中永久添加一个新列,该列应将收集时间记录为天
- jekyll-theme - 当我尝试对帖子进行排序时,出现预期的 end_of_string 但发现管道错误
- laravel - 将复杂字符串解析为碳日期
- laravel - 如何在控制器中获取 api_token?
- r - 使用 tidyverse 创建具有特定特征 R 的变量编号观测值