16.事件中心优化:添加参数

5G NR Rel16测量上报事件全解析:从A1到I1,手把手教你理解每个触发条件 本文全面解析5G NR Rel16测量上报事件,从A1到I1的触发机制与实战应用。详细介绍了同频测量事件(A1-A6)、异系统测量事件(B1/B2)以及Rel16新增的I1干扰检测事件,帮助网络优化人员理解每个事件的触发条件、参数配置和实际应用场景,提升5G网络性能。 阅读详情

一、为什么要给事件添加参数

原来的事件只能通知监听者“敌人死亡了”,不能告诉监听者死亡的是哪个敌人。
添加参数后,Enemy 可以在触发死亡事件时把自身传给事件中心:

EventMgr.Instance.EventTrigger
(
    EventMgr.enemyDieEvent,
    this
);

Level 和 Player 收到事件后,就能读取死亡敌人的名称、编号等信息。

二、事件字典的变化

原来的委托不接收参数:

Dictionary<string, UnityAction> eventDic;

现在改为接收一个 object 参数:

Dictionary<string, UnityAction<object>> eventDic;

object 是所有类型的父类,因此可以接收 Enemy、GameObject、数值或其他数据。

三、触发带参数的事件

public void EventTrigger(string eventName, object info = null)
{
    if (eventDic.TryGetValue(
        eventName,
        out UnityAction<object> unityAction))
    {
        unityAction?.Invoke(info);
    }
}
  • eventName:需要触发的事件名称。
  • info:需要传给监听者的数据。
  • info = null:不传参数时默认使用 null。

四、监听方法也要接收参数

添加参数后,注册到事件中心的方法必须接收一个 object:

private void UpGrade(object info)

接收到数据后,将 object 转回原来的 Enemy 类型:

Enemy enemy = info as Enemy;

转换成功后,就可以读取敌人数据:

enemy.enemyName;
enemy.enemyID;

五、带参数事件的执行流程

Enemy 的 Hp 归零
        ↓
Enemy 触发 enemyDieEvent
并把 this 作为参数传入
        ↓
EventMgr 执行 UnityAction<object>
        ↓
Level 和 Player 收到 object
        ↓
将 object 转换为 Enemy
        ↓
读取敌人信息并执行对应逻辑

六、object 传参存在的问题

object 可以接收不同类型的数据,使用比较方便。
但是传递 int、float、bool 等值类型时会发生装箱;取出并转换回值类型时会发生拆箱,会产生额外的性能开销。

七、完整代码

1. EventMgr.cs

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

public class EventMgr : Singleton2<EventMgr>
{
    private EventMgr()
    {
    }

    // Key:事件名称
    // Value:带有一个 object 参数的事件委托
    private readonly Dictionary<string, UnityAction<object>> eventDic = new();

    // 敌人死亡事件的唯一标识
    public const string enemyDieEvent = "EnemyDieEvent";

    /// <summary>
    /// 触发事件并传递参数。
    /// </summary>
    /// <param name="eventName">要触发的事件标识名。</param>
    /// <param name="info">需要传给监听者的数据。</param>
    public void EventTrigger(string eventName, object info = null)
    {
        if (eventDic.TryGetValue(
            eventName,
            out UnityAction<object> unityAction))
        {
            unityAction?.Invoke(info);
        }
    }

    /// <summary>
    /// 添加事件监听。
    /// </summary>
    /// <param name="eventName">要监听的事件标识名。</param>
    /// <param name="unityAction">接收 object 参数的事件委托。</param>
    public void AddEventListener(
        string eventName,
        UnityAction<object> unityAction)
    {
        if (string.IsNullOrEmpty(eventName) || unityAction == null)
        {
            Debug.LogError("输入的事件名称或者函数不合法");
            return;
        }

        if (eventDic.ContainsKey(eventName))
        {
            eventDic[eventName] += unityAction;
        }
        else
        {
            eventDic.Add(eventName, unityAction);
        }
    }

