Unity3D 中 UI 项目的 Raycast 替代方案
Alternative of Raycast for UI Items in Unity3D
我正在 Unity3D 中为 VR 项目实现注视算法。到目前为止,我在这里发现的是使用 Physics.Raycast
并为每个按钮对象添加 BoxCollider2D 组件以检测用户是否正在查看它。我想避免使用 Raycast,因为它很昂贵并且可能会产生性能问题,因为我要处理非常复杂的 UI 结构。
我尝试使用光标锁定,但不幸的是它不适用于移动平台。
我还尝试使用相机视口的中心来检查按钮对象的 rect
是否包含由
创建的世界点
Camera.main.ViewportToWorldPoint(new Vector3(0.5f,0.5f,Camera.main.nearClipPlane));
当按钮对象的矩形变换锚定为中间中心时,它工作正常。但是当它有一些其他设置或者按钮稍微倾斜时不起作用(在世界 space canvas 中)。而且我不太熟悉矩形变换的工作原理以及如何找到它在世界中的确切位置 space。
有人知道解决办法吗?或者还有其他方法吗?
非常感谢您提供各种帮助。
我发现了问题所在,是 z 轴上的不同值导致了问题。以下解决方案在不使用 Physics.Raycast
:
的情况下工作正常
void Update ()
{
pos = Camera.main.ViewportToWorldPoint(new Vector3(0.5f,0.5f,Vector3.Distance(transform.position,Camera.main.transform.position)));
_rect = new Rect(pos.x-size,pos.y-size,size,size);
_rect2 = new Rect(transform.position.x-rt.rect.width/2,transform.position.y-rt.rect.height/2,rt.rect.width,rt.rect.height);
Hit = _rect2.Overlaps(_rect);
if(Hit)
{
if (!isEntered)
{
_button.OnPointerEnter(new PointerEventData(EventSystem.current));
}
isEntered = true;
timeElapsed += Time.deltaTime;
if(timeElapsed >= 3) // autoclick after 3 sec.
{
timeElapsed = 0;
_button.onClick.Invoke();
isEntered = false;
}
}
else
{
timeElapsed = 0;
if (isEntered)
{
_button.OnPointerExit(new PointerEventData(EventSystem.current));
}
isEntered = false;
}
}
我正在 Unity3D 中为 VR 项目实现注视算法。到目前为止,我在这里发现的是使用 Physics.Raycast
并为每个按钮对象添加 BoxCollider2D 组件以检测用户是否正在查看它。我想避免使用 Raycast,因为它很昂贵并且可能会产生性能问题,因为我要处理非常复杂的 UI 结构。
我尝试使用光标锁定,但不幸的是它不适用于移动平台。
我还尝试使用相机视口的中心来检查按钮对象的 rect
是否包含由
Camera.main.ViewportToWorldPoint(new Vector3(0.5f,0.5f,Camera.main.nearClipPlane));
当按钮对象的矩形变换锚定为中间中心时,它工作正常。但是当它有一些其他设置或者按钮稍微倾斜时不起作用(在世界 space canvas 中)。而且我不太熟悉矩形变换的工作原理以及如何找到它在世界中的确切位置 space。
有人知道解决办法吗?或者还有其他方法吗?
非常感谢您提供各种帮助。
我发现了问题所在,是 z 轴上的不同值导致了问题。以下解决方案在不使用 Physics.Raycast
:
void Update ()
{
pos = Camera.main.ViewportToWorldPoint(new Vector3(0.5f,0.5f,Vector3.Distance(transform.position,Camera.main.transform.position)));
_rect = new Rect(pos.x-size,pos.y-size,size,size);
_rect2 = new Rect(transform.position.x-rt.rect.width/2,transform.position.y-rt.rect.height/2,rt.rect.width,rt.rect.height);
Hit = _rect2.Overlaps(_rect);
if(Hit)
{
if (!isEntered)
{
_button.OnPointerEnter(new PointerEventData(EventSystem.current));
}
isEntered = true;
timeElapsed += Time.deltaTime;
if(timeElapsed >= 3) // autoclick after 3 sec.
{
timeElapsed = 0;
_button.onClick.Invoke();
isEntered = false;
}
}
else
{
timeElapsed = 0;
if (isEntered)
{
_button.OnPointerExit(new PointerEventData(EventSystem.current));
}
isEntered = false;
}
}