当前位置: 首页 > news >正文

【Unity】搭建泛型事件框架,可广泛应用于中小型的游戏项目!!!

1.前言

1.1 普通的事件框架的缺陷

普通的事件框架,通常是创建一个EventHandler脚本文件,在里面定义大量的事件和对应的激活方法,然后再在对应的脚本当中编写监听方法,例如:

//EventHandler.cs
public static event Action OnSceneLoad;
public static void CallOnSceneLoad()
{
    OnSceneLoad?.Invoke();
}

然后,对应的脚本对事件进行订阅

//比如,这是某个脚本要监听这个事件
private void OnEnable()
{
    //订阅事件
    EventHandler.OnSceneLoad+=OnSceneLoad;
}
​
private void OnDisable()
{
    //取消订阅事件
    EventHandler.OnSceneLoad-=OnSceneLoad;
}
​
private void OnSceneLoad()
{
    //要执行的内容
}

这样无论是在代码中还是在Inspector窗口中,都十分的不直观,而且这样框架下,事件系统在后续的维护会很麻烦,因此,需要考虑到开发一套泛型开发框架,能够在Inspector窗口中快捷的修改事件订阅。

1.2 泛型事件框架的设计思路

对于泛型事件的框架,需要利用面向对象的思想来实现。

事件框架分为“事件广播者”和“事件监听者”。

  1. 事件广播者:负责广播事件,存储着事件广播的信息,需要一个泛型委托和一个广播函数组成,泛型委托用于存储订阅者,广播函数用于激活泛型委托

  2. 事件监听者:负责监听来自事件广播者的事件,需要确定监听的广播者,并定义Unity事件用于在接收到广播之后执行相应的方法

2.泛型事件框架的实现

下面是基本的泛型事件实现案例,可以根据个人的项目需求进行调整

2.1 创建事件广播者基类(SO)

这里可以将事件广播者继承ScriptableObject,但是不要写[CreateAssetMenu]标注,这个留给子类来写

using UnityEngine;
using UnityEngine.Events;
/// <summary>
/// 事件SO基类
/// </summary>
public class BaseEventSO<T> : ScriptableObject
{
    [Header("事件描述")]
    [TextArea]
    public string description;
​
    public UnityAction<T> OnEventRaised;
​
    public string lastSender; //最后一个发送广播的对象(可选)
    
    /// <summary>
    /// 广播事件
    /// </summary>
    /// <param name="value">要广播的值</param>
    /// <param name="sender">广播发送者(可选)</param>
    public void RaiseEvent(T value,object sender)
    {
        OnEventRaised?.Invoke(value);
        lastSender = sender.ToString();
    }
}

2.2 创建事件监听者基类

事件监听者默认继承MonoBehavior即可,需要写上要监听的事件广播者,同时定义一个UnityEvent类型用于绑定接收到事件之后需要执行的函数

using System;
using UnityEngine;
using UnityEngine.Events;
/// <summary>
/// 事件监听器基类
/// </summary>
public class BaseEventListener<T> : MonoBehaviour
{
    /// <summary>
    /// 要监听的事件广播者
    /// </summary>
    public BaseEventSO<T> eventSO;
    
    /// <summary>
    /// 当eventSO中的事件被激活的之后,
    ///  执行response中订阅的方法
    /// </summary>
    public UnityEvent<T> response; 
    
    private void OnEnable()
    {
        if (eventSO != null)
        {
            //订阅事件
            eventSO.OnEventRaised += OnEventRaised;
        }
    }
​
    private void OnDisable()
    {
        if (eventSO != null)
        {
            //注销事件
            eventSO.OnEventRaised -= OnEventRaised;
        }
    }
    
    /// <summary>
    /// 接收到事件广播
    /// </summary>
    /// <param name="value"></param>
    private void OnEventRaised(T value)
    {
        response.Invoke(value); //执行接收到事件后要执行的函数
    }
}

2.3 创建事件广播者的子类(SO)

这里这个子类就用来广播来自object类型的数据,继承其事件广播者的基类

using UnityEngine;
​
[CreateAssetMenu(fileName = "ObjectEventSO",menuName = "Events/ObjectEventSO")]
public class ObjectEventSO : BaseEventSO<object>
{
   
}

2.4 创建事件监听者的子类

继承事件监听者的基类

using UnityEngine;
​
public class ObjectEventListener : BaseEventListener<object>
{
    
}

2.5 创建事件广播者的SO文件

有了上述的框架基础之后,我们就可以实现这样的可视化操作:

  1. 在project窗口中创建多个事件的SO文件,以用于定义多个不同的事件

  2. 在指定对象的Inpector窗口中添加多个事件监听者,通过可视化的方式管理要监听的事件(引用SO文件)以及事件激活后要执行的方法。

2.6 订阅事件

将事件监听者子类的脚本挂载到场景中要监听事件的对象上,同时,根据自身项目需求,给事件监听者挂载要监听的事件广播者,并为该事件订阅单个或多个方法。

由于事件监听者已经独立化,所以你可以为一个对象添加多个事件监听者脚本,以方便监听多个事件。

2.7 广播事件

在需要发送广播的对象的脚本中,定义变量来引用指定的事件广播者(引用事件广播者的SO文件),然后在合适的时机广播事件即可。

相关文章:

  • STM32启动过程概述
  • TCP/IP 四层模型数据的封装过程
  • kkFileView二开之pdf转图片接口
  • 你如何利用SIMD(如SSE/AVX)优化图像处理的性能?
  • 数据结构 二叉树
  • 超纯水设备的智能化控制系统为用户带来安全简便的操作体验
  • AWS SES 邮件服务退信/投诉处理与最佳实践指南
  • 记一次MySQL故障解决
  • Unity入门3 添加碰撞体
  • 打造高效狼性团队的实践指南
  • 将错误消息输出到标准错误流:Rust中的最佳实践
  • 掌控系统性能的利器:自动化系统性能监控工具
  • 使用c风格和c++风格逐行读取文件
  • 力扣19题——删除链表的倒数第 N 个结点
  • ping使用的协议,ping使用的协议是
  • linux系统测试网络pps、带宽和延时(方案来源于阿里云)
  • 解锁建造者模式:Java 编程中的对象构建秘籍
  • IT行业方向细分,如何做到专家水平——4.网络安全(Cybersecurity)
  • 进化强化学习
  • 计算机毕业设计PySpark+PyFlink+Hive地震预测系统 地震数据分析可视化 地震爬虫 大数据毕业设计 Hadoop 机器学习 深度学习
  • 首次带人形机器人走科技节红毯,傅利叶顾捷:机器人行业没包袱,很多事都能从零开始
  • 上海国际珠宝时尚功能区未来三年如何建设?六大行动将开展
  • 中央提级巡视后,昆明厅官郭子贞接受审查调查
  • 马上评|文玩字画竞拍轻松赚差价?严防这类新型传销
  • 长期吃太饱,身体会发生什么变化?
  • 共建医学人工智能高地,上海卫健委与徐汇区将在这些方面合作