    /// <summary>
    /// 移除事件监听。
    /// </summary>
    /// <param name="eventName">要移除的事件标识名。</param>
    /// <param name="unityAction">需要移除的事件委托。</param>
    public void RemoveEventListener(
        string eventName,
        UnityAction<object> unityAction)
    {
        if (string.IsNullOrEmpty(eventName) || unityAction == null)
        {
            Debug.LogError("输入的事件名称或者函数不合法");
            return;
        }

        if (!eventDic.ContainsKey(eventName))
            return;

        eventDic[eventName] -= unityAction;

        // 已经没有监听者时,删除该事件记录
        if (eventDic[eventName] == null)
        {
            eventDic.Remove(eventName);
        }
    }

    /// <summary>
    /// 清空所有事件监听。
    /// </summary>
    public void Clear()
    {
        eventDic.Clear();
    }

    /// <summary>
    /// 清空指定事件的所有监听。
    /// </summary>
    public void Clear(string eventName)
    {
        if (eventDic.ContainsKey(eventName))
        {
            eventDic.Remove(eventName);
        }
    }
}

2. Enemy.cs

using UnityEngine;

public class Enemy : MonoBehaviour
{
    public string enemyName = "普通怪兽";
    public int enemyID = 1;
    public int Hp = 5;

    private bool isDead;

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.J) && !isDead)
        {
            Hp--;
            Debug.Log($"{enemyName}扣血,剩余生命值:{Hp}");

            if (Hp <= 0)
            {
                Die();
            }
        }
    }

    private void Die()
    {
        isDead = true;
        Debug.Log($"{enemyName}死亡");

        // 将当前死亡的 Enemy 作为参数传给事件中心
        EventMgr.Instance.EventTrigger(
            EventMgr.enemyDieEvent,
            this
        );
    }
}

3. Level.cs

using UnityEngine;

public class Level : MonoBehaviour
{
    private void Awake()
    {
        EventMgr.Instance.AddEventListener(
            EventMgr.enemyDieEvent,
            ClearLevel
        );
    }

    // 带参数事件的监听方法必须接收一个 object
    private void ClearLevel(object info)
    {
        Enemy enemy = info as Enemy;

        if (enemy == null)
        {
            Debug.LogError("敌人死亡事件传入的数据不是 Enemy");
            return;
        }

        Debug.Log(
            $"击败敌人:{enemy.enemyName},游戏成功通关"
        );
    }

    private void OnDestroy()
    {
        EventMgr.Instance.RemoveEventListener(
            EventMgr.enemyDieEvent,
            ClearLevel
        );
    }
}

4. Player.cs

using UnityEngine;

public class Player : MonoBehaviour
{
    private void Awake()
    {
        EventMgr.Instance.AddEventListener(
            EventMgr.enemyDieEvent,
            UpGrade
        );
    }

    // 带参数事件的监听方法必须接收一个 object
    private void UpGrade(object info)
    {
        Enemy enemy = info as Enemy;

        if (enemy == null)
        {
            Debug.LogError("敌人死亡事件传入的数据不是 Enemy");
            return;
        }

        Debug.Log(
            $"击败编号为 {enemy.enemyID} 的敌人,人物升级"
        );
    }

    private void OnDestroy()
    {
        EventMgr.Instance.RemoveEventListener(
            EventMgr.enemyDieEvent,
            UpGrade
        );
    }
}

运行后连续按下 J,敌人生命值归零时会输出:

普通怪兽死亡
击败敌人:普通怪兽,游戏成功通关
击败编号为 1 的敌人,人物升级
5G NR Rel16测量上报事件深度解析:从A1到I1的触发机制与应用场景 本文深度解析5G NR Rel16测量上报事件,从A1到I1的触发机制与应用场景。详细介绍了事件触发上报的核心作用、Rel16新增的I1事件干扰检测功能,以及关键参数配置和典型应用场景优化策略。通过实际案例展示如何利用测量上报事件提升网络性能,特别适合5G网络优化工程师参考。 阅读详情

相关推荐

SC9S08MZ16 TPM模块PWM配置:边沿对齐与中心对齐模式详解

