游戏事件系统(Game Event/Message System)

UML类图在游戏中应用 笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,优快云社区专家,特邀编辑,畅销书作者,国家专利发明人;已出版书籍:《手把手教你架构3D游戏引擎》电子工业出版社和《Unity3D实战核心技术详解》电子工业出版社等。优快云视频网址:http://edu.youkuaiyun.com/lecturer/144 前面介绍过各种架构设计,也编写过使用架构设计开发游戏,但是没有细说用什么工具去做架构设计,在这里我 阅读详情

  当游戏里面的元素多起来后,对象之间产生的事件将会越发复杂,比如主角走路,会对周围所有的角色发送当前坐标信息;比如主角打怪,除了通知其他人打怪的状态信息,还要通知怪物,您被虐了;还有很多都可以用事件来做,操作系统的事件驱动的方式就明显优于轮询方式。事件系统相当于将所有这些事件统一起来,让开发者易于扩展及维护。

 

  一、简单的事件系统

  参考:

  http://www.gamedev.net/reference/articles/article2141.asp

 

 直接看代码IEventHandler.h

 

  1. 首先定义事件结构体:

  // The event structure
struct Event {
  int Type;
  int arg1, arg2;
};

 

 一个类型,加上两个参数。(越简单越好,能阐述问题)

 

  2. 为了type好辨认,通过enum管理所有的消息类型

 

  // Defination of all the different type of events
enum EventType
{
   // Mouse button events. Each of the next six events gets passed
  // the absolute position of the mouse
  E_MOUSELEFTBUTTONPRESS,
  E_MOUSELEFTBUTTONRELEASE,

  // Start new games
  E_NEWGAMEEASY,
  E_NEWGAMENORMAL,
  E_NEWGAMEHARD,

  // Game play related
  E_INCREMENTSCORE,
  E_PAUSEGAME,
  E_CONTINUEGAME,
  E_GAMEOVER,

  // Close the App
  E_APPCLOSE
};

 

还是很简单,鼠标键盘消息,游戏难度选项,游戏状态等

 

 3. 定义一个接口,事件处理器(EventHandler)

 

class IEventHandler {

public:
  virtual void EventHandler(const Event &e) = 0;   // 纯虚函数,继承类必须实现

  // Mutator and selector
  IEventHandler * GetNextHandler(void) {return _nextHandler;} 
  void SetNextHandler(IEventHandler *next) {_nextHandler = next;}


// 构造函数使得对象一创建就自动注册到了时间分发器中,因为消息的分发主要靠事件分发器

// 遍历所有的事件处理器来发送事件。 而分发器是单例的,相对于事件处理器是一对多的关系,

// 后面会接着分析

  IEventHandler() : _nextHandler(0) {

    EventDispatcher::Get()->RegisterHandler(this);
  }

protected:
  void SendEvent(int eventType, int arg1 = 0, int arg2 = 0) {
    EventDispatcher::Get()->SendEvent(eventType, arg1, arg2);
  }

private:
  IEventHandler *_nextHandler;   // 将会有多个事件处理器,这里用链表来实现
};

 

 4. 接着看EventDispatcher.h

 

class IEventHandler;  // 类的前向声明

 

class EventDispatcher {

// definitions necessary to handle a singleton class
public:
  //returns a pointer to the EventDispatcher singleton instance
  static EventDispatcher*    Get();  // 提供一个得到对象指针的机会 , 与外界沟通的桥梁

private:
  // These are private so that only instance will ever be created
  // the _deviceList pointer is initialized to null as the linked list
  // is null-terminated
  EventDispatcher(void) : _deviceList(0) {;}  // 构造函数私有化,不能用new来创建对象
  ~EventDispatcher(void) {;} // 析构函数私有化,不能在栈上创建对象 , 应该添加一个释放资源的函数,要不没机会释放了

  // pointer to singleton class
  static EventDispatcher*    _instanceOf;

// definitions of methods which handle events
public:

  void RegisterHandler(IEventHandler *device); // 注册事件处理器,放入链表

  // Sends the event to all the devices registered to listen
  void SendEvent(int eventType, int arg1 = 0, int arg2 = 0); // 遍历所有事件处理器,发送消息

private:
  IEventHandler *_deviceList; // 这里体现出来关系了,一对多。
};

 

  5. 最后来看看实现吧,EventDispatcher.cpp

 

#include "EventDispatcher.h"

#include "IEventHandler.h"

// pointer to singleton instance
EventDispatcher* EventDispatcher::_instanceOf = 0;  // 初始化单例 对象

 

// 通过这个方法来创建单例对象,有点太懒了^_^,多个函数都不愿意写

EventDispatcher* EventDispatcher::Get() {
    if (_instanceOf)
        return _instanceOf;
    return _instanceOf = new EventDispatcher();
}

// 链表
void EventDispatcher::RegisterHandler(IEventHandler *device) {
  device->SetNextHandler(_deviceList);
  _deviceList = device;
}


void EventDispatcher::SendEvent(int eventType, int arg1, int arg2) {
  Event e;
  e.Type = eventType;
  e.arg1 = arg1;
  e.arg2 = arg2;
  IEventHandler * curDevice = _deviceList;

  // 遍历
  for (; curDevice; curDevice = curDevice->GetNextHandler())
    curDevice->EventHandler(e);
}

 

6. 使用 main.cpp

 

// 继承接口,实现虚函数

class A : public IEventHandler {

public:

  // 真正处理消息的函数,可以只针对相应的类型

  void EventHandler(const Event &e) {
    switch (e.Type) {
      case E_NEWGAMEEASY:
        cout << "Class A handling E_NEWGAMEEASY event" << endl;
        cout << "Class A sending a E_INCREMENTSCORE event" << endl;
        SendEvent(E_INCREMENTSCORE);
        break;
      case E_PAUSEGAME:
        cout << "Class A handling E_PAUSEGAME event" << endl;
        break;
    }
  }
};

 

class B : public IEventHandler {

public:
  void EventHandler(const Event &e) {
    switch (e.Type) {
      case E_INCREMENTSCORE:
        cout << "Class B handling E_INCREMENTSCORE event" << endl;
        break;
      case E_PAUSEGAME:
        cout << "Class B handling E_PAUSEGAME event" << endl;
        break;
    }
  }
};


void main () {
  A a1; // 定义就被放入了分发器中
  B b1;

  cout << "Main fct sending E_NEWGAMEEASY event" << endl;
  EventDispatcher::Get()->SendEvent(E_NEWGAMEEASY); // 直接发送消息,群发
  cout << "Main fct sending E_PAUSEGAME event" << endl;
  EventDispatcher::Get()->SendEvent(E_PAUSEGAME);

  char c;
  cout << "Press any key followed by [Enter] to exit" << endl;
  cin >> c;

  exit(0);
}

 

是不是有很多想法,那就对了,接着写吧。

Unity事件系统全解析:从委托到事件管理器,构建松耦合游戏架构 在游戏开发中,解耦与模块化通信是提升项目可维护性的核心。发布-订阅模式通过委托机制实现,让组件间无需直接引用即可通信,大幅降低耦合度。Unity引擎在此基础上提供了UnityEvent,实现了可视化的事件配置,极大提升了开发效率与团队协作流畅性。其技术价值在于支持快速迭代与功能扩展,例如成就系统、UI响应等模块可以独立监听游戏事件,无需修改核心逻辑。通过构建集中式的事件管理器,并结合枚举与强类型参数,可以打造出健壮、可调试的通信框架,这正是构建中大型Unity项目的关键实践。 阅读详情

相关推荐

【Unity事件系统插件】Game Event System(GES)底层实现原理详解:从“事件地狱”到可视化架构的进化

