【unity实战】事件(Event)的基本实战使用

news2025/3/11 6:21:27

文章目录

  • 最终效果
  • 前言
  • 一、素材
  • 二、角色金币交互
    • 1. 拾取金币
    • 2. 显示金币数UI
  • 完结

最终效果

在这里插入图片描述

前言

之前我们介绍过委托的用法,具体可以跳转:【unity小技巧】委托(Delegate)的基础使用和介绍

这期来讲讲事件,使用你会发现它和委托真的很像,那么他们具体有什么区别呢?

在Unity中,事件(Event)和委托(Delegate)是两种不同的概念,它们之间有一些区别:

  1. 委托(Delegate)

    • 委托是一种类型,用于引用一个或多个方法。委托可以看作是函数指针或函数的代理。
    • 委托用于实现回调函数、事件处理和方法的动态绑定。
    • 委托是一种类型安全的方式来封装方法调用。
  2. 事件(Event)

    • 事件是建立在委托之上的高级概念,它提供了一种更加简洁、安全的方式来实现观察者模式。
    • 事件使用委托来通知其他对象或类,当特定情况发生时,让它们执行相应的操作。
    • 事件可以通过“+=”(添加订阅者)和“-=”(移除订阅者)来管理委托的订阅和取消订阅。

何时使用事件和委托

  • 当需要实现一对多的消息传递时,可以使用事件。比如,当某个对象的状态发生变化时,需要通知多个其他对象做出相应的反应。
  • 当需要回调函数或方法引用时,可以使用委托。比如,当某个操作完成后需要执行特定的方法,可以使用委托来实现回调。

综合来说,事件和委托在Unity开发中都有各自的用途,根据具体情况选择合适的方式来实现功能会更加方便和有效。

一、素材

https://assetstore.unity.com/packages/2d/environments/pixel-art-top-down-basic-187605
在这里插入图片描述

二、角色金币交互

1. 拾取金币

金币事件,定义当金币增加时触发的事件

public class GoldEvents
{
    public event Action<int> onGoldGained; // 当金币增加时触发的事件
    public void GoldGained(int gold) 
    {
        onGoldGained?.Invoke(gold); // 触发金币增加事件
    }
}

游戏事件管理中心,初始化各种事件

public class GameEventsManager : MonoBehaviour
{
    public static GameEventsManager instance { get; private set; } // 单例实例
    
    public GoldEvents goldEvents; // 金币事件

    private void Awake()
    {
        if (instance != null)
        {
            Debug.LogError("在场景中找到多个游戏事件管理器"); // 如果场景中存在多个游戏事件管理器,则输出错误信息
        }
        instance = this; // 设置单例实例为当前实例
        
        // 初始化所有事件
        goldEvents = new GoldEvents(); // 初始化金币事件
    }
}

挂载脚本
在这里插入图片描述

管理玩家的金币,注册金币增加事件执行方法

// GoldManager类,负责管理玩家的金币
public class GoldManager : MonoBehaviour
{
    [Header("Configuration")]
    // 游戏开始时玩家拥有的金币数量
    [SerializeField] private int startingGold = 5;

    // 当前玩家持有的金币数量,外部只能获取不能设置
    public int currentGold { get; private set; }

    // 在对象被激活时调用,初始化玩家的金币数量
    private void Awake()
    {
        currentGold = startingGold;
    }

    // 注册事件监听器
    private void OnEnable() 
    {
        // 当玩家获得金币时,注册GoldGained方法来处理事件
        GameEventsManager.instance.goldEvents.onGoldGained += GoldGained;
    }

    // 注销事件监听器
    private void OnDisable() 
    {
        // 当对象被禁用时,取消注册GoldGained方法
        GameEventsManager.instance.goldEvents.onGoldGained -= GoldGained;
    }

    // 处理获得金币的事件
    private void GoldGained(int gold) 
    {
        // 增加玩家的金币数量
        currentGold += gold;
    }
}

配置脚本
在这里插入图片描述

设置脚本执行顺序,在Unity的"Project Settings"中,你可以通过"Script Execution Order"设置脚本的执行顺序,确保GameEventsManager的Awake方法总是在其他依赖它的组件之前执行,不然可能会报错。
在这里插入图片描述

定义金币脚本,控制金币拾取和金币重新生成

[RequireComponent(typeof(CircleCollider2D))]
public class Coin : MonoBehaviour
{
    [Header("Config")]
    [SerializeField] private float respawnTimeSeconds = 8; // 重生时间
    [SerializeField] private int goldGained = 1; // 获得的金币数量

    private CircleCollider2D circleCollider; // 圆形碰撞体
    private SpriteRenderer visual; // 视觉元素

    private void Awake() 
    {
        // 初始化圆形碰撞体和视觉元素
        circleCollider = GetComponent<CircleCollider2D>();
        visual = GetComponentInChildren<SpriteRenderer>();
    }

    // 收集金币的方法
    private void CollectCoin() 
    {
        circleCollider.enabled = false;
        visual.enabled = false;
        // 触发获得金币事件
        GameEventsManager.instance.goldEvents.GoldGained(goldGained);
        StopAllCoroutines();
        StartCoroutine(RespawnAfterTime());
    }

    // 在一定时间后重生金币
    private IEnumerator RespawnAfterTime()
    {
        yield return new WaitForSeconds(respawnTimeSeconds);
        circleCollider.enabled = true;
        visual.enabled = true;
    }

    // 触发进入触发器事件
    private void OnTriggerEnter2D(Collider2D otherCollider) 
    {
        if (otherCollider.CompareTag("Player"))
        {
            CollectCoin();
        }
    }
}

金币挂载脚本
在这里插入图片描述
运行效果
在这里插入图片描述
拾取金币后,currentGold加1,说明没问题
在这里插入图片描述

2. 显示金币数UI

一直查看金币变量数据变化,不是很方便,我们可以让金币数显示出来

修改GoldEvents,新增金币变化事件

public class GoldEvents
{
	//。。。
	
    public event Action<int> onGoldChange; // 当金币数量变化时触发的事件
    public void GoldChange(int gold) 
    {
        onGoldChange?.Invoke(gold); // 触发金币变化事件
    }
}

新增GoldUI,注册金币数量发生变化时调用的方法

public class GoldUI : MonoBehaviour
{
    [Header("Components")]
    // 用于显示金币数量的TextMeshProUGUI组件
    [SerializeField] private TextMeshProUGUI goldText;

    // 在对象激活时注册事件监听器
    private void OnEnable() 
    {
        // 当金币数量发生变化时,注册GoldChange方法来处理事件
        GameEventsManager.instance.goldEvents.onGoldChange += GoldChange;
    }

    // 在对象禁用时注销事件监听器
    private void OnDisable() 
    {
        // 当对象被禁用时,取消注册GoldChange方法
        GameEventsManager.instance.goldEvents.onGoldChange -= GoldChange;
    }

    // 处理金币数量变化的事件
    private void GoldChange(int gold) 
    {
        // 将金币数量转换为字符串,并更新UI显示
        goldText.text = gold.ToString();
    }
}

同样配置GoldUI 脚本执行顺序
在这里插入图片描述

挂载脚本
在这里插入图片描述
修改GoldManager,广播当前金币数量的改变事件

// 在第一帧更新之前调用,广播当前金币数量的改变
private void Start()
{
    GameEventsManager.instance.goldEvents.GoldChange(currentGold);
}

// 处理获得金币的事件
private void GoldGained(int gold) 
{
    // 增加玩家的金币数量
    currentGold += gold;
    // 广播金币数量的变化
    GameEventsManager.instance.goldEvents.GoldChange(currentGold);
}

效果
在这里插入图片描述

完结

赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注,以便我第一时间收到反馈,你的每一次支持都是我不断创作的最大动力。当然如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦!

好了,我是向宇,https://xiangyu.blog.csdn.net

一位在小公司默默奋斗的开发者,出于兴趣爱好,最近开始自学unity,闲暇之余,边学习边记录分享,站在巨人的肩膀上,通过学习前辈们的经验总是会给我很多帮助和启发!php是工作,unity是生活!如果你遇到任何问题,也欢迎你评论私信找我, 虽然有些问题我也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~

在这里插入图片描述

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

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

相关文章

IDEA稀奇古怪问题的解决方案

idea在电脑死机重启后&#xff0c;启动项目报错 尝试了各种办法&#xff0c;重新导入项目&#xff0c;删除.idea文件重新导入&#xff0c;把本地代码删除重新pull下来再次导入&#xff0c;均无法解决。而且代码在eclipse中可以正常启动&#xff0c;遂排除代码和网络环境原因。…

【VTKExamples::PolyData】第四十九期 Silhouette

很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ:870202403 前言 本文分享VTK样例Silhouette,并解析接口vtkPolyDataSilhouette,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步! 你的点赞就是我的动力(^U^)ノ~YO 1. Silhouett…

消息队列实现AB进程对话

进程A代码&#xff1a; #include <stdio.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>#include <stdlib.h>#include <string.h>#define MSG_EXCEPT 020000struct msgbuf{long mtype;char mtext[100];};int main(in…

Redis6 搭建主从集群架构

文章目录 搭建Redis主从集群架构1.集群结构2.准备实例和配置3.启动4.开启主从关系5.测试 搭建Redis主从集群架构 安装部署单机版Redis6可参考&#xff1a; 安装部署单机版Redis6 1.集群结构 我们搭建的主从集群结构如图&#xff1a; 我们计划是在一台虚拟机里去部署三个R…

Docker数据卷篇

1. 数据卷&#xff08;容器数据管理&#xff09; 引言&#xff1a;在之前的nginx案例中&#xff0c;修改nginx的html页面时&#xff0c;需要进入nginx内部。并且因为没有编辑器&#xff0c;修改文件也很麻烦。 这就是因为容器与数据&#xff08;容器内文件&#xff09;耦合带…

重新下载各种编辑器、软件

全是资源编辑器&#xff0c;书写&#xff0c;有需要书写资料或者是代码编程的可以找我呀&#xff0c;闲暇时间接一下副业。 git任务也重启了&#xff0c;原家厨房项目也重启了&#xff0c;浓心项目也在重启。如下图 后续再慢慢联系吧&#xff0c;先书写到这里&#xff0c;晚安…

Day29-Ubuntu介绍及企业标准安装实战

Day29-Ubuntu介绍及企业标准安装实战 第1章 Ubuntu Linux系统介绍1.Ubuntu是什么2.Ubuntu Linux基本特点3.为什么要讲Ubuntu&#xff1f;4.Ubuntu服务器版本选择5.如何学习Ubuntu使用6.Linux发展前景说明简介 第2章 Ubuntu安装环境搭建准备第3章 Ubuntu安装实战1. 开机安装Ubun…

【无标题】day6网路

#include<myhead.h> int main(int argc, const char *argv[]) {int workid 0;char name[20] "";double salary 0;sqlite3 *ppDb NULL;//数据库句柄指针//打开数据库&#xff0c;如果数据库不存在&#xff0c;则创建数据库//将数据库句柄由参数2返回if((sql…

JVM工作原理与实战(四十二):JVM常见面试题目

专栏导航 JVM工作原理与实战 RabbitMQ入门指南 从零开始了解大数据 目录 专栏导航 前言 一、JVM常见面试题目 1.请阐述JVM的概念及其核心功能&#xff0c;并简要介绍其组成部分和常用的实现。 2.请阐述Java字节码文件的组成部分。 3.请描述JVM的运行时数据区及其组成部分…

