3D物体上的UI显示时,存在判断点击的问题

3D物体上的UI显示时,存在判断点击的问题

1.所有2D和3D物体的射线检测。 当检测到 2D 对象时,表明当前存在 UI。 然而,Physics2D.Raycast()和Physics.Raycast()都只能检测包含Collider组件的对象。 普通UI如Image Button等一般光线将无法工作。 EventSystem.current.RaycastAll() 可以检测当前屏幕上所有可检测的对象。 该方法需要构造一个PointerEventData参数并传入检测到的点坐标:

1     PointerEventData pointerData = new PointerEventData (EventSystem.current);
2     pointerData.position = Input.mousePosition;
3     List results = new List ();
4     EventSystem.current.RaycastAll (pointerData, results);

ugui射线检测_unity射线检测耗时_射线检测算法

2、将PhysicsRaycaster组件挂在3D物体的Camera上,让3D物体上的脚本响应IPointerClickHandler等事件(原理与挂在Canvas上的GraphicRaycaster组件相同)。

当3D对象上有UI时程序开发,它会自动被UI事件拦截,因为通常UI(Camera或overlay)的显示级别高于场景中的3D对象。

unity射线检测耗时_ugui射线检测_射线检测算法

这样,只有当你点击UI时,它才会响应UI事件。 如果还想响应3D物体上的事件,只能再次使用射线来检测点击位置是否有3D物体(3D物体一般都有Colliders)。

3.具体参见以下代码

射线检测算法_unity射线检测耗时_ugui射线检测

 1         void Update ()
 2         {
 3             if (Input.GetMouseButtonDown (0) || (Input.touchCount > 0 && Input.GetTouch (0).phase == TouchPhase.Began))
 4             {
 5 #if UNITY_IOS || UNITY_ANDROID
 6                 if (EventSystem.current.IsPointerOverGameObject (Input.GetTouch (0).fingerId))
 7 #else
 8                 if (EventSystem.current.IsPointerOverGameObject ())
 9 #endif
10                     Debug.Log ("当前触摸在UI上");
11 
12                 else
13                     Debug.Log ("当前没有触摸在UI上");
14             }
15         }

不过EventSystem.current.IsPointerOverGameObject()只能检测Button等有事件的组件,普通Images等UI无法检测,所以该方法只用在少数简单的按钮和其他交互UI、3D对象之间。 当打开一个大的UI窗口并点击背景图片等非按钮时游戏运营,该判断将无效。

其他:

为了让3D对象响应点击,MonoBehaviour自带了一个消息函数MonoBehaviour.OnMouseDown()。 可以很容易实现,但脚本中最好不要有OnMouseXXX消息处理函数。 此类功能会影响游戏性能。 (当存在这样的函数时unity射线检测耗时,构建包末尾会有黄色警告,表示对性能的影响)

ugui射线检测_射线检测算法_unity射线检测耗时

Graphics Raycaster 的 Raycast 是一个虚函数。 您可以编写 Graphics Raycaster 的派生类。 执行默认的 Raycast 操作后,使用自定义图层过滤并移除不需要响应的游戏对象。 这样就只能响应某一层的需求。 在新手指南中unity射线检测耗时,只需设置需要响应特定层的游戏对象即可。

实现ICanvasRaycastFilter接口并将其挂在UI组件上。 当任意UI事件触发时,您可以实现自定义判断,例如:

 1 public class CustomRay : MonoBehaviour, ICanvasRaycastFilter
 2 {
 3     public bool IsRaycastLocationValid(Vector2 screenPoint, Camera eventCamera)
 4     {
 5         //....
 6         ...
 7         return true;
 8         //....
 9         ...
10         return false;
11     }
12 }

文章来源:https://mnews.68idc.cn/mobilesys/other/20170905643366.html