一. 解决UI与3D物体重叠时的同时相应
UI使用OnPointerClick,3D物体使用OnMouseDown会造成同时相应
UI:
继承接口IPointerClickHandler,实现OnPointerClick,响应鼠标点击。
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class ClickUi : MonoBehaviour,IPointerClickHandler
{
private bool change;
public void OnPointerClick(PointerEventData eventData)
{
if(!change)
GetComponent<Image>().color = new Color(1,1,1);
else
GetComponent<Image>().color = new Color(1, 0, 0);
change = !change;
}
}
3D物体:
重写MonoBehaviour.OnMouseDown()
using UnityEngine;
public class Click3D : MonoBehaviour
{
private bool change;
void OnMouseDown()
{
if (!change)
{
GetComponent<MeshRenderer>().material.color = new Color(0, 0, 1);
}
else
{
GetComponent<MeshRenderer>().material.color = new Color(0, 0, 0);
}
change = !change;
}
}
说明
UI的响应射线主要是Canvas上的Graphic Raycaster(图形射线发射器)实现,而Graphic Raycaster只会对继承了Graphic的对象响应。
解决办法:
3D物体继承接口IPointerClickHandler,实现OnPointerClick。在Main Camera上需要添加Physics Raycaster组件
二. 用OnPointerClick实现UI与3D物体同时响应
原理:获取到所有检测到的物体,再遍历调用其OnPointerClick
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class ClickUi : MonoBehaviour,IPointerClickHandler
{
private bool change;
private void ChangeColor()
{
if (!change)
GetComponent<Image>().color = new Color(1, 1, 1);
else
GetComponent<Image>().color = new Color(1, 0, 0);
change = !change;
}
public void OnPointerClick(PointerEventData eventData)
{
ChangeColor();
ExecuteAll(eventData);
}
public void ExecuteAll(PointerEventData eventData)
{
List<RaycastResult> results = new List<RaycastResult>();
EventSystem.current.RaycastAll(eventData, results);//获取到所有检测到的物体;ui源码中,只响应第一个
foreach (RaycastResult result in results)
{
if (result.gameObject != gameObject)
{
//调用物体的pointerClickHandler
ExecuteEvents.Execute(result.gameObject, eventData, ExecuteEvents.pointerClickHandler);
}
}
}
三. 鼠标点击Input.GetMouseButtonDown(0)位置发射射线,检测是否点击到UI
方法:用GraphicRaycaster 来检测点击位置发射的射线是否存在UI
using UnityEngine.EventSystems;
using UnityEngine.UI;
void Update()
{
if(Input.GetMouseButtonDown(0) && IsUI())
{
Debug.Log("点击UI");
}
}
bool IsUI()
{
PointerEventData data = new PointerEventData(EventSystem.current);
data.pressPosition = Input.mousePosition;
data.position = Input.mousePosition;
List<RaycastResult> results = new List<RaycastResult>();
//GraphicRaycaster只会响应UI
GraphicRaycaster raycaster = FindObjectOfType<GraphicRaycaster>();
raycaster.Raycast(data,results);
return results.Count>0;
}