GES是Unity中一套基于ScriptableObject+强类型事件+可视化节点的事件架构系统,旨在解决游戏项目中的事件失控问题。它将事件系统提升为项目级基础设施,通过事件资产化、GUID绑定和多数据库设计实现稳定性。系统采用强类型事件模型和委托驱动机制,通过表达式树编译实现高性能零GC。可视化节点图支持并行/串行混合执行,并提供调试工具链。

2403_88403568的博客 520

eventhandler java_简单的Java Event-事件框架

自己写的一个简单的Java事件框架。目前具备以下功能:1.通过继承Event类,用户可自定义事件。2.通过EventService 的fireEvent(Event e) 发出一个事件。3.通过实现IEventHandler接口,监听某类事件。EventHandler可以动态注册到EventServer,也可以在配置文件中配置。4.通过实现IEventConsumedCallback接口,在事件被...

weixin_26834281的博客 774

996引擎 - 活捉NPC

本文围绕 996 引擎触发机制展开,重点是 NPC 点击触发。配置cfg_game_data的ShareNpc=1可转 QM 和机器人触发事件到QF,TXT 触发转小写能用于 LUA。Envir\Market_Def\QFunction - 0.lua有 NPC 点击触发功能,调用GameEvent.push。GameEvent模块涵盖事件注册、移除和推送功能。作者创建Test.lua测试文件输出点击 NPC 的 id,并调试了服务器进程,还给出参考资料链接。

灵台方寸山斜月三星洞 1910

Common(五)—— 消息系统(一):简单的EventCenter

源码里面有一个消息系统,把这个消息系统挖出来,然后单独的一个EventCenter就出来了,文章最后面会有演示如何使用. 先来看看都有哪些文件: Assets/Scripts/Common/目录下 Callback.cs, Event.cs, EventCenter.cs, EventDefine.cs. Callback.cs://无参数 public delegate void Callback

qq_22472397的博客 2881

Unity-ScriptableObjects-Game-Events-:基于Ryan Hipple的精彩演讲,这是我为Unity开发的Game Event系统的改进版本

Unity:ScriptableObjects游戏事件系统 根据Ryan Hipple的精彩演讲,这是我为Unity开发的Game Event系统的改进版本 快速说明:该项目不使用任何名称空间。 如果您有任何名称相同的类,则可能会与您自己的代码发生冲突。 有3个类:GameEvent EventListener EventAndResponse 为什么用这个 在Unite Austin 2017上,Ryan Hipple谈到了在Unity中使用可脚本化对象的优势。 视频在这里(他说): ://youtu.be/raQ3iHhE_Kk?t 1964大约32分钟,他谈到要创建一个事件系统,该系

别再手动续期SSL证书了!用acme.sh配合阿里云DNS API,实现全自动HTTPS证书管理

本文详细介绍了如何使用acme.sh配合阿里云DNS API实现SSL/TLS证书的全自动管理,彻底解决手动续期带来的风险与不便。通过自动化部署流程,包括环境准备、API集成、多域名证书申请等关键步骤,帮助运维人员构建高效、可靠的HTTPS证书管理体系,显著提升安全性和运维效率。

weixin_29200485的博客 268

SoonFx Runtime事件系统揭秘:构建高效的游戏通信架构

🎮 欢迎来到SoonFx Runtime事件系统的深度探索!作为一款专为RPG和策略游戏设计的TypeScript数值引擎,SoonFx Runtime的事件通信系统是其核心架构的重要组成部分。本文将为您详细解析这个强大的游戏通信架构,帮助您理解如何构建高效、解耦的游戏系统。 ## 什么是SoonFx Runtime事件系统? SoonFx Runtime事件系统是一个**轻量级、类型安全的

gitblog_01157的博客 482

器件物理与工艺:揭秘MOSFET寄生电容Cgd/Cgs的微观结构及演变

