问题1: 解决UI和3D物体层叠问题,只响应UI的问题
先看看当点击3D物体和UI响应事件的代码,一般点击UI使用IPointerClickHandler接口和OnPointerClick函数,点击3D物体时使用OnMouseDown函数。
点击UI代码
public class CollideUI : MonoBehaviour,IPointerClickHandler {
private int _index;
public void ChangeColor()
{
if (_index == 0)
{
GetComponent<Image>().color = Color.blue;
}
else
{
GetComponent<Image>().color = Color.white;
}
_index = _index == 0 ? 1 : 0;
}
public void OnPointerClick(PointerEventData eventData)
{
ChangeColor();
}
}
点击3D物体代码
public class CollideCube : MonoBehaviour
{
private int _index=0;
private void OnMouseDown()
{
ChangeColor();
}
private void ChangeColor()
{
if (_index == 0)
{
GetComponent<MeshRenderer>().material.SetColor("_Color", Color.black);
}
else
{
GetComponent<MeshRenderer>().material.SetColor("_Color",Color.white);
}
_index = _index == 0 ? 1 : 0;
}
}
但当点击后重叠3D物体的UI后响应的事件会穿透UI同时响应3D物体,事件如下所示
image.png
如何解决这一问题,我们可以在3D物体上也使用IPointerClickHandler接口以及OnPointerClick函数,但是需要在摄像机上加上Physics Raycaster组件,这样就不会出现穿透问题。
点击3D物体代码修改如下
public class CollideCube : MonoBehaviour,IPointerClickHandler
{
private int _index=0;
public void ChangeColor()
{
if (_index == 0)
{
GetComponent<MeshRenderer>().material.SetColor("_Color", Color.black);
}
else
{
GetComponent<MeshRenderer>().material.SetColor("_Color",Color.white);
}
_index = _index == 0 ? 1 : 0;
}
public void OnPointerClick(PointerEventData eventData)
{
ChangeColor();
}
}
如此点击叠加处UI后不会出现点击穿透问题
image.png
问题二:解决UI和3D物体的同时响应问题
除了上面3D物体使用OnMouseDown函数以外,我们想要同时响应并且同时都使用IPointerClickHandler,这样看起来比较整体。我们只需要修改点击UI方面的代码即可。代码如下
public class CollideUI : MonoBehaviour,IPointerClickHandler {
private int _index;
public void OnPointerClick(PointerEventData eventData)
{
ChangeColor();
ExecuteAll(eventData);
}
public void ChangeColor()
{
if (_index == 0)
{
GetComponent<Image>().color = Color.blue;
}
else
{
GetComponent<Image>().color = Color.white;
}
_index = _index == 0 ? 1 : 0;
}
public void ExecuteAll(PointerEventData data)
{
List<RaycastResult> results = new List<RaycastResult>();
//获取所有射线射中的物体并返回结果列表results
EventSystem.current.RaycastAll(data, results);
foreach (var result in results)
{
if (result.gameObject != this.gameObject)
{
//执行所有点击中的函数
ExecuteEvents.Execute(result.gameObject,data,ExecuteEvents.pointerClickHandler);
}
}
}
}
image.png
问题三:解决UI和鼠标点击之间的响应问题
当我有3D物体为只要点击屏幕任何地方都会响应事件的函数,那这时候当我点击UI时候这个3D物体也会同时响应。点击到UI后同时响应
点击鼠标代码如下,挂载在3DCub。
public class ClickMouse : MonoBehaviour {
private int _index=0;
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
ChangeColor();
}
}
public void ChangeColor()
{
if (_index == 0)
{
GetComponent<MeshRenderer>().material.SetColor("_Color", Color.black);
}
else
{
GetComponent<MeshRenderer>().material.SetColor("_Color", Color.white);
}
_index = _index == 0 ? 1 : 0;
}
}
这时候我们想当我们点击到UI后不响应鼠标点击事件。代码如下:
public class ClickMouse : MonoBehaviour {
private int _index=0;
GraphicRaycaster _raycaster;
private void Start()
{
_raycaster = FindObjectOfType<GraphicRaycaster>();
}
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
ChangeColor();
}
}
public void ChangeColor()
{
if (_index == 0&& !IsUI())
{
GetComponent<MeshRenderer>().material.SetColor("_Color", Color.black);
}
else
{
GetComponent<MeshRenderer>().material.SetColor("_Color", Color.white);
}
_index = _index == 0 ? 1 : 0;
}
private bool IsUI()
{
PointerEventData data = new PointerEventData(EventSystem.current);
data.pressPosition = Input.mousePosition;
data.position = Input.mousePosition;
List<RaycastResult> result = new List<RaycastResult>();
_raycaster.Raycast(data, result);
return result.Count > 0;
}
}
这时候当我们点击除开UI的地方都会响应Cube的事件,当我们点击中UI后只会响应UI事件
image.png