前言
例如:最近在做一些Unity的小游戲需要,需要用到射線檢測(cè)和點(diǎn)擊事件等操作,雖然都是一些很基礎(chǔ)的東西但是也折騰了一會(huì),主要有些細(xì)節(jié)沒處理好就會(huì)導(dǎo)致不觸發(fā),寫篇博客學(xué)習(xí)記錄一下吧。
一、射線檢測(cè)
??1、3D射線檢測(cè)
??這個(gè)是最常用的,常用于3D游戲中通過射線檢測(cè)來獲取鼠標(biāo)點(diǎn)擊的位置來控制任務(wù)角色的移動(dòng)、以及在射擊游戲中通過射線檢測(cè)來進(jìn)行子彈擊中檢測(cè)等。這里我不細(xì)說射線檢測(cè)的API解析了,關(guān)于層級(jí)以及忽略自身碰撞體等情況直接查看對(duì)應(yīng)的API即可。代碼如下:
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
Debug.Log("射線檢測(cè):" + hit.collider.name);
}
}
注意:射線檢測(cè)是跟碰撞體配合使用的,當(dāng)我們使用3D射線檢測(cè)API的時(shí)候,需要給被檢測(cè)的對(duì)象加上3D碰撞體。
??2、2D射線檢測(cè)
這個(gè)多用于2D游戲之中,其實(shí)和本質(zhì)3D幾乎一直但是在發(fā)射射線的時(shí)候由于是2D,需要忽略Z軸的影響并且在發(fā)射的時(shí)候需要將屏幕坐標(biāo)轉(zhuǎn)換成世界坐標(biāo)。代碼如下:
if (Input.GetMouseButtonDown(0))
{
RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero, 1000);
if (hit.collider != null)
{
Debug.Log("射線檢測(cè):" + hit.collider.name);
}
}
注意:2D檢測(cè)需要添加2D碰撞體,且需要進(jìn)行屏幕坐標(biāo)到世界坐標(biāo)的轉(zhuǎn)換。
二、鼠標(biāo)按下事件OnMouseDown
當(dāng)我們需要在點(diǎn)擊某個(gè)物體(非UGUI)的時(shí)候,我們希望對(duì)自己本身和相關(guān)聯(lián)的對(duì)象進(jìn)行一系列的操作,這個(gè)時(shí)候我們就會(huì)用到這個(gè)函數(shù),并且這個(gè)函數(shù)是自動(dòng)觸發(fā)的。但是必須要掛在在非UGUI的物體上。代碼如下:
private void OnMouseDown()
{
//這個(gè)函數(shù)的觸發(fā)需要依賴碰撞體,并且這個(gè)腳本必須掛在在檢測(cè)的物體上且只能在點(diǎn)擊自己碰撞體的時(shí)候才會(huì)觸發(fā),類似于IPointClickHanlder這些接口事件觸發(fā)一樣
Debug.Log("鼠標(biāo)按下");
}
注意:這個(gè)函數(shù)是依賴于碰撞體的而且必須要掛載在非UGUI的物體上才會(huì)觸發(fā),還有對(duì)應(yīng)的鼠標(biāo)拖拽(OnMouseDrag())、鼠標(biāo)抬起(OnMouseUp()、鼠標(biāo)進(jìn)入(OnMouseEnter)等等類似的函數(shù),幾乎都是一樣的只是觸發(fā)條件不一樣。
三、UGUI常用檢測(cè)接口
對(duì)于UGUI的物體,我們也經(jīng)常需要對(duì)鼠標(biāo)在其上面的操作狀態(tài)來進(jìn)行對(duì)應(yīng)的操作和事件響應(yīng),這就要用到我們UGUI中的事件系統(tǒng)了。我們只需要繼承對(duì)應(yīng)的鼠標(biāo)操作接口,然后在接口實(shí)現(xiàn)函數(shù)中進(jìn)行對(duì)應(yīng)的操作即可。包含有:鼠標(biāo)進(jìn)入(IPointerEnterHandler)、鼠標(biāo)點(diǎn)擊(IPointerClickHandler)、鼠標(biāo)按下(IPointerDownHandler)等等。具體部分代碼如下:
public class UGUI檢測(cè) : MonoBehaviour, IPointerClickHandler,IPointerDownHandler,IPointerEnterHandler
{
//這些接口的檢測(cè)都是基于射線檢測(cè)的,在UGUI中需要勾選UI組件的Raycaset Target,否則無法觸發(fā)
public void OnPointerClick(PointerEventData eventData)
{
Debug.Log("鼠標(biāo)點(diǎn)擊:" + transform.name);
}
public void OnPointerDown(PointerEventData eventData)
{
Debug.Log("鼠標(biāo)按下");
}
public void OnPointerEnter(PointerEventData eventData)
{
Debug.Log("鼠標(biāo)進(jìn)入");
}
}
注意:實(shí)現(xiàn)接口的腳本必須掛載在需要監(jiān)聽的UGUI物體上,并且掛載的UGUI物體的Raycast Target是需要勾選的,否則無法被檢測(cè)到。這些事件的觸發(fā)是基于UGUI的事件系統(tǒng)的,所以在使用的時(shí)候務(wù)必確保Unity項(xiàng)目的Hierarchy面板必須有一個(gè)物體掛載了EventSystem.
四、UGUI射線檢測(cè)
有時(shí)我們也需要在UGUI中進(jìn)行射線的檢測(cè)來獲取我們當(dāng)前點(diǎn)擊到的UGUI物體,這種方法也是基于UGUI事件系統(tǒng)而來的。具體實(shí)現(xiàn)代碼如下:
/// <summary>
/// 通過射線檢測(cè)獲得點(diǎn)擊的UI物體
/// </summary>
/// <param name="position">輸入的點(diǎn)</param>
/// <returns></returns>
public GameObject GetFirstPickGameObject(Vector2 position)
{
//創(chuàng)建事件對(duì)象
EventSystem eventSystem = EventSystem.current;
PointerEventData pointerEventData = new PointerEventData(eventSystem);
pointerEventData.position = position;
//射線檢測(cè)結(jié)果列表
List<RaycastResult> uiRaycastResultCache = new List<RaycastResult>();
//對(duì)UI元素進(jìn)行射線檢測(cè)
eventSystem.RaycastAll(pointerEventData, uiRaycastResultCache);
//判斷結(jié)果列表的數(shù)量并且輸出第一個(gè)檢測(cè)到的物體
if (uiRaycastResultCache.Count > 0)
{
return uiRaycastResultCache[0].gameObject;
}
return null;
}
private void Update()
{
//射線檢測(cè)UI
if (Input.GetMouseButtonDown(0))
{
GameObject go = GetFirstPickGameObject(Input.mousePosition);
if (go)
{
Debug.Log("檢測(cè)到點(diǎn)擊的物體:" + go.name);
}
}
}
注意:由于這種檢測(cè)方法也是基于Unity中的UGUI事件系統(tǒng)的所以也需要勾選被檢測(cè)UGUI物體的Raycast Target允許接受射線,并且在Hierarchy面板中也需要進(jìn)行EventSystem組件的掛載,這個(gè)函數(shù)是可以檢測(cè)到當(dāng)前面板中的所有接收射線的UI的,無需掛在在特定的物體上。
五、拓展
在游戲過程中我們經(jīng)常需要判斷鼠標(biāo)是否點(diǎn)擊在UI上,假如點(diǎn)擊在UI上的話我們就不需要讓人物移動(dòng)到我們點(diǎn)擊的目標(biāo)點(diǎn)了,以及我們?cè)谝恍┣闆r下需要進(jìn)行UI穿透等操作,這些都需要我們檢測(cè)是否點(diǎn)擊在UI上。我們可以使用以下代碼判斷當(dāng)前是否點(diǎn)擊在UI上。如下:
//檢測(cè)是否點(diǎn)擊到了UGUI物體
if (Input.GetMouseButtonDown(0))
{
if (EventSystem.current.IsPointerOverGameObject())
{
Debug.Log("當(dāng)前點(diǎn)擊在物體上了");
}
}
注意:這個(gè)也是基于UGUI事件系統(tǒng)的,需要開啟接收射線(Raycast Target),并且場(chǎng)景中有掛載EventSystem。無需掛在在特定物體上且只檢測(cè)UGUI對(duì)象。文章來源:http://www.zghlxwxcb.cn/news/detail-789866.html
六、總結(jié)
對(duì)于不同的情況我們可以選擇自己需要的以及最方便、高效的檢測(cè)方法,以上為個(gè)人學(xué)習(xí)記錄,如有不對(duì)的地方希望大家指正討論,一起學(xué)習(xí)進(jìn)步。文章來源地址http://www.zghlxwxcb.cn/news/detail-789866.html
到了這里,關(guān)于Unity射線以及相關(guān)點(diǎn)擊觸發(fā)事件的歸納的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!