脉宽调制(PWM)是嵌入式系统中实现模拟信号控制的核心技术,通过快速切换数字信号的高低电平来模拟连续变化的电压或电流。其工作原理基于定时器模块的计数器与比较寄存器协同工作,通过调节占空比来控制输出信号的平均功率。PWM的技术价值在于能够高效、精确地实现电机调速、LED调光、电源转换等应用,同时降低系统功耗和热量产生。在电机控制、数字音频和开关电源等场景中,PWM的稳定性和精度直接决定了系统性能。本文聚焦于飞思卡尔SC9S08MZ16 MCU的TPM模块,深入解析其边沿对齐和中心对齐两种PWM模式,帮助开发者

weixin_33957648的博客 418

探秘 Android DataBinding:事件参数传递与 Lambda 表达式应用(16)

Android DataBinding 作为一种强大的框架,能够将布局文件中的视图与数据进行绑定,极大地简化了 Android 应用的开发过程。在事件处理方面,DataBinding 提供了简洁且灵活的方式来处理各种用户交互事件,包括点击、长按、滑动等。

Android开发领域创作者 917

FMOD:FMOD事件与参数控制详解_2024-07-16_15-25-04.Tex

FMOD事件系统是FMOD Studio的核心,它允许开发者通过事件来组织和控制游戏中的音频。一个事件可以包含多个音频片段,以及各种音频效果和参数控制。事件系统提供了事件的加载、播放、停止、暂停等功能,使得音频的控制更加灵活和高效。在FMOD中,参数(Parameters)是用于在运行时动态调整音频事件的音量、音调、效果器设置等的一种机制。通过定义参数,开发者可以在游戏或应用中根据玩家的行为、环境变化或其他动态因素来实时调整音频输出,从而增强沉浸感和交互性。

943

5G NR Rel16测量上报事件全解析:从A1到I1的实战避坑指南

本文深入解析了5G NR Rel16标准中的测量上报事件,从A1到I1逐一进行实战拆解。重点剖析了同频切换基石A3事件的参数配置陷阱、跨系统切换B系列事件的优化要点,并探讨了Rel16新增I1事件的潜在应用。文章提供了一份从参数规划到日志分析的端到端排障指南,旨在帮助网络优化工程师和开发人员规避常见配置错误,提升移动性管理性能。

x1y2z的博客 709

物联网 Mixly-智能楼道灯

一、实验目的及要求 熟悉声音及人体红外传感器用法。 二、实验原理与内容 1.使用声音传感器实现声控灯功能。 2.使用人体红外传感器实现人体检测控制灯功能。 三、实验软硬件环境 硬件:Arduino、LED灯、声音传感器、人体红外传感器 软件:Mixly IDE 四、实验过程(实验步骤、记录、数据、分析) 核心代码截图 声控灯: 人体红外检测灯: 3.实验效果图: (1)、声控灯总线连接: (1)、声控灯声音大于一某个值时灯亮,经过2秒后灯灭: (3)、人体红外检测灯连接总线: (4)、人体红外

qq_43430810的博客 1916

2024年【MCM/ICM】美国大学生数学建模竞赛优秀论文(免费下载)

美国大学生数学建模竞赛(MCM/ICM)由美国数学及其应用联合会主办,是最高的国际性数学建模竞赛,也是世界范围内最具影响力的数学建模竞赛,一般也指数学建模竞赛。赛题内容涉及经济、管理、环境、资源、生态、医学、安全、等众多领域。竞赛要求三人(本科生和研究生均可参加)为一组,在四天时间内,就指定的问题完成从建立模型、求解、验证到论文撰写的全部工作,体现了参赛选手研究问题、解决方案的能力及团队合作精神。为现今各类数学建模竞赛之鼻祖。

weixin_43608857的博客 1839

React@16.x(19)事件的处理

事件的处理

qq_40147756的博客 732

Oracle EBS订单的流程(Order->AR)

基本流程创建订单路径:Order Management > Orders,Returns > Sales Orders填写订单头信息,客户,订单类型,销售人员填写订单体信息,输入物料,数量...然后Book Order,订单Book之后,你会发现订单头的Status的状态变成了“Booked”,订单行的状态为"Awaiting Shipping",记录下来你的订单号,后边的每一步都需要这个订单号。

