UnityVR--EventManager--事件中心2

news2024/12/27 12:10:09

目录

前言

事件中心的结构

EventManager事件管理器

EventType事件类型

EventListener监听及回调

EventDataBase回调时需要传递的参数

总结


前言

  上一篇(事件中心1)中,简单解释了委托、事件、监听者,是用于管理项目运行过程中突发情况的产生和相应处理方法的手段。比如在仿真实验项目中,一旦按下急停按钮,或者传感器检测到过载等,这些情况都会带来一系列的后续,如电路短路、系统报警等。因此,每一个有一定规模的项目,需要建立一个事件管理中心,来管理和调用情况变化时需要执行的方法。否则不断地需要在Update()、FixedUpdate()中去if……else……非常消耗资源。

事件中心的结构

  事件中心要解决的问题有3个:

  1. 有哪些事件需要被关注?2. 这些事件与谁有关?3. 事件发生后要做出什么应对?

  这三个问题相对应的就是1. 事件的类型;2. 事件的监听者;3. 回调(委托)

   这里的键盘输入,使用到了新版的输入系统InputSystem,详细设置需要参照新版InputSystem。

EventManager事件管理器

  EventManager是最主要的事件管理文档,继承单例(Single,详见单例)在这里要定义一些关于事件的添加、发送、删除等方法。基本结构如下:

   

public delegate void EventCallBack(EventDataBase database);
//定义一个委托,用于管理回调方法
public class EventManager : Single<EventManager>  //继承单例
{
    Dictionary<EventType, List<EventListener>> eventListener = new Dictionary<EventType, List<EventListener>>();  //定义存储事件的字典

    //添加事件
    public void AddEvent(EventType type,object listener,EventCallBack callBack)
    {//事件类型,监听者(可以是任何类型),回调(委托)
        if (listener == null)
            return;
        IfEventType(type);//判断字典里是否有该事件
        eventListener[type].Add(new EventListener(listener, callBack)); //添加监听者到字典
    }
    private void IfEventType(EventType eventType)
    {//判断字典里是否有该事件
        if (!eventListener.ContainsKey(eventType))//如果字典没找到,就添加一个
            eventListener.Add(eventType, new List<EventListener>());
    }

    //发送事件,通知所有监听者
    public void SendEvent(EventType type, EventDataBase database)
    {
        if(eventListener.ContainsKey(type))//判断一下字典是否有该事件
        {
            List<EventListener> listeners = eventListener[type];//一旦事件对应上字典中的类型
            foreach (EventListener listener in listeners)
            {
                listener.CallBack(database);  //将该事件所对应的监听都回调一下,并且传参数
            }
        }
    }

    //删除事件的指定接收者listener
    public void RemoveEventListener(EventType type, object listener)
    {
        List<EventListener> listeners;
        if(eventListener.TryGetValue(type,out listeners))
        {//尝试获取type类型,如果获取到了,就写到listenerList里
            for(int i=0; i<listeners.Count;i++)
            {
                if (listeners[i] == listener)
                {
                    listeners.RemoveAt(i);
                    return;
                }
            }
        }
    }

    //删除事件,也会把这个事件的所有监听者都取消
    public void RemoveEvent(EventType type)
    {
        if (eventListener.ContainsKey(type))
        {
            eventListener.Remove(type);
        }
    }

    //清空所有事件
    public void Clear()
    {
        eventListener.Clear();
    }
}

  在这段代码中使用到的EventDataBase、EventType、EventListener等类型,下面继续定义、说明:

EventType事件类型

  使用一个枚举类型,列举所有需要关注的事件名称,这里仅仅举例了几个事件,需要其他事件还可以逐步加入完善:

public enum EventType 
{
    OnMouseInput=1001,     //鼠标点击事件
    OnKeyboardInput=1002,  //键盘输入事件
    OnPlayerFire = 1003,   //发射子弹事件
    OnPlayerMove=1004      //玩家移动事件
}

EventListener监听及回调

  在EventListener类中定义了listener、callBack两个变量,并且需要一个带参构造,以便于调用。

public class EventListener 
{//监听者,和它相应的回调
    object listener;//监听可能为任何事件,所以用最大的类型Object
    EventCallBack callBack;

    public EventListener(object listener, EventCallBack callBack)
    {//带参构造
        Listener = listener;
        CallBack = callBack;
    }
    //封装
    public object Listener { get;}
    public EventCallBack CallBack { get;}
}

EventDataBase回调时需要传递的参数

  不同的回调函数需要传递的参数类型自然不同,因此设置一个传参数据的父类EventDataBase,以便于在管理器EventManager中统一调用。之后在实例使用中使用的实际参数类型只要都继承这个父类,向上转型即可。

//管理委托要传入的参数
public class EventDataBase
{//父类
    
}

public class EventDataPlayerMove:EventDataBase
{//在主角移动时,需要传入移动的坐标(XZ轴)
    public Vector2 position;
}

public class EventDataMouseInput:EventDataBase
{//鼠标点击拖拽时,鼠标状态的传递
    private EMouseInputKey key;      //鼠标被按下的按键,从枚举中获取
    private EMouseInputState state;  //鼠标的状态,从枚举中获取
    private Vector2 mousePosition;   //鼠标的位置传递(XY转XZ轴)
}

public enum EMouseInputKey
{//鼠标被按下的按键,左、中、右,从枚举中获取
    Left, Mid, Right,
}
public enum EMouseInputState
{//鼠标的状态:按下、长按、抬起
    Down,Stay,Up
}

总结

   1. 梳理一下事件中心定义的几个类、参数的关系:

   

  2. 这只是一个定义事件的参考案例,在实际项目中还有更多的事件情况需要考虑;

  3. 如何使用上面定义的这些方法,实现事件的注册、发送、回调等,请参照下一篇,实现鼠标拖拽、角色移动、发射子弹等几个功能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/596760.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深度学习进阶篇[9]:对抗生成网络GANs综述、代表变体模型、训练策略、GAN在计算机视觉应用和常见数据集介绍,以及前沿问题解决

【深度学习入门到进阶】必看系列&#xff0c;含激活函数、优化策略、损失函数、模型调优、归一化算法、卷积模型、序列模型、预训练模型、对抗神经网络等 专栏详细介绍&#xff1a;【深度学习入门到进阶】必看系列&#xff0c;含激活函数、优化策略、损失函数、模型调优、归一化…

多线程-*同步代码块*解决两种线程创建方式的线程安全问题

线程安全问题及解决 当我们使用多个线程访问同一资源&#xff08;可以是同一个变量、同一个文件、同一条记录等&#xff09;的时候&#xff0c;若多个线程只有读操作&#xff0c;那么不会发生线程安全问题。但是多个线程中对资源有读和写的操作。就容易出现线程安全问题。 举…

PyTorch 深度学习 || 专题三:PyTorch 数据的准备

PyTorch 数据的准备 1. 生成数据的准备工作 import torch import torch.utils.data as Data#准备建模数据 x torch.unsqueeze(torch.linspace(-1, 1, 500), dim1) # 生成列向量 y x.pow(3) # yx^3#设置超参数 batch_size 15 # 分块大小 torch.manual_seed(10) # 设置种子点…

国自然发文:这种行为将永久取消基金申请资格

函评阶段这些行为被基金委禁止 国家自然科学基金委重拳出击打击"打招呼"现象,出台《国家自然科学基金项目评审请托行为禁止清单》&#xff0c;禁止科研人员、依托单位、评审专家和基金委工作人员24种违规行为。 主要内容如下: 一、科研人员禁止清单(7项) 主要包括…

初阶数据结构——二叉树

目录 树的概念及结构树的概念树的相关概念树的表示树在实际中的运用 二叉树概念及结构特殊的二叉树二叉树的性质二叉树的存储结构 二叉树的顺序结构及实现二叉树的顺序结构堆的概念及结构堆的实现堆的结构&#xff1a;初始化堆&#xff1a;销毁堆&#xff1a;插入数据&#xff…

通过maven配置不同的开发环境

前言 项目有开发、测试、生产至少有这三个环境&#xff0c; 所需要的配置信息肯定不一样&#xff0c; 比如需要开发环境的时候&#xff0c;注解掉测试和生产的配置信息&#xff0c;打开开发的配置信息。 后来工作接触到新项目&#xff0c;发现是通过maven来控制加载不同的配置…

第55讲:Python函数形参、实参的语法格式汇总以及应用小案例

文章目录 1.Python函数中各种参数的汇总1.1.常规参数1.2.参数设置默认值1.3.强制传参时使用关键字传参1.4.个数可变的形参1.5.将序列中的每个元素都转换为位置实参1.6.将字典中的每个元素都转换为关键字实参 2.小案例练习Python中的各种函数参数2.1.案例一2.2.案例二 1.Python函…

React-reacte-app项目实现antD按需加载(2023)

出现的问题&#xff1a; 项目打包后&#xff0c;由于引入了antD&#xff0c;所以打包后的mani.js体积会非常大。相当于引入了全部的antD的代码。所以可以做一个优化&#xff1a;通过script标签引入antD&#xff0c;将其挂载在window上。使用antD组件的使用&#xff0c;直接从w…

2.矢量分析

目录 一.标量函数和矢量函数 二.矢端曲线 三.矢量函数导数和微分 1.导数 2.导数的几何意义 3.微分 4.矢量导数性质 5.例题 四.矢量导数的应用 1.几何应用 1.曲线的切线和法平面 2.曲面的法线和法平面 2.物理应用 3.两大典型问题 五.矢量函数的积分 如果第一章我…

WOT全球技术创新大会开幕倒计时——好内容才是永远的底气

距离6月16日-17日召开的WOT全球技术创新大会还有半个月时间&#xff0c;所有讲师、议题均已就位。本届WOT不仅囊括2023年最火的技术——AIGC、大模型、大算力&#xff0c;也有被技术人永恒关注的热点话题——多云实践、业务架构演进、效能提升。 筹备数月之久&#xff0c;50来…

Intel® 以太网800 系列网络适配器 – DPDK上的性能演进

1. 介绍 Intel以太网800系列网络适配器提供卓越的性能&#xff0c;以满足各种工作负载的要求。800系列提供了数据包分类和排序优化、硬件增强的定时能力以及完全可编程的流水线。Intel的以太网产品组合始终提供可靠的体验和经过验证的互操作性。 在DPDK中&#xff0c;ICE轮询模…

CDN控制平台操作指引之账号注册及添加域名

一、注册账户及登录 &#xff08;一&#xff09;请确认您已经注册了火伞云账号并完成账号实名认证。如果未注册&#xff0c;请先完成账号注册和实名认证。 &#xff08;二&#xff09;登录火伞云融合CDN管理平台。 二、添加加速域名 使用火伞云融合CDN加速指定网站&#xff…

NodeJs之Ajax技术

1. 初识Ajax ./public/Ajax.html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content&qu…

ArcGIS Pro地图和场景

目录 1 地图和场景 1.1 地图 1.2 场景 2 图层 2.1 图层类型 2.1.1 要素图层&#xff08;Feature layers&#xff09; 2.1.2 栅格图层&#xff08;Raster layers&#xff09; 2.1.3 场景图层&#xff08;Scene layers&#xff09; 2.1.4 服务图层&#xff08;Service la…

机器视觉怎么对陶瓷板的外观尺寸进行自动检测?

随着工业自动化的不断发展&#xff0c;机器视觉技术在制造业中的应用越来越广泛。在陶瓷板行业中&#xff0c;机器视觉技术可以用于自动检测陶瓷板的外观尺寸&#xff0c;提高生产效率和产品质量。下面我们来介绍机器视觉如何对陶瓷板的外观尺寸进行自动检测。 一、检测原理 …

第2关:socket编程

第2关&#xff1a;socket编程 任务描述相关知识1、Socket2、socket函数3、bind函数4、listen、connetct函数5、accept函数6、read、write函数7、close、shutdown函数8、三次握手9、数据传输10、四次挥手 编程要求及注意事项测试说明参考代码 任务描述 本关任务&#xff1a; 编…

轻松掌握,板对板连接器选型指南

一、什么是板对板连接器&#xff1f; 板对板连接器(简称BTB)&#xff0c;是精密电路中电源和信号耦合连接必不可少的器件。随着产品复杂度和电路设计规模的不断提升&#xff0c;板对板连接器也沿着市场需求向着高速率&#xff0c;高功率密度&#xff0c;轻薄化几个方向发展。 …

chatgpt赋能python:为什么Python不适合做SEO?——解析

为什么Python不适合做SEO&#xff1f;——解析 Python作为一种非常方便的编程语言&#xff0c;在数据处理、人工智能等方面有着广泛的应用。然而&#xff0c;在SEO领域&#xff0c;Python似乎并不受欢迎。本文将从Python不适用于SEO的几个方面做出详细的介绍&#xff0c;并为读…

WPF .Net6中使用Prism

.NET 6 是微软长期支持&#xff0c;并在移动、桌面、IoT 和云应用之间统一了 SDK、基础库和运行时。 Prism为程序设计提供指导,旨在帮助用户更加容易的设计和构建丰富、灵活、易于维护WPF桌面应用程序。Prism使用设计模式&#xff08;如MVVM,复合视图,事件聚合器&#xff09;…

02 【el和data的两种写法 MVVM模型】

02 【el和data的两种写法 MVVM模型】 1.el和data的两种写法 el有2种写法 创建Vue实例对象的时候配置el属性 先创建Vue实例&#xff0c;随后再通过vm.$mount(‘#root’)指定el的值 data有2种写法 对象式&#xff1a;data&#xff1a; { }函数式&#xff1a;data() { retur…