問題1: 解決UI和3D物體層疊問題,只響應(yīng)UI的問題
先看看當(dāng)點擊3D物體和UI響應(yīng)事件的代碼,一般點擊UI使用IPointerClickHandler接口和OnPointerClick函數(shù),點擊3D物體時使用OnMouseDown函數(shù)。
點擊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;
}
}
但當(dāng)點擊后重疊3D物體的UI后響應(yīng)的事件會穿透UI同時響應(yīng)3D物體,事件如下所示

image.png
如何解決這一問題,我們可以在3D物體上也使用IPointerClickHandler接口以及OnPointerClick函數(shù),但是需要在攝像機(jī)上加上Physics Raycaster組件,這樣就不會出現(xiàn)穿透問題。
點擊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后不會出現(xiàn)點擊穿透問題

image.png
問題二:解決UI和3D物體的同時響應(yīng)問題
除了上面3D物體使用OnMouseDown函數(shù)以外,我們想要同時響應(yīng)并且同時都使用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>();
//獲取所有射線射中的物體并返回結(jié)果列表results
EventSystem.current.RaycastAll(data, results);
foreach (var result in results)
{
if (result.gameObject != this.gameObject)
{
//執(zhí)行所有點擊中的函數(shù)
ExecuteEvents.Execute(result.gameObject,data,ExecuteEvents.pointerClickHandler);
}
}
}
}

image.png
問題三:解決UI和鼠標(biāo)點擊之間的響應(yīng)問題
當(dāng)我有3D物體為只要點擊屏幕任何地方都會響應(yīng)事件的函數(shù),那這時候當(dāng)我點擊UI時候這個3D物體也會同時響應(yīng)。
點擊到UI后同時響應(yīng)
點擊鼠標(biāo)代碼如下,掛載在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;
}
}
這時候我們想當(dāng)我們點擊到UI后不響應(yīng)鼠標(biāo)點擊事件。代碼如下:
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;
}
}
這時候當(dāng)我們點擊除開UI的地方都會響應(yīng)Cube的事件,當(dāng)我們點擊中UI后只會響應(yīng)UI事件

image.png