田攀的日志 4万+

16、什么是事件委托

rem布局原理 rem:相对于根元素(即 html 元素)font-size 计算值的倍数。通俗的说,1rem = html 的 font-size 值 这段代码。a 标签的 font-size 值为 0.5rem,实际就是 100px*0.5=50px。 html{font-size:100px;} a{font-size:.5rem;} 如何使用 rem 进行布局? 1.标签的 rem 单位的值怎么计算 通过使用 rem + js 改变 html 标签的 font-size(整体缩放)实现兼容性

派大星儿的博客 718

GhidrAssist:AI驱动的逆向工程助手实战指南

逆向工程是分析软件内部工作原理、理解二进制代码逻辑的关键技术,广泛应用于软件安全、恶意代码分析和漏洞挖掘等领域。其核心原理在于通过反编译、控制流与数据流分析等手段,将机器码还原为可理解的高级语言表示。传统逆向分析高度依赖人工经验,面对海量代码时效率低下且易出错。随着大语言模型(LLM)技术的发展,其强大的代码理解与推理能力为自动化逆向分析提供了新的可能。通过将LLM与成熟的逆向工程框架(如Ghidra)相结合,可以构建智能辅助系统,实现代码意图的自动解释、变量/函数的智能重命名以及潜在漏洞模式的辅助识别,从

weixin_42547335的博客 596

Folia 快速上手指南:3 分钟放完第一首歌,摸清全屏歌词动画播放器

