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

从Button点击到自定义事件系统:手把手教你玩转UnityEvent与C#委托的混合编程

从Button点击到自定义事件系统手把手教你玩转UnityEvent与C#委托的混合编程在Unity开发中Button组件的点击事件可能是我们最熟悉的交互入口。但你是否思考过为什么在Inspector面板拖拽方法就能实现回调为什么代码中既能用AddListener又能用注册事件这背后隐藏着UnityEvent与C#原生委托系统的精妙配合。本文将带你从UGUI的Button组件出发逐步拆解事件系统的实现原理最终构建一个支持跨模块通信的自定义事件总线。1. Button点击背后的双面魔法UnityEvent解析当我们创建一个UGUI Button时Inspector面板中的On Click列表允许我们直接拖拽游戏对象和方法。这种可视化配置的背后是UnityEvent的封装机制。不同于纯代码的委托系统UnityEvent实现了以下独特特性序列化存储面板中配置的回调方法会被序列化到场景/预制体文件中双轨制调用面板配置与代码注册的监听器互不干扰参数传递隔离Invoke调用时面板配置的方法使用预设参数值// 典型UnityEvent用法示例 public UnityEvent onPlayerDeath; void Start() { // 代码注册监听 onPlayerDeath.AddListener(HandlePlayerDeath); } void HandlePlayerDeath() { Debug.Log(Player defeated!); }注意通过RemoveAllListeners()只能清除代码注册的监听器面板配置的需要手动移除UnityEvent的局限也很明显缺乏类型安全的强约束无法直接传递动态参数给面板配置的方法性能开销略高于原生C#委托2. C#委托系统三剑客delegate、event与Action/Func要突破UnityEvent的限制我们需要回到C#的委托系统。理解这三个核心概念的区别至关重要2.1 基础委托(delegate)委托本质上是方法签名的类型声明允许将方法作为参数传递。关键特点包括支持/-操作符进行多播可以直接赋值()替换全部监听需要显式初始化后才能调用public delegate void DamageHandler(float amount); public class HealthSystem { public DamageHandler OnDamageTaken; public void TakeDamage(float damage) { OnDamageTaken?.Invoke(damage); } }2.2 事件(event)封装event在delegate基础上添加了访问控制层外部代码只能通过/-订阅禁止外部直接调用或赋值提供更好的封装性public class EventPublisher { public event Actionstring OnMessageReceived; private void ProcessInput() { OnMessageReceived?.Invoke(Hello World); } }2.3 预定义泛型委托Action与Func.NET提供的通用委托类型可以避免重复声明类型返回值最大参数数典型用法Actionvoid16无返回值的事件通知Actionvoid1带单个参数的事件FuncT0无参数的返回值方法FuncT,KK1带参数转换的方法// 技能系统使用示例 public FuncVector3, bool CheckTargetValid; public ActionGameObject OnSkillHit; void CastSkill() { if(CheckTargetValid?.Invoke(targetPos) true) { OnSkillHit?.Invoke(target); } }3. 混合编程实战构建自定义事件总线结合UnityEvent的可视化优势和C#委托的性能优势我们可以创建更强大的事件系统。以下是实现全局事件总线的关键步骤3.1 基础事件总线架构public class EventBus { private static readonly DictionaryType, Delegate _events new(); public static void SubscribeT(ActionT handler) { if(_events.TryGetValue(typeof(T), out var existing)) { _events[typeof(T)] Delegate.Combine(existing, handler); } else { _events[typeof(T)] handler; } } public static void PublishT(T eventData) { if(_events.TryGetValue(typeof(T), out var handlers)) { (handlers as ActionT)?.Invoke(eventData); } } }3.2 与UnityEvent的桥接设计实现面板配置与代码事件的互通[Serializable] public class UnityEventBridgeT : UnityEventT { private ActionT _runtimeHandlers; public new void AddListener(ActionT call) { _runtimeHandlers call; base.AddListener(call); } public new void Invoke(T arg) { base.Invoke(arg); _runtimeHandlers?.Invoke(arg); } } // 使用示例 public UnityEventBridgeint OnScoreChanged; void Start() { // 面板配置的方法和代码注册的方法将同时触发 OnScoreChanged.AddListener(score { Debug.Log($Score updated: {score}); }); }3.3 性能优化技巧事件系统的性能瓶颈主要来自装箱拆箱使用泛型避免值类型转换委托调用缓存Invoke列表减少GC空检查使用null条件运算符(?.)优化后的发布逻辑public static void OptimizedPublishT(T eventData) where T : struct { if(_events.TryGetValue(typeof(T), out var del)) { var handlers del.GetInvocationList(); for(int i 0; i handlers.Length; i) { (handlers[i] as ActionT)?.Invoke(eventData); } } }4. 高级应用模式技能系统实战将混合事件系统应用于技能触发场景// 定义技能事件 public struct SkillEventData { public GameObject Caster; public Vector3 TargetPos; public float Power; } // 技能组件 public class SkillComponent : MonoBehaviour { public UnityEventBridgeSkillEventData OnSkillCast; void Update() { if(Input.GetKeyDown(KeyCode.Space)) { var data new SkillEventData { Caster gameObject, TargetPos transform.position transform.forward, Power 100f }; // 同时触发面板配置和代码注册的事件 OnSkillCast.Invoke(data); // 发布到全局事件总线 EventBus.Publish(data); } } } // 伤害计算系统 public class DamageSystem { void Start() { EventBus.SubscribeSkillEventData(OnSkillTriggered); } void OnSkillTriggered(SkillEventData data) { // 计算区域伤害... } }这种架构实现了技能逻辑与伤害计算的完全解耦可视化调试通过UnityEvent面板跨系统的事件通信灵活的技能效果组合5. 调试与异常处理健壮的事件系统需要完善的错误处理机制5.1 安全调用模式public static void SafePublishT(T eventData) { try { if(_events.TryGetValue(typeof(T), out var handlers)) { var invocationList handlers.GetInvocationList(); foreach(var handler in invocationList) { try { (handler as ActionT)?.Invoke(eventData); } catch(Exception ex) { Debug.LogError($Event handler failed: {ex}); } } } } catch(Exception ex) { Debug.LogError($Event dispatch failed: {ex}); } }5.2 调试可视化工具创建编辑器窗口显示当前注册的事件#if UNITY_EDITOR [CustomEditor(typeof(EventDebugger))] public class EventDebuggerEditor : Editor { public override void OnInspectorGUI() { var debugger target as EventDebugger; foreach(var pair in EventBus.GetAllEvents()) { EditorGUILayout.LabelField(pair.Key.Name); var listeners pair.Value.GetInvocationList(); EditorGUI.indentLevel; foreach(var listener in listeners) { EditorGUILayout.LabelField(listener.Method.Name); } EditorGUI.indentLevel--; } } } #endif6. 架构演进建议随着项目规模扩大可以考虑按模块划分事件总线避免全局事件泛滥引入事件优先级系统控制处理顺序添加事件日志便于回放调试实现事件拦截机制支持中间件模式最终极的解决方案是集成成熟的框架如MediatR实现中介者模式MessagePipe高性能消息管道UniRx响应式编程扩展但在大多数Unity项目中适度的自定义事件系统往往是最佳选择——既保持灵活性又不会引入过多复杂性。

