event、Event 和 UnityEvent
event和delegate
event是C#的保留關鍵字,是委託的一種封裝。委託(delegate)可以理解爲C或C++中的函數指針,可以保存具有特定返回類型和參數列表的方法的引用,並直接作爲函數的參數間接調用目標函數。事件(event)則可以理解爲基於委託的一個函數指針棧,可以包括來自不同類型的不同對象的不同方法。典型的委託與事件的使用如下:
public delegate void PrintName(string name);//聲明瞭一個委託類型
public class DelegateExample : MonoBehaviour
{
public event PrintName printName;//將委託類型作爲事件實例化
void print(string name, PrintName method)//將委託類型作爲函數參數的示例
{
method(name);
}
private void Start()
{
printName += PrintEnglishName;//使事件監聽一個函數
printName += PrintChineseName;//使事件監聽另一個函數
printName("UPiracy");//調用事件
print("UPiracy",printName);//通過函數調用事件
}
private void PrintEnglishName(string name)
{
Debug.LogFormat("My name is {0}.", name);
}
private void PrintChineseName(string name)
{
Debug.LogFormat("我的名字是{0}.", name);
}
}
Event
Event是屬於UnityEngine命名空間的,它和event完全無關,是用於處理輸入事件的類型,它主要負責Unity中的鍵盤、按鍵、鼠標輸入以及GUI事件。
在生命週期表中,我們可以看到OnGUI事件在一幀中可以被調用很多次。在每一次鍵盤、鼠標、按鍵以及GUI輸入發生時,OnGUI都會被調用一次,用於按批處理同一幀中多個GUI輸入事件的,這些事件使用一個隊列存儲在Event類型中,在生命週期的每次OnGUI中,Event可以獲取當前OnGUI週期正在處理的GUI信息。
public static Event Event.current;
current用於獲取當前OnGUI週期正在處理的GUI信息。
批次處理過程中,Unity將輸入信息分成了幾個不同的種類,每個OnGUI循環只會處理其中的一類,如果我們想針對性的對某類輸入進行自定義,就應該在OnGUI的開頭對其進行判斷:
public bool Event.isMouse; public bool Event.isKey;
表示當前批次處理了鼠標信息還是鍵盤信息。
public EventType Event.type;
public enum EventType { MouseDown,MouseUp,MouseDrag,MouseMove, KeyDown,KeyUp, ScrollWheel, ContextClick, Repaint, Layout, }
用於更精細化的分別當前批次處理信息的類型。
public int Event.button;
當鼠標按下時,保存按下的鍵位,0對應左鍵、1對應右鍵、2對應中鍵。
public int Event.clickCount;
當鼠標按下時,保存當前連擊的次數。
public Vector2 Event.delta;
返回鼠標座標在上一次處理到這次處理的偏移量。
public Vector2 Event.mousePosition;
返回當前鼠標指針的屏幕座標。
public PointerType Event.pointerType;
public enum PointerType { Mouse,Touch,Pen }
返回當前鼠標事件的來源是鼠標、觸摸屏還是觸摸筆。
public bool Event.shift; public bool Event.command; public bool Event.control; public bool Event.alt; public bool Event.capsLock;
依次返回是否按下了Shift鍵、Command/Windows鍵、Ctrl鍵、Alt鍵和大小鎖定是否開啓。
public bool Event.numeric;
返回按下的是否是小鍵盤上的按鍵。
public char Event.character; public KeyCode Event.keyCode;
分別輸出當前按下按鍵的字符或當前按下按鍵的鍵值。
實例:通過Event實現玩家自定義按鍵的功能。
public class CustomKey : MonoBehaviour
{
private GameManager gm;
private void Start()
{
gm = GetComponent<GameManager>();
}
private void OnGUI()
{
Event e = Event.current;
if(!e.isKey) return;
else
{
gm.SetKey(e.keyCode,e.character);
Destory(this);
}
}
}
UnityEvent
UnityEvent保存在UnityEngine.Events命名空間中。
UnityEvent對標C#中的關鍵字event,是event的一個封裝,用於將event暴露到Inspector面板。
在UnityEvent中監聽的函數必須是MonoBehaviour或ScriptableObject中的函數,可以是靜態函數也可以是實例函數。
聲明一個UnityEvent的格式如下:
public class UnityEventExample : MonoBehaviour
{
[SerializeField]
private UnityEvent<string> OnEnter;
[SerializeField]
private UnityEvent OnClick;
}
注:UnityEvent必須被註明[System.Serializable]才能被暴露到Inspector面板。
無參數的類型可以直接使用
UnityEvent可以構造具有任意數量任意類型參數的事件,但只能構造返回類型爲void的事件。
對應event中的"+=“和”-="操作,UnityEvent具有三個方法:
public void UnityEvent.Invoke();
public void UnityEvent.AddListener(Events.UnityAction call);
public void UnityEvent.RemoveListener(Events.UnityAction call);
Invoke用於調用UnityEvent中的所有方法。
UnityEvent在UI中最常出現,我們以Unity UI中的Button組件爲例,講解在Inspector面板中使用UnityEvent的方式:
點擊”+”號可以創建一個監聽項目,效果如圖所示:
左上角:觸發限定時間。可以選擇None、Editor And Runtime或者Runtime Only。顧名思義,None表示這個監聽項目不會觸發,Editor And Runtime表示這個監聽項目可以在編輯器下被觸發,Runtime Only表示這個監聽項目只在遊戲模式下被觸發。
左下角:觸發物體。將一個GameObject拖動到這裏以監聽其上的組件中的函數和屬性,將一個Prefab拖動到這裏以監聽其上的組件中的靜態函數或屬性,將一個ScriptableObject拖動到這裏以監聽其中的函數和屬性。
右上角:觸發的方法或修改的屬性。在觸發物體上找到想要的組件,然後在組件中找到想觸發的方法或想修改的屬性。只有符合監聽條件(參數列表對應)且被聲明爲public的屬性或方法才能被找到。
右下角:參數。作爲方法的參數,或者修改屬性的目標常量。
Unity中的EventTrigger組件可以快捷的給物體添加一段常見的UnityEvent: