【Unity设计模式】观察者模式,发布订阅模式,事件总线

news2024/10/7 4:36:15

在这里插入图片描述


前言

最近在学习Unity游戏设计模式,看到两本比较适合入门的书,一本是unity官方的 《Level up your programming with game programming patterns》 ,另一本是 《游戏编程模式》

这两本书介绍了大部分会使用到的设计模式,因此很值得学习

本专栏暂时先记录一些教程部分,深入阅读后续再更新


文章目录

  • 前言
  • 使用观察者模式
  • 委托和事件
  • 发布订阅模式
  • 事件总线


【Unity】观察者模式、中介者模式和事件总线

建议看看这个视频,相信你会对代码实现有个明显的了解

使用观察者模式

在游戏运行中发生了各种各样的事件,例如玩家消灭敌人,玩家受伤,或是收集到道具。不同的GameObject之间想要在发生事件后进行某类交互,此时我们需要在事件发生后去通知那些想要交互的对象。

为了避免耦合,我们肯定要避免不同对象间的复杂引用关系。同时要保证事件能够通知到,一种好方法是使用观察者模式:

在这里插入图片描述

观察者模式就好比向许多观众发送广播的无线电台,电台本身不需要知道有谁在收听,只需要进行正常的广播即可。而收听了电台的听众们自然就会接受到广播,且不同听众之间不知道其他听众的存在,在他们看来自己与电台是一对一的关系。

我们将正在广播的对象称为Subject主题,将监听的对象称为Observer观察者或订阅者

通过观察模式,可以将主题和观察者解耦,主题发布事件时不需要关心有没有观察者,也不关心他们在收到事件后会干嘛。而观察者虽然与主题耦合,但是与其他观察者之间不相干。


委托和事件

在学习C#的时候,我们学习了委托和事件,其实委托和事件就是一种观察者模式,想象观察者们将自己的方法注册到主题的委托当中,当主题触发委托后就会广播这些事件。

并且使用委托,我们对方法的注册更加灵活,我们可以当GameObject(观察者们)在OnEnable的时候向主题进行事件注册,而在OnDisable的时候向主题取消注册的事件。

发布订阅模式

发布定义模式是观察者模式的升级版:

在这里插入图片描述

同样的例子,假设这个电台自身完全不生产任何事件。现在有一个广告商要向电台投放广告,那么电台在接收到广告商投放的广告之后会将广告分发给订阅的观察者们,这些观察者在接到广告后选择如何行动。

此时的主题更像是一个中介,它接受来自Publisher发布者 的消息,并将其分发给订阅了该主题的订阅者。当然发布者也不只有广告商,也会有主播发布事件,或者听众来电发布事件。但是订阅者们并不关心是谁发送了,发布者们也不关心谁会收到,他们只需要完成自己的事情,由主题作为中介进行交互即可。这样观察者和发布者本身没有耦合,却能实现不同组件之间的交互。

我们将此时的主题称为事件频道Event Channel, 我们当然可以定义多个频道,比如有人只订阅体育频道,有人订阅音乐频道,有人两个都订阅了。发布者只需完成发布到他们所订阅的频道即可,而观察者只需接受来自订阅频道的事件。

如果所有的事件全部都塞进了一个事件频道,我们将这种模式称为事件总线Event Bus 模式

事件总线

【Unity教程搬运】事件总线(Event Bus)

事件总线模式其实就是对发布订阅的简单抽象,我们看发布订阅模式其实分为三步:

1.订阅者订阅事件频道
2.发布者向事件频道发布消息
3.订阅者收到事件频道广播的订阅消息(触发订阅事件)

而事件总线模式则将整个步骤抽象成了两步:
1.订阅者向事件总线注册事件
2.发布者直接触发事件总线中的事件列表

也就是说,相比于观察订阅模式,事件总线维护的并不是观察者的列表,而是观察者需要触发的事件本身。那么发布者也不需要让事件频道分发消息了,直接触发对应的事件列表即可。

在这里插入图片描述

因此事件总线直接提供了事件的注册方法,事件撤销方法和事件总线的触发方法。通过订阅者本身的事件驱动

所以本质上看事件总线中维护的事件列表其实就是不同的泛型委托吧

好处是我们可以把事件总线设计成一个静态的工具类(注意应用时考虑是否使用单例模式或DDOL)

当然,我们只需对事件总线触发代码进行优化就可以改变全局的事件触发状态,例如我们可能并不想一次性触发所有事件,那么也可以在总线中定义一个命令缓冲区,让所有事件一个一个地触发。(或者将多次触发的同个事件合并只触发一次)

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

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

相关文章

Redis小对象压缩

小对象压缩存储 如果Redis内部管理的集合数据结构很小,他会使用紧凑存储形式压缩存储。 Redis的ziplist是一个紧凑的字节数组结构,如下图所示,每个元素之间都是紧挨着的。 如果他存储的是hash结构,那么key和value会作为两个ent…

UE5 C++ 跑酷游戏练习 Part1

一.修改第三人称模板的 Charactor 1.随鼠标将四处看的功能的输入注释掉。 void ARunGANCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) {// Set up action bindingsif (UEnhancedInputComponent* EnhancedInputComponent CastChecked&…

微服务开发与实战Day11 - 微服务面试篇

一、分布式事务 1. CAP定理 1998年,加州大学的计算机科学及Eric Brewer提出,分布式系统有三个指标: Consistency(一致性)Availability(可用性)Partition tolerance(分区容错性&am…

“Git之道:掌握常用命令,轻松管理代码“

目录 1. 初始化和配置 2. 提交和更新 3. 分支和合并 4. 查看和比较 5. 远程仓库 6. 文件操作命令 1. 初始化和配置 git init:在当前目录初始化一个新的Git仓库git config:配置Git的全局或局部选项git clone:从远程仓库克隆一个本地副本…

MySQL基础——函数和约束

目录 1函数 1.1字符串函数 1.2数值函数 1.3日期函数 1.4流程函数 2约束 2.1约束概述和演示 2.2外键约束(表连接键) 1函数 函数是指一段可以直接被另一段程序调用的程序或代码。 1.1字符串函数 MySQL中内置了很多字符串函数,常用的…

【C语言习题】31.冒泡排序

文章目录 作业标题作业内容2.解题思路3.具体代码 作业标题 冒泡排序 作业内容 实现一个对整形数组的冒泡排序 2.解题思路 先了解一下冒泡排序: 两两相邻的元素进行比较,如果前面元素大于后面元素就交换两个元素的位置,最终的结果是最大的…

三星S20以上手机中的动态相片及其分解

三星S20以后的相机,相机拍出来的图片,用三星手机自带的“相册”打开之后,还会有“查看动态照片”的选项,点击之后就能查看拍照片时前后2秒左右的视频! 不知道这个功能是不是三星独有的。 这样得到的图片非常大。因为…

一个简单的信号发射电路的构建

在基本的信号发射电路中,线圈(电感器)和电阻的组合可以产生振荡信号,而天线(通常通过线圈)用于发射信号。 LC振荡电路: **线圈(L1)和电容器(C)**串…

MySQL 基本语法讲解及示例(上)

第一节:MySQL的基本操作 1. 创建数据库 在 MySQL 中,创建数据库的步骤如下: 命令行操作 打开 MySQL 命令行客户端或连接到 MySQL 服务器。 输入以下命令创建一个数据库: CREATE DATABASE database_name;例如,创建一…

Locust框架

Locust 简介:是一个Python的第三方库,专门用来进行性能并发测试 Locust特点: 基于Python的开源负载测试工具支持多种操作系统支持二次开发能够模拟更多用户基于协程(微线程)的并发 Jmeter与Locust对比 Locust安装 …

街道网格宣传稿件投稿我知道了好方法

作为街道信息宣传员,我的日常是将街道的每一项重要活动、每一份温暖故事编织成文字,传递给公众。这份工作既充满挑战又极具意义,但在最初,我却在这份看似简单的任务上屡屡受阻。那时,我的投稿方式单一且传统——依赖电子邮件,将稿件发送至各大媒体的投稿箱。我本以为,只要内容足…

Linux操作系统学习:day03

内容来自:Linux介绍 视频推荐:[Linux基础入门教程-linux命令-vim-gcc/g -动态库/静态库 -makefile-gdb调试]( 目录 day0317、创建删除目录创建目录删除目录 18、文件的拷贝19、mv 命令20、查看文件内容的相关命令21、给文件创建软连接或硬链接 day03 …

docker部署dm数据库

官方文档参考 官网地址:https://eco.dameng.com/document/dm/zh-cn/start/dm-install-docker.html 下载镜像地址 docker部署 1、加载镜像 docker load -i dm8_20240613_x86_rh6_64_rq_ent_8.1.3.140_pack5.tar使用docker images,查看镜像和镜像标签…

【RK3588/算能/Nvidia智能盒子】挑战「无电无网」部署AI算法,守护大亚湾荃美石化码头工地安全

“万顷碧波之上,一座千米钢栈桥如蛟龙出水,向大海蜿蜒。钢栈桥上的项目建设者正在加紧作业,为助推惠州大亚湾加快建设成为世界级绿色石化基地全力奋战。”这是不久前北京日报对大亚湾惠州港荃湾港区荃美石化码头工地的描述。 △ 图片来源于北…

【RK3588/算能/Nvidia智能盒子】AI“值守”,规范新能源汽车充电站停车、烟火及充电乱象

近年来,中国新能源汽车高速发展,产量连续8年位居全球第一。根据中国充电联盟数据,截至2023年6月,新能源汽车保有量1620万辆,全国充电基础设施累计数量为665.2万台,车桩比约2.5:1。 虽然新能源汽车与充电桩供…

java架构设计-COLA

参考:https://github.com/alibaba/COLA 架构 要素:组成架构的重要元素 结构:要素直接的关系 意义:定义良好的结构,治理应用复杂度,降低系统熵值,改善混乱状态 创建COLA应用: mvn …

代理商 SAAS 系统权限设计

代理商 SAAS 系统与垂直业务系统不一样,代理商可以不断发展下级,每一级有每一级的管理员。超级管理员可以开通下级代理机构,同时设置下级机构的管理员账号。每一级管理员可以管理本级机构对应的部门、岗位、员工,并进行授权管理。…

SSH 远程执行任务

SSH 是 Linux 下进行远程连接的基本工具,但是如果仅仅用它来登录那可是太浪费啦!SSH 命令可是完成远程操作的神器啊,借助它我们可以把很多的远程操作自动化掉!下面就对 SSH 的远程操作功能进行一个小小的总结。 远程执行命令 如…

拦截器 之 用户登录判断

spring boot 拦截器的实现需要有两步: 拦截器 自定义一个拦截器 package com.example.demo.common;import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; import org.s…

【React】极客园--01.项目前置准备

项目搭建 基于CRA创建项目 CRA是一个底层基于webpack快速创建React项目的脚手架工具 # 使用npx创建项目 npx create-react-app react-jike# 进入到项 cd react-jike# 启动项目 npm start调整项目目录结构 -src-apis 项目接口函数-assets 项目资源文件&…