相关文章:

从Button点击到自定义事件系统:手把手教你玩转UnityEvent与C#委托的混合编程

从Button点击到自定义事件系统:手把手教你玩转UnityEvent与C#委托的混合编程 在Unity开发中,Button组件的点击事件可能是我们最熟悉的交互入口。但你是否思考过,为什么在Inspector面板拖拽方法就能实现回调?为什么代码中既能用Add…...

别再乱合并电源了!FPGA驱动DDR3时,VDD、VDDQ、Vref、VTT到底该怎么供?

FPGA驱动DDR3的电源设计:VDD、VDDQ、Vref与VTT的黄金法则 在高速数字电路设计中,DDR3内存接口的稳定性往往成为整个系统的瓶颈。许多工程师花费大量精力研究信号完整性和布线技巧,却忽视了电源系统这个更基础、更关键的因素。当FPGA与DDR3颗粒…...

拆解一个古董设备,发现了宝藏芯片MB85RC64:聊聊FRAM那些被低估的应用场景

从MB85RC64芯片拆解看FRAM技术的隐形战场 拆开一台90年代的工业流量计,灰尘中露出指甲盖大小的MB85RC64芯片——这枚富士通生产的FRAM存储器,在当年可是身价不菲的"贵族器件"。如今当我们重新审视这种铁电存储技术,会发现它在那些&…...

别再只盯着CMMI认证了!聊聊CMMI-DEV、SVC、ACQ三个模型到底该怎么选?

CMMI三大模型深度解析:如何为你的企业精准匹配最佳实践框架? 当企业决策者面对CMMI认证时,往往陷入一个典型误区——将CMMI-DEV视为唯一选择。事实上,CMMI研究院早在2010年就针对不同业务场景推出了三大专业模型:面向软…...

别再傻傻分不清了!华为交换机上三种ARP代理的实战配置与场景选择指南

华为交换机三种ARP代理的深度解析与实战指南 在复杂的网络环境中,ARP代理技术常常成为网络工程师的"隐形助手"。它像一位熟练的翻译官,在不同网络边界间架起沟通的桥梁。今天,我们就来揭开华为交换机上三种ARP代理技术的神秘面纱&…...

从RFC函数到可调用的Web Service:SAP ABAP中SOAMANAGER配置全流程避坑指南

从RFC函数到可调用的Web Service:SAP ABAP中SOAMANAGER配置全流程避坑指南 在SAP系统集成项目中,将ABAP函数模块封装为Web Service是打通异构系统的关键技术路径。许多开发者在初次接触SOAMANAGER配置时,往往会在服务激活、WSDL生成和接口测试…...

Mac学Linux新姿势:VMware Fusion装Ubuntu后,用VS Code远程开发真香了

Mac与Linux的优雅共舞:VMware FusionUbuntuVS Code远程开发全指南 当Mac的精致美学遇上Linux的强大内核,会碰撞出怎样的火花?对于开发者而言,这绝非简单的系统切换选择题,而是如何让两大操作系统优势互补的深度整合。本…...

仅限Tier1供应商内部流传的Docker车载部署Checklist(v4.3),含17项ASAM OpenX标准兼容性校验项,免费领取最后47份

第一章:Docker车载部署优化在智能网联汽车边缘计算场景中,Docker 容器因轻量、可移植和快速启停等特性被广泛用于车载应用部署。然而,车载环境存在资源受限(如 CPU/内存波动、存储空间紧张)、网络不稳定、实时性要求高…...

从车窗升降到自动驾驶:聊聊LIN总线和CAN总线在实车里的那些事儿

从车窗升降到自动驾驶:LIN与CAN总线的汽车神经脉络解密 清晨七点十五分,当你坐进驾驶座按下车窗按钮时,可能不会想到这个简单的动作正触发着一场精密的电子交响乐。而在三公里外的高速公路上,前方车辆突然刹车时,你的爱…...

STM32F030硬件SPI调试踩坑实录:为什么读写数据总是不对?

STM32F030硬件SPI调试实战:从异常波形到数据访问的深度解析 当你在STM32F030上调试硬件SPI时,是否遇到过这样的场景:所有配置看起来都正确,逻辑分析仪显示的时钟信号也正常,但读回来的数据就是不对?这不是个…...

免费开源在线PPT制作工具:浏览器中打造专业演示文稿的终极指南

免费开源在线PPT制作工具:浏览器中打造专业演示文稿的终极指南 【免费下载链接】PPTist PowerPoint-ist(/pauəpɔintist/), An online presentation application that replicates most of the commonly used features of MS PowerPoint, all…...

3分钟掌握Xbox控制器性能测试:XInputTest终极指南

3分钟掌握Xbox控制器性能测试:XInputTest终极指南 【免费下载链接】XInputTest Xbox 360 Controller (XInput) Polling Rate Checker 项目地址: https://gitcode.com/gh_mirrors/xin/XInputTest 想要知道你的游戏手柄是否真的"零延迟"吗&#xff1…...

浙江大学毕业论文LaTeX模板:3步告别格式烦恼,专注学术研究

浙江大学毕业论文LaTeX模板:3步告别格式烦恼,专注学术研究 【免费下载链接】zjuthesis Zhejiang University Graduation Thesis LaTeX Template 项目地址: https://gitcode.com/gh_mirrors/zj/zjuthesis 还在为毕业论文的格式要求头疼吗&#xff…...

层次状态机与同步数据流的设计原理与实践

1. 层次状态机基础与设计原理1.1 状态细化的核心思想层次状态机(Hierarchical State Machines, HSMs)的核心创新在于状态细化(State Refinement)机制。如图5.13所示,当状态B被细化为一组子状态{C, D}时,系统…...

STM32的‘防拆保险箱’:手把手教你用BKP备份寄存器保存关键数据(附VBAT供电电路设计)

STM32的‘防拆保险箱’:手把手教你用BKP备份寄存器保存关键数据(附VBAT供电电路设计) 在智能硬件和消费电子领域,数据安全正成为开发者面临的核心挑战之一。想象这样一个场景:你的智能门锁被物理拆解时,如何…...

USB-PD协议分析仪Dr. PD的设计与应用

1. 项目概述:Dr. PD USB-PD协议分析仪十年前谁能想到,一根数据线能同时传输4K视频、千兆网络和240W电力?USB-C和Power Delivery(PD)协议彻底改变了电子设备的供电方式。但当你设计的PD设备无法正常握手,或者…...

告别手动操作:30+专业Illustrator脚本如何彻底改变你的设计工作流

告别手动操作:30专业Illustrator脚本如何彻底改变你的设计工作流 【免费下载链接】illustrator-scripts Adobe Illustrator scripts 项目地址: https://gitcode.com/gh_mirrors/il/illustrator-scripts 你是否厌倦了在Adobe Illustrator中重复执行相同的操作…...

手把手教你用FontCreator汉化软件界面和制作中文图标字体(保姆级避坑指南)

手把手教你用FontCreator打造专业级中文图标字体 在数字化设计领域,图标字体已经成为提升用户体验的利器。无论是开发者的后台管理系统,还是设计师的PPT演示文稿,一套风格统一、加载迅速的图标字体能让界面瞬间专业起来。而FontCreator作为字…...

树莓派4B无头启动后,除了SSH还能怎么玩?Win11网线直连下的文件共享与端口转发实战

树莓派4B无头启动进阶指南:Win11直连下的高效开发环境搭建 当你已经通过网线直连成功SSH登录树莓派时,这仅仅是探索的开始。本文将带你解锁无显示器环境下更强大的工作流——从基础文件共享到专业级服务部署,让树莓派4B真正成为你的便携式开发…...

League-Toolkit:英雄联盟玩家的终极自动化工具集

League-Toolkit:英雄联盟玩家的终极自动化工具集 【免费下载链接】League-Toolkit An all-in-one toolkit for LeagueClient. Gathering power 🚀. 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit League-Toolkit 是一款基于官方 L…...

Meshroom终极指南:免费开源3D重建软件从入门到精通

Meshroom终极指南:免费开源3D重建软件从入门到精通 【免费下载链接】Meshroom Node-based Visual Programming Toolbox 项目地址: https://gitcode.com/gh_mirrors/me/Meshroom 想要将普通照片转化为专业级3D模型吗?Meshroom正是你需要的魔法工具…...

从GPT到T5:深入理解Transformer解码器的‘因果掩码’(Causal Mask)及其在PyTorch中的实现

从GPT到T5:深入理解Transformer解码器的‘因果掩码’及其实现 在自然语言处理领域,Transformer架构彻底改变了序列建模的方式。2017年那篇开创性的论文《Attention Is All You Need》不仅引入了自注意力机制,还埋下了后来各种变体模型的种子…...

【花雕动手做】MAKER-ESP32-PRO 双核CPU物联网带四路电机驱动板

MAKER-ESP32-PRO 是一款专为创客、机器人与物联网(IoT)开发设计的高性能集成控制板。它以乐鑫 ESP32-WROOM-32 双核模组为核心,板载 4 路大功率电机驱动,并集成了丰富的外设接口,无需额外搭建复杂电路,即可…...

3D Tiles Tools实战指南:从GLB到B3DM的格式转换与批量处理技术

3D Tiles Tools实战指南:从GLB到B3DM的格式转换与批量处理技术 【免费下载链接】3d-tiles-tools 项目地址: https://gitcode.com/gh_mirrors/3d/3d-tiles-tools 在3D地理空间数据可视化领域,3D Tiles Tools项目提供了强大的格式转换能力&#xf…...

无需烦恼查重!AI写教材工具实测,高效生成教材,轻松搞定学术难题!

选择AI教材写作工具的纠结与解决方案 在编写教材之前,选择合适的工具就像置身于一个“庞大的纠结现场”!如果选择办公软件,功能往往显得太过简单,框架的搭建和格式的规范也需手动去调整;而如果使用一些专业的AI写教材…...

抖音内容高效获取指南:从零开始掌握批量下载技巧

抖音内容高效获取指南:从零开始掌握批量下载技巧 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback support. 抖…...

从3小时到3分钟:构建自动化视频号批量下载系统的高效方案

从3小时到3分钟:构建自动化视频号批量下载系统的高效方案 【免费下载链接】res-downloader 视频号、小程序、抖音、快手、小红书、直播流、m3u8、酷狗、QQ音乐等常见网络资源下载! 项目地址: https://gitcode.com/GitHub_Trending/re/res-downloader 在内容创…...

moto 新机必看!这几个基础设置,让实用性和流畅度直接翻倍

刚拿到 moto 手机的朋友,大多习惯开机直接用,却很少去调整系统里那些能大幅提升体验的关键设置。默认状态下,续航、手势、通知、显示、隐私等功能往往没有达到最优状态,用久了容易出现耗电快、操作不顺手、消息杂乱等问题&#xf…...

WeChatExporter:5步轻松完成微信聊天记录永久备份的终极指南

WeChatExporter:5步轻松完成微信聊天记录永久备份的终极指南 【免费下载链接】WeChatExporter 一个可以快速导出、查看你的微信聊天记录的工具 项目地址: https://gitcode.com/gh_mirrors/wec/WeChatExporter 你是否担心珍贵的微信聊天记录会因为手机丢失、系…...

别再手动改编号了!Word题注+交叉引用保姆级教程,论文排版效率翻倍

Word自动化排版:题注与交叉引用全攻略 写论文最崩溃的时刻是什么?当你调整了第37张图片的位置,却发现要手动修改后面63处引用编号的时候。这不是夸张,而是许多学术工作者真实的噩梦。手动编号不仅消耗时间,更会在反复修…...