你刚装完 Folia,双击图标,屏幕先暗下来,中央浮出一排带立体感的专辑卡片,左上角一个齿轮,顶部一个搜索框——这就是它给你的第一印象。Folia 是一款主打全屏沉浸式歌词动画的播放器:本地曲库、Navidrome、网易云、QQ、酷歌等在线平台都能放,桌面端还支持波点音乐、Spotify 等。接下来 3 分钟,带你放完第一首歌、记住高频按钮的位置,再挑两处设置动一下,剩下的用到哪块再翻哪块。 [

gitblog_00651的博客 1079

OPENSSL使用方法

预备知识KEY 通常指私钥。CSR 是 Certificate Signing Request 的缩写,即证书签名请求,这不是证书,只是包含申请证书的基本信息。生成证书时要把这个提交给权威的证书颁发机构,颁发机构审核通过之后,再根据这些申请信息生成相应的证书。CRT 即 certificate的缩写,即证书。 X.509 是一种证书格式。对X.509证书来说,认证者总是CA或由CA指定的人,一份...

zxm8513优快云博客 1212

5G NR Rel16测量上报事件解析:从A1到I1的触发机制与应用场景

本文深入解析了5G NR Rel16中的测量上报事件机制,从A1到I1的触发原理与应用场景。文章回顾了Rel15的经典事件,并重点探讨了Rel16新增的I1事件如何通过干扰测量实现网络质量优化。通过实战案例,详细说明了参数配置对切换成功率、网络负载均衡及用户体验的关键影响,为5G网络优化提供了专业指导。

weixin_29276847的博客 183

大数据面试必考题:Spark数据倾斜问题总结和优化措施

在Spark分布式计算环境中,

大模型大数据攻城狮的专栏 1465

Qt —— 在Win11下“Qt for Android“开发环境,通过USB在真机(华为Meta60 PRO)上调试运行,并打包APK并在真实手机运行

Qt —— 在Win11下“Qt for Android“开发环境,打包APK并在真实手机运行

310

bootstraptable append 没有events事件_从源码看React16事件机制-事件合成

前言在事件注册部分,你有可能有下面几个困扰: 为什么所有注册的事件的回调都是一个dispatchEvent,它到底是怎么运作的呢? 事件注册部分从头到尾都没有用到我们传入的事件回调,仅仅对我们想要绑定的事件做了一些处理(绑定依赖等等),那React是怎么正确执行我们指定的回调的呢?别急,在继续讲下去之前,我们要先聊一下React16与之前版本的最大区别:Fiber架构对于16之前的React来...

weixin_36353849的博客 111

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

onchange事件触发不了_从源码看React16事件机制-事件合成

前言在事件注册部分,你有可能有下面几个困扰: 为什么所有注册的事件的回调都是一个dispatchEvent,它到底是怎么运作的呢? 事件注册部分从头到尾都没有用到我们传入的事件回调,仅仅对我们想要绑定的事件做了一些处理(绑定依赖等等),那React是怎么正确执行我们指定的回调的呢?别急,在继续讲下去之前,我们要先聊一下React16与之前版本的最大区别:Fiber架构对于16之前的React来...

weixin_39939303的博客 534

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

button添加插槽之后绑定不来事件_小前端读源码 React16.7.0(合成事件)

在上一篇文章中,我们说到了setState的过程。但是在阅读的过程中,发现setState的很多东西是依赖着合成事件去对我们的事件做一个分发处理和批量更新的。所以这篇文章就是以搞懂合成事件为目的对源码进行阅读的。Lam:小前端读源码 - React16.7.0(深入了解setState)zhuanlan.zhihu.com官方对合成事件的一些说明:SyntheticEvent – Rea...

weixin_39554170的博客 112

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

button添加插槽之后绑定不来事件_小前端读源码 - React16.7.0(合成事件)

。在上一篇文章中,我们说到了setState的过程。但是在阅读的过程中,发现setState的很多东西是依赖着合成事件去对我们的事件做一个分发处理和批量更新的。所以这篇文章就是以搞懂合成事件为目的对源码进行阅读的。Lam:小前端读源码 - React16.7.0(深入了解setState)​zhuanlan.zhihu.com官方对合成事件的一些说明:SyntheticEvent – React​...

weixin_36349685的博客 172

React事件处理的方式/绑定this的5种方式/事件回调函数传递参数

一、在React元素绑定事件要注意的三点 1、React中事件的命名采用驼峰命名法,而不是原生dom中的小写。 如:onclick要写成onClick,onchange要写成onChange 2、使用 JSX 语法时你需要传入一个函数作为事件处理函数,而不是以dom字符串的形式 在dom中: <button οnclick=“clickMe()”>不服点我</button> React中: <button onClick={clickButton}>不服点我&l

祥哥的说 2300

BLE连接事件功耗优化详解

摘要:本文深入探讨了低功耗蓝牙(BLE)物联网设备在连接事件中的功耗优化策略。通过分析连接事件的基本原理和流程,提出两大核心优化方向:缩短射频收发时间和实施快速睡眠策略。具体优化方法包括调整数据包长度、提升传输速率、优化连接参数,以及采用事件驱动的异步处理架构。文章提供了完整的优化路线图和实战案例,强调在吞吐量、响应性和可靠性之间进行权衡的重要性。最后给出了可操作的优化清单,建议结合专业工具进行验证,以实现最佳的功耗表现。

油墨香^-^的博客 375

React 合成事件 SyntheticEvent

React 合成事件

weixin_47431743的博客 1130

iview里render添加双击事件_小前端读源码 - React16.7.0(合成事件)

。在上一篇文章中,我们说到了setState的过程。但是在阅读的过程中,发现setState的很多东西是依赖着合成事件去对我们的事件做一个分发处理和批量更新的。所以这篇文章就是以搞懂合成事件为目的对源码进行阅读的。Lam:小前端读源码 - React16.7.0(深入了解setState)​zhuanlan.zhihu.com官方对合成事件的一些说明:SyntheticEvent – React​...

weixin_39938855的博客 400

【JVM】对象内存布局

HotSpot JVM 中,Java 对象内存布局由对象头(12字节,含Mark Word与压缩Klass Pointer)、实例数据及对齐填充构成,总大小为8字节倍数。对象头支持锁状态动态复用,指针压缩使引用仅4字节,但堆超32GB时失效。实例字段按类型优先级重排序以减少间隙,最小对象大小为16字节。通过JOL工具可精准验证布局,理解锁机制、GC、伪共享等底层行为。

2301_79732484的博客 149
上一篇: 15.事件中心:实现
下一篇: 17.事件中心优化:泛型参数
Unity黑马王子
博客等级 码龄4年 1846粉丝 181原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值