本文深入解析MOSFET寄生电容Cgd与Cgs的微观物理结构及其在开关过程中的非线性演变,重点探讨由Cgd反馈效应引发的米勒平台现象。通过分析器件物理机制与先进工艺技术,揭示电容特性对开关性能的影响,并提供工艺优化与设计策略,助力提升高频功率应用的效率与稳定性。

desk3的博客 1082

Web-Dev-For-Beginners 太空射击游戏(第 1 课):用 JavaScript 继承、组合与 Pub/Sub 事件架构构建可扩展的游戏系统

本文是微软开源课程 [Web-Dev-For-Beginners](https://link.gitcode.com/i/b1df4286cae8aecb6301dff704c837fa) 中「构建太空射击游戏」系列的第一篇理论课(对应 [6-space-game/1-introduction](https://link.gitcode.com/i/46a7f6b58904e8f67ba8c9d2

gitblog_00493的博客 449

【车辆仿真】从0开始建立dSPACE RT Simulink工程:输出模拟电平

0基础建议先看下前面的博文,补充基础知识。原来的博文太长太复杂,后续我会逐步梳理改进,去除操作层面的内容,仅关注知识层面,提升系列博文的系统性。【工程环境信息】:上位机:惠普台式PC(Windows 11专业版)下位机(实时机):SCALEXIO RTPC板卡:DS2680。

winnizap的博客 2054

RV1126B RV1126B-P 瑞芯微 高性能视觉处理器SoC 芯片

它集成了大量算法加速器,如 HDR、3A、LSC、3DNR、2DNR、锐化、去雾、鱼眼校正、伽马校正、特征点检测等。此外,还配备了一款最多8兆像素的 AI-ISP,作为对传统ISP 的补充,以提供卓越的空间去噪性能和增强的图像增强效果。除了先前的高性能多媒体区块外,RV1126B还包含丰富的音频、内存和其他外围接口,如I2C、SPI、PWM等。借助这-特性,来自相机的视频可以以高分辨率进行编码,并存储在本地内存中,同时还能将另-段较低分辨率的视频传输到云存储。

szhorsway的博客 1856

Web-Dev-For-Beginners 太空游戏系列:用「继承 / 组合 + Pub-Sub 事件系统」完成你的第一个游戏原型设计

本篇围绕 Web-Dev-For-Beginners 仓库中 Build a Space Game 系列第一课的课后作业「Mock up a Game: Apply Design Patterns」展开:它要求你基于本课学到的两种对象组织方式(类继承或组合)和发布-订阅(pub/sub)通信机制,独立搭建一个功能可用的游戏原型。读完并动手完成后,你将掌握:如何在真实项目里选型继承 vs 组合、如何

gitblog_00325的博客 269

基于ARDUINIO的5路红外循迹小车

基于ARDUINIO的5路红外循迹小车 新手抄袭了很多大神的代码。这里表示感谢。 #define STOP 0 #define FORWARD 1 #define BACKWARD 2 #define STURNLEFT 3 #define STURNRIGHT 4 #define TURNLEFT 5 #define TURNRIGHT 6 #define TURNRIGHT90 7 #define TURNLEFT90 8 int leftA_PIN = A0; int

weixin_48214416的博客 4381

NuvioTVSmart 跨电视平台适配实战:Tizen 4/5/6 与 webOS 5/6 能力差异与兼容策略指南

NuvioTVSmart 是开源电视媒体应用 **Nuvio TV** 的官方 WebOS / Tizen 仓库,同一套代码要同时跑在三星 Tizen 4/5/6 与 LG webOS 5/6 五档电视系统上。本文拆解它的跨电视平台适配实战:平台检测与适配器架构、Tizen 4/5/6 与 webOS 5/6 的能力差异、AVPlay 播放分流、EngineFS 伴随服务,以及"能力降级而不崩溃"

gitblog_00405的博客 852

华硕笔记本全硬盘恢复原厂状态 实机操作,MYASUS IN WINRE恢复,ASUS RECOVERY恢复

本教程的前提的在之前就备份了原厂的RECOVERY分区,RESTORE分区,MYASUS分区 如果这些分区都没有的话那就只能找同型号笔记本的朋友要一份了,或者去售后,告诉他这三个分区都要恢复。一般售后为了节约硬盘空间,不会给你恢复restore分区,这个分区有将近20G。 我机器撒天选2 i7-11800H,3060,32G,512GB,型号FX506HM 这篇教程先说全格式化怎么做,下次有空再说免格式化怎么弄。下面开始。 首先首先你的先做给优盘或者移动硬盘做一个PE。网上做PE启动盘的教程很多,这

JamesCurtis的博客 3万+

最新Python爬虫实战(入门爬虫篇)——案例7:电影网站电影数据采集(详细爬虫思路截图+抓包动图演示+完整爬虫代码+详细注释)

本次案例通过Python爬虫技术,成功实现了对某电影网站Top250多页电影详细信息的批量爬取与Excel保存。代码采用模块化设计,包含分页请求构造、XPath+正则提取结构化信息、Excel数据持久化保存等完整流程。通过配置User-Agent等请求头信息,有效模拟浏览器行为以绕过豆瓣基础反爬策略。整个爬虫逻辑遵循"分页遍历 → 请求页面 → 解析HTML → 提取电影信息 → 保存到Excel"的标准流程,与主流静态网站爬取范式高度一致。

努力让自己发光,对的人才能迎着光而来 11万+

游戏AI搭子系统全解析:从猫娘到人格、记忆与事件联动

在人工智能与游戏产业深度融合的当下,打造具有陪伴感的AI角色逐渐成为提升玩家留存的关键手段。其核心并非简单的对话生成,而是围绕角色一致性、跨会话记忆与游戏事件感知构建的工程体系。一个合格的AI搭子需要具备稳定的人设配置、分层的长期记忆管理,以及能够实时响应玩家行为的事件联动机制。通过将角色配置结构化、记忆按重要性分级存储,并打通游戏事件到对话上下文的注入链路,即使是独立开发者也能基于大模型接口快速实现一个具备“专属感”的AI伙伴。本文将借鉴猫娘搭子的实际案例,拆解AI角色从Prompt设计到系统落地的完整路

weixin_34302561的博客 382

vue支付项目-APP支付宝支付功能

如果用户已安装支付宝客户端,商家 App 唤起支付宝完成支付,支付完后跳回到商家 App 内,最后展示支付结果。如果用户没有安装支付宝客户端,商家 App 内会调起支付宝网页支付收银台,用户登录支付宝账号,支付完后展示支付结果。1.点击按钮开通或者续费,会验证是否选择会员商品以及对协议是否查看选中(这里根据项目需要自行验证,可忽略),验证通过打开选择支付方式弹窗页面,选择微信支付或者支付宝支付;4.可取消支付,放弃支付会返回会员页面,页面提示支付取消;1.判断支付方式,如果是2,则是支付宝支付方式。

总结前端开发中遇到的问题,分享前端知识 1万+

Web-Dev-For-Beginners 项目实战:用 JavaScript 从零构建太空射击游戏(Space Game)

**导读**:本篇技术指南围绕 `Web-Dev-For-Beginners` 开源课程中的 `6-space-game` 模块(对应 [translations/bg/6-space-game/README.md](https://link.gitcode.com/i/a6afd6de4c59454a60233161bb50288f) 及其英文原文 [6-space-game/README.md

gitblog_00310的博客 474

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

用设计模式与 Pub/Sub 构建游戏原型:Web-Dev-For-Beginners 空间游戏系列实战作业完全指南

本指南围绕 [Web-Dev-For-Beginners](https://link.gitcode.com/i/52398b16b813664d6e8e9b2b6541779f) 空间游戏课程第一课(Introduction)的配套作业展开:要求你用继承或组合两种架构模式,配合发布-订阅(Pub/Sub)事件系统,从零搭建一个可运行、可扩展的简单游戏原型。读完本文,你将掌握 EventEmitt

gitblog_00476的博客 1024

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

游戏事件监听与预警系统实战:从数据解析到威胁检测

在游戏开发与数据分析领域,事件驱动模型是实现实时交互与状态同步的核心架构。其原理在于通过监听游戏内特定动作或状态变化,触发预设的逻辑响应,从而实现高效的数据流处理。这项技术的价值在于能够将复杂的游戏世界抽象为可观测、可分析的结构化信息流,为游戏平衡性分析、AI训练、观战系统及辅助工具开发提供底层数据支持。应用场景广泛覆盖MOBA、FPS等需要实时信息处理的在线竞技游戏。本文聚焦于游戏事件监听与预警系统的构建,详细阐述了如何通过数据解析与威胁检测算法,模拟实现类似“视野控制”与“信息获取”的功能,为开发者提供

weixin_34378969的博客 345

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

用继承、组合与 Pub/Sub 构建太空游戏:Web-Dev-For-Beginners 游戏开发系列入门篇

本文将带你进入 Web-Dev-For-Beginners 项目中"构建太空游戏"(Build a Space Game)六课系列的第一课,以浏览器 JavaScript 为语言环境,系统讲解游戏对象(Game Object)的两种代码组织方式——类继承与组合,以及让游戏组件松耦合协作的发布-订阅(Pub/Sub)通信模式。学完本篇,你将掌握游戏对象的基础建模、EventEmitter 事件系统的

gitblog_01183的博客 381

UnityEvent可视化事件系统:从委托原理到游戏逻辑解耦实战

在游戏开发中,事件驱动架构是实现模块间通信的核心模式,其原理基于观察者模式,通过解耦事件的发布与订阅来提升代码的灵活性和可维护性。UnityEvent作为Unity引擎内置的可序列化委托系统,将这一模式与编辑器可视化深度结合,允许开发者直接在Inspector面板中配置事件响应关系,无需硬编码依赖。这一技术显著降低了脚本间的耦合度,使得策划和美术人员也能参与逻辑连接,提升了团队协作效率。在游戏开发中,UnityEvent常用于UI交互、游戏对象通信、状态同步等场景,是实现模块化游戏逻辑的关键工具。通过合理应

weixin_30861459的博客 406

<划重点的Unity2017>事件系统

(1)事件系统概述 1.Overview 概述the Event System itself is designed as a manager and facilitator of communication between Event System modules. 事件系统本身是作为两个事件系统模块的管理者。The primary roles of the Event System are

游戏引擎研发进阶之路 1535

Web-Dev-For-Beginners:基于事件驱动编程从零构建打字速度游戏

在 Web-Dev-For-Beginners 课程的第 4 课中,你将通过构建一个能追踪打字速度与准确率的打字游戏,系统掌握浏览器事件驱动编程的核心机制:事件监听器(event listener)、`addEventListener()`、`click` 与 `input` 事件的处理流程,以及如何用 DOM 操作实现实时视觉反馈。读完本篇并动手完成后,你将能够独立完成"用户输入 → 事件分发

gitblog_00713的博客 203

Bevy 0.20 Observer 事件匹配迁移指南:`B: Bundle` 泛型从 `On<E, B>` 移入事件类型

本文基于 Bevy 官方迁移文档 [observer_event_matching.md](https://link.gitcode.com/i/47509d05f22b158c9e7554f9f598b825)(对应变更来自 PR #24013)展开,讲解 Bevy 0.19 到 0.20 中 Observer 系统的一项重要 API 变更:`On<E, B>` 中的 `B: Bundle` 类

gitblog_01116的博客 447
上一篇: 命名空间使用后,在头文件中怎样声明?
下一篇: install rubyonrails( no such file to load -- zlib )
gnuser
博客等级 码龄20年 35粉丝 141原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值