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: