2017年10月31日 星期二

Unity內用Pointer方式來偵測非互動型的UGUI

在UGUI內像是Button或Slidert等這種可以讓使用者操控的介面,都會有Interactable這個設定,同時也可以使用下列的程式碼偵測到點擊:

if (Input.GetMouseButtonDown(0))
{
    if (EventSystem.current.currentSelectedGameObject != null)
    {
        Debug.Log(EventSystem.current.currentSelectedGameObject);
    }
}
但是像Image或Rawimage等這種非互動類型的介面,無法用上述的方式偵測到,但偏偏有需要的話該怎麼辦?

首先想到的是從Raycast Target這個設定著手,但意外地我無法使用2DRaycast等方式去偵測(應該是要可以才對,是我人品太糟?):

然後發現了Pointer和其相關方式,因此使用了一下,效果就和Button的OnClick一樣:



使用EventTrigger有很多種觸發方式,相當好用:

最後,如果即時創造UGUI,並且需要即時賦予點擊時回傳的參數時,上面那些事先設定的方式就沒法用了,因此查詢一下各種作法後,發現下面這種方式比較適合我。

首先在即時創造的UGUI上,有沒有EventTrigger這個Comoponent都可以,有的話也不要事先添加任何UnityEvent:

然後撰寫下面程式,並將Script附加在該UGUI物件下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ImageController : MonoBehaviour, IPointerDownHandler, IPointerUpHandler {

    void Start ()
    {

    }

    void Update ()
    {

    }

    public void OnPointerDown(PointerEventData eventData)
    {
        Debug.Log("Point down = " + this.name);
    }

    public void OnPointerUp(PointerEventData eventData)
    {
        Debug.Log("Point up = " + this.name);
    }
}
這樣就等於當點擊這個UGUI時,程式會回傳該UGUI的名稱,或是其他想回傳的相對應資料了。

Unity內增加UGUI的Button Event方式

一般要來用UGUI的Button,只要事先在Editor內設定好就可以了,例如像這樣:

那為什麼要特別講這個?因為當在做Runtime產生的清單GUI之類時,就需要將Runtime產生的Button即時賦予特定的參數,好讓OnClick的UnityEvent可以在點擊時傳回這個特定的參數。

本來有想嘗試使用預設定義的UnityEvent,例如像是GameObject.name這種看起來可以在點擊時,便自動傳回該UGUI名稱的方式:

但是查詢網路過後,發現使用方式對我來講有些複雜,所以就想說看能不能直接更改已創造的UnityEvent所指定回傳的參數;結果反而發現直接在Button上增加一個全新的UnityEvent還比較快和方便,這樣就可以在創造即時UGUI時,依照需求來即時賦予相對應的UnityEvent了。

首先即時創造出來的Button部分,並不需要事先在OnClick處設定UnityEvent,因為是要靠程式碼來即時創造並附加上去:

然後假設我即時創造了一個GameObject名為"Action"的Button,並且我需要在點擊這個Button時,讓程式回傳給我這個Button名稱:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class ButtonController : MonoBehaviour {

    Button ActionButton;

    void Start ()
    {
        ActionButton = GameObject.Find("Action").GetComponent<Button>();
        ActionButton.onClick.AddListener(delegate { GetButton(GameObject.Find("Action").name); });
    }

    void Update ()
    {

    }

    public void GetButton(string tempData)
    {
        Debug.Log(tempData);
    }
}
這樣就等於是在Inspector處設定了這個UnityEvent:

可以隨著即時創造的UGUI來進行即時賦予參數了,程式碼也簡單方便。