Android中的传感器类型和接口名称

本文将介绍传感器坐标轴、基础传感器和复合传感器&#xff08;动作传感器、姿势传感器、未校准传感器和互动传感器&#xff09;。 1. 传感器坐标轴 许多传感器的传感器事件值在相对于设备静止的特定坐标系中表示。 1.1 移动设备坐标轴 Sensor API 仅与屏幕的自然方向相关&a…

前端将html导出pdf文件解决分页问题

这是借鉴了qq_251025116大佬的解决方案并优化升级完成的&#xff0c;原文链接 1.安装依赖 npm install jspdf html2canvas2.使用方法 import htmlToPdffrom ./index.jsconst suc () > {message.success(success);};//记得在需要打印的div上面添加 idlet dom document.que…

operator-sdk入门(mac)

1. 安装operator-sdk brew install operator-sdk 2. 安装kubebuilder brew install kubebuilder 3.初始化一个operator脚手架 3.1 新建一个文件夹 redis-operator 3.2 执行初始化 operator-sdk init --domain lyl.com --repo github.com 参数介绍 可以通过operator-sdk --…

HTML静态网页成品作业(HTML+CSS)——图书出版社介绍设计制作(6个页面)

&#x1f389;不定期分享源码&#xff0c;关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 &#x1f3f7;️本套采用HTMLCSS&#xff0c;未使用Javacsript代码&#xff0c;共有6个页面。 &#x1f3f7;️想要…

idea手动导入插件

idea有时候连接不上 我们去手动下载压缩包 插件网址 选择下载的压缩包导入 导入成功

Intel CPU体系结构

原文来自一文解析&#xff0c;Linux内核——Intel CPU体系结构 本文主要介绍Intel CPU体系结构&#xff0c;以供读者能够理解该技术的定义、原理、应用。 &#x1f3ac;个人简介&#xff1a;一个全栈工程师的升级之路&#xff01; &#x1f4cb;个人专栏&#xff1a;计算机杂记…

RabbitMQ(任务模型,交换机(广播,订阅,通配符订阅))

一.WorkQueues模型 WorkQueues(任务模式):让多个消费者绑定到一个队列&#xff0c;共同消费队列中的消息。 架构: 所需场景: 当消息处理比较耗时的时候&#xff0c;可能生产消息的速度会远远大于消息的消费速度。长此以往&#xff0c;消息就会堆积越来越多&#xff0c;无法及…

大数据开发-Hadoop之MapReduce

文章目录 MapReduce原理剖析MapReduce之Map阶段MapReduce之Reduce阶段WordCount分析多文件WordCount分析 实战wordCount案例开发 MapReduce原理剖析 MapReduce是一种分布式计算模型,主要用于搜索领域&#xff0c;解决海量数据的计算问题MapReduce由两个阶段组成&#xff1a;Ma…

热红外图像直方图修正显示

热红外图像的直方图修正是一种用于增强图像对比度和可视化细节的技术。下面是一个使用Python和OpenCV库实现直方图均衡化的示例代码&#xff1a; import cv2 import numpy as np# 读取热红外图像 image cv2.imread(thermal_image.png, cv2.IMREAD_GRAYSCALE)# 对图像进行直方…

植被生长动态与多时间尺度干旱事件的关联性研究

随着全球气候变暖的趋势愈发明显&#xff0c;干旱事件不仅发生的频率增加&#xff0c;其持续时间和影响范围也在不断扩大。干旱对生态环境造成了严重破坏&#xff0c;导致生物多样性减少、土地退化和水资源短缺&#xff1b;对农业生产而言&#xff0c;干旱会导致作物减产甚至绝…

Java精品项目--第5期基于SpringBoot的高速收费系统的设计分析与实现

项目使用技术栈 SpringBootMavenShiroMySQLMybatis-PlusJavaJDK1.8HTML 系统介绍 项目截图