文章目录

  • UnityEvent
    • 如何使用
    • 何时使用
  • 实现原理
  • 总结

UnityEvent

UnityEvent是Unity提供的用于处理事件的类,方便我们自定义事件。为了便于参数传递,Unity默认为我们提供了多个事件类,通过泛型不同实现事件响应参数不同。

如何使用

对于如何使用UnityEvent,官方文档给出了简单的使用案例,我们以一个泛型的版本为例。

UnityEvent代表使用此事件时可以添加一种类型,在调用Invoke方法时可以将此类型作为参数传入,事件响应端会接收到这个参数,以获取事件上下文。

如下图案例,我们自制的MyIntEvent继承UnityEvent,当事件触发调用Invoke方法时将int值5传入,此时Ping方法就会接收到事件响应时传入的5。

下面为Unity官方文档中提供的代码。

using UnityEngine;
using UnityEngine.Events;[System.Serializable]
public class MyIntEvent : UnityEvent<int>
{}public class ExampleClass : MonoBehaviour
{public MyIntEvent m_MyEvent;void Start(){if (m_MyEvent == null)m_MyEvent = new MyIntEvent();m_MyEvent.AddListener(Ping);}void Update(){if (Input.anyKeyDown && m_MyEvent != null){m_MyEvent.Invoke(5);}}void Ping(int i){Debug.Log("Ping" + i);}
}

何时使用

比如,当我们想要在屏幕上做多个按钮时,每个按钮的触发要有相应的区分,我们可以利用一个for循环来批量添加事件,并在事件触发时传入相应的 i(index索引),并使用同一个事件触发响应器。每个按钮被点击都会触发这个相同的事件响应器,响应器可以接收到参数index,以此来判断是哪个按钮被点击了。

实现原理

不带泛型的UnityEvent使用无参数方式调用Invoke方法。

以下为UnityEvent代码:

using System.Reflection;
using UnityEngine.Scripting;namespace UnityEngine.Events
{//// 摘要://     A zero argument persistent callback that can be saved with the Scene.public class UnityEvent : UnityEventBase{//// 摘要://     Constructor.[RequiredByNativeCode]public UnityEvent();//// 摘要://     Add a non persistent listener to the UnityEvent.//// 参数://   call://     Callback function.public void AddListener(UnityAction call);//// 摘要://     Invoke all registered callbacks (runtime and persistent).public void Invoke();//// 摘要://     Remove a non persistent listener from the UnityEvent.//// 参数://   call://     Callback function.public void RemoveListener(UnityAction call);protected override MethodInfo FindMethod_Impl(string name, object targetObj);}
}

带泛型的UnityEvent将泛型作为参数传递给Invoke方法。

以下为UnityEvent代码:

using System.Reflection;
using UnityEngine.Scripting;namespace UnityEngine.Events
{//// 摘要://     One argument version of UnityEvent.public abstract class UnityEvent<T0> : UnityEventBase{[RequiredByNativeCode]public UnityEvent();public void AddListener(UnityAction<T0> call);public void Invoke(T0 arg0);public void RemoveListener(UnityAction<T0> call);protected override MethodInfo FindMethod_Impl(string name, object targetObj);}
}

多个泛型的情况以此类推。

在AddListener和RemoveListener中都传入了参数UnityAction call,看这个名字就像个回调函数,我们看一下代码:

以下为UnityAction代码:

namespace UnityEngine.Events
{//// 摘要://     Zero argument delegate used by UnityEvents.public delegate void UnityAction();
}

果然,UnityAction其实就是个委托方法。

看过了UnityEvent和UnityAction,那么UnityEvent的基类都做了些什么呢?

以下为UnityEventBase代码:

using System;
using System.Reflection;
using UnityEngine.Scripting;namespace UnityEngine.Events
{//// 摘要://     Abstract base class for UnityEvents.[UsedByNativeCode]public abstract class UnityEventBase : ISerializationCallbackReceiver{protected UnityEventBase();//// 摘要://     Given an object, function name, and a list of argument types; find the method//     that matches.//// 参数://   obj://     Object to search for the method.////   functionName://     Function name to search for.////   argumentTypes://     Argument types for the function.public static MethodInfo GetValidMethodInfo(object obj, string functionName, Type[] argumentTypes);//// 摘要://     Get the number of registered persistent listeners.public int GetPersistentEventCount();//// 摘要://     Get the target method name of the listener at index index.//// 参数://   index://     Index of the listener to query.public string GetPersistentMethodName(int index);//// 摘要://     Get the target component of the listener at index index.//// 参数://   index://     Index of the listener to query.public Object GetPersistentTarget(int index);//// 摘要://     Remove all non-persisent (ie created from script) listeners from the event.public void RemoveAllListeners();//// 摘要://     Modify the execution state of a persistent listener.//// 参数://   index://     Index of the listener to query.////   state://     State to set.public void SetPersistentListenerState(int index, UnityEventCallState state);public override string ToString();protected void AddListener(object targetObj, MethodInfo method);protected abstract MethodInfo FindMethod_Impl(string name, object targetObj);protected void Invoke(object[] parameters);protected void RegisterPersistentListener(int index, object targetObj, MethodInfo method);protected void RemoveListener(object targetObj, MethodInfo method);protected bool ValidateRegistration(MethodInfo method, object targetObj, PersistentListenerMode mode);protected bool ValidateRegistration(MethodInfo method, object targetObj, PersistentListenerMode mode, Type argumentType);}
}

以下为ISerializationCallbackReceiver代码:

using UnityEngine.Scripting;namespace UnityEngine
{[RequiredByNativeCode]public interface ISerializationCallbackReceiver{//// 摘要://     Implement this method to receive a callback after Unity deserializes your object.[RequiredByNativeCode]void OnAfterDeserialize();//// 摘要://     Implement this method to receive a callback before Unity serializes your object.[RequiredByNativeCode]void OnBeforeSerialize();}
}

从UnityEventBase和ISerializationCallbackReceiver的内容可以看出,其实Unity提供的功能并不复杂,只是提供了一些工具方法和一些抽象方法,其最主要的工作还是帮助开发者完成了委托,以提高代码可读性。

总结

UnityEvent其实就是Unity帮我们提前写好的用于处理事件的功能,其作用是减去了自己写委托的过程,且提高了开发的规范性,方便代码整合。


更多内容请查看总目录【Unity】Unity学习笔记目录整理

【Unity】Unity开发进阶(六)UnityEvent使用与源码解析相关推荐

  1. iOS开发- 以图搜图功能实现 (源码+解析)

    以图搜图这个功能相当实用, 之前在实现这个功能的时候, 有一些笔记, 今天就整合成博文, 分享给大家. 这个demo主要实现的功能包括: 自定义拍照界面 图像识别 以图搜图 信息获取(通过识别出的图像 ...

  2. Unity Shader 阴影系列(2)--内置阴影源码解析

    Unity是如何生成阴影的 前言 相关的宏 投射阴影 v2f结构定义 V2F_SHADOW_CASTER UNITY_VERTEX_OUTPUT_STEREO 顶点函数:TRANSFER_SHADOW ...

  3. Unity中的UGUI源码解析之事件系统(9)-输入模块(下)

    Unity中的UGUI源码解析之事件系统(9)-输入模块(下) 接上一篇文章, 继续介绍输入模块. StandaloneInputModule类是上一篇文章介绍的抽象类PointerInputModu ...

  4. Unity中的UGUI源码解析之事件系统(6)-RayCaster(下)

    Unity中的UGUI源码解析之事件系统(6)-RayCaster(下) 接上一篇文章, 继续介绍投射器. GraphicRaycaster GraphicRaycaster继承于BaseRaycas ...

  5. unity urp内置lit材质源码解析(中)

    上一篇(https://blog.csdn.net/qq_30100043/article/details/125725934)解析了内置shader lit的主文件和input文件,接下来,我们将视 ...

  6. AD9364 测试平台开发——第六篇,SPI配置内容解析

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 AD9364 测试平台开发--第六篇,SPI配置内容解析 以下为个人的一些理解,有一些东西可能不一定理解透彻了,可能有错误,请指正和见 ...

  7. Unity中的UGUI源码解析之事件系统(2)-EventSystem组件

    Unity中的UGUI源码解析之事件系统(2)-EventSystem组件 今天介绍我们的第一个主角: EventSystem. EventSystem在整个事件系统中处于中心, 相当于事件系统的管理 ...

  8. Unity中的UGUI源码解析之事件系统(8)-输入模块(中)

    Unity中的UGUI源码解析之事件系统(8)-输入模块(中) 接上一篇文章, 继续介绍输入模块. Unity中主要处理的是指针事件, 也就是在2d平面上跟踪指针设备输入坐标的的事件, 这一类事件有鼠 ...

  9. Unity中的UGUI源码解析之图形对象(Graphic)(2)-ICanvasElement

    Unity中的UGUI源码解析之图形对象(Graphic)(2)-ICanvasElement 在上一篇文章中, 我们对整个Graphic部分做了概述, 这篇文章我们介绍ICanvasElement和 ...

最新文章

  1. 如何理解矩阵的特征向量和特征值?
  2. 将Windows下的InfluxDB、Grafana做成Windows服务
  3. php header调试,yii2打log
  4. 因主机名更改造成oracle控制台登录错误:ora-12545,ora-12541
  5. mysql 之后,装完MySQL之后的一些操作
  6. mysql 主主模式优缺点_mysql主主同步模式
  7. Flink Kafka consumer的消费策略配置
  8. 计算机程序的建立命令,数控车床编程指令 编程由一系列的指令组成
  9. Docker学习总结(51)——为什么不建议把数据库部署在 Docker 容器内的7大原因?
  10. 平面方程(Plane Equation)求解方法
  11. wnmp支持php文件,Windows下配置nginx+php(wnmp)
  12. C++解决程序一闪而退及清屏函数
  13. 今日学习在线编程题:弓形半径
  14. 爆火书单视频怎么制作?实用制作教程来了
  15. 使用CAD镜像和修剪命令绘制图形
  16. mysql8对系统的要求_linux-mysql8的安装步骤详解及需要注意的坑
  17. 新锐房地产销售管理系统(部分流程)技术解析(七) 销售管理_认筹管理
  18. 使用”网上办税厅”节约大厅办税时间的技巧
  19. 豆瓣电影TOP250爬虫及可视化分析笔记
  20. 数字城市天津防汛应急平台用户痛点分析【软件测试与工程】

热门文章

  1. vue中获取短信验证码功能IOS手机问题
  2. Mathorcup数学建模竞赛第六届-【妈妈杯】A题:水产养殖池塘综合研究(附一等奖获奖论文、lingo和matlab代码)
  3. 蓝松视频编辑SDK使用说明
  4. 团队的形成、协作与成长
  5. Green Plum 非并行备份恢复方案
  6. gevent学习介绍
  7. php getter,IntelliJ IDEA生成Getter和Setter方法
  8. Vue 引入腾讯地图 API 与实际应用保姆级分享
  9. MySQL千万数据方案调研,一不小心直接打挂我系统
  10. STS报错“HttpServlet cannot be resolved to a type”