【unity小技巧】unity事件系统创建通用的对象交互的功能

文章目录

  • 前言
  • 实现
    • 1. **InteractEvent 类**:
    • 2. **Interact 类**:
    • 3. **Player 类**:
    • 4. **Chest 类**:
  • 工作流程说明:
  • 开单个箱子
  • 按钮触发打开很多箱子
  • 拾取物品(传参)
  • 参考
  • 完结

前言

游戏开发过程中,要实现玩家和物体之间的交互是非常常见的事情。如果在开发过程中,你希望和箱子交互触发开箱子的方法,和门交互,又触发开门的方法,实现方式其实有很多,比如继承同一个分类或者定义一个接口就是不错的方法,门和箱子都继承这个接口,然后各自重写方法接口里面的触发方法。

但是,如果我说要实现点击一个按钮,打开几个箱子同时开启几个门呢?你可能会说我先获取所有的箱子或者门,然后循环遍历执行里面对应的触发方法不就可以了?当然这种方法是可行的,但是不够优雅。今天我就分享一种使用委托和事件的方式来实现一个通用的物品的交互方式。

至于什么是委托和事件,之前文章我已经有所介绍了,感兴趣可以先去看看:
【unity小技巧】委托(Delegate)的基础使用和介绍
【unity实战】事件(Event)的基本实战使用

实现

1. InteractEvent 类

  • InteractHandler 委托: 定义了一个没有参数和返回值的委托类型。
  • HasInteracted 事件: 事件,当触发时调用所有注册的委托。

方法:

  • CallInteractEvent 方法: 触发 HasInteracted 事件,如果有订阅者,则调用它们。
public class InteractEvent
{public delegate void InteractHandler();public event InteractHandler HasInteracted;// 调用互动事件public void CallInteractEvent() => HasInteracted?.Invoke();
}

2. Interact 类

  • InteractEvent interact: 这是一个 InteractEvent 类的实例,用于处理交互事件。
  • Player player: 用于存储与之交互的玩家实例。

属性和方法:

  • GetInteractEvent 属性: 返回 InteractEvent 实例。如果 interact 为 null,会在首次访问时初始化。
  • GetPlayer 属性: 返回存储的玩家实例。
  • CallInteract 方法: 接受一个 Player 参数,设置 player 属性为该参数,然后调用 interactCallInteractEvent 方法。
public class Interact : MonoBehaviour
{InteractEvent interact = new InteractEvent();Player player;// 获取互动事件public InteractEvent GetInteractEvent{get{if (interact == null)interact = new InteractEvent();return interact;}}// 获取玩家public Player GetPlayer{get { return player; }}// 调用互动方法public void CallInteract(Player interactedPlayer){player = interactedPlayer;interact.CallInteractEvent();}
}

3. Player 类

  • Update 方法: 每帧检查玩家是否按下 E 键,如果是,则调用 PlayerInteract 方法。
  • PlayerInteract 方法: 创建一条射线从相机的视口中心向前发射,然后检测是否击中了特定层级(层0和层3)的物体。如果击中了一个具有 Interact 组件的物体,则调用其 CallInteract 方法,并传递自身实例。
public class Player : MonoBehaviour
{void Update(){// 如果玩家按下E键,进行交互操作if (Input.GetKeyDown(KeyCode.E)){PlayerInteract();}}// 处理玩家交互的函数public void PlayerInteract(){// 定义用于层0和层3的层蒙版,0和3图层都可以满足条件var layerMask0 = 1 << 0;var layerMask3 = 1 << 3;var finalMask = layerMask0 | layerMask3;// 从屏幕中心创建一条射线Ray ray = Camera.main.ViewportPointToRay(new Vector3(.5f, .5f, 0));// 进行射线投射,检查在最终蒙版上是否命中物体(距离不超过15个单位)RaycastHit hit;if (Physics.Raycast(ray, out hit, 15, finalMask)){// 从命中的物体获取Interact脚本组件Interact interactScript = hit.transform.GetComponent<Interact>();// 如果Interact脚本组件存在,调用其CallInteract方法并传递玩家实例if (interactScript != null){interactScript.CallInteract(this);}}}
}

4. Chest 类

  • Interact openFromInteraction: 存储一个 Interact 类的实例,用于处理与宝箱的交互。

方法:

  • OnEnable 方法: 当对象激活时,订阅 openFromInteractionHasInteracted 事件到 OpenChest 方法。
  • OnDisable 方法: 当对象禁用时,取消订阅 openFromInteractionHasInteracted 事件。
  • OpenChest 方法: 当宝箱应该打开时调用,可以在其中添加具体的打开宝箱逻辑,例如生成掉落物品。
public class Chest : MonoBehaviour
{public Interact interact;// 当对象启用时订阅交互事件private void OnEnable(){if (interact != null){interact.GetInteractEvent.HasInteracted += OpenChest;}}// 当对象禁用时取消订阅交互事件private void OnDisable(){if (interact != null){interact.GetInteractEvent.HasInteracted -= OpenChest;}}// 处理宝箱打开的函数public void OpenChest(){// 掉落一些酷炫的东西}
}

工作流程说明:

  • Player 类中的 PlayerInteract 方法检测玩家按下 E 键后,发射一条射线检测是否与可交互物体碰撞。
  • 如果射线击中了具有 Interact 组件的物体,就调用其 CallInteract 方法,并传递玩家实例。
  • Interact 类中的 CallInteract 方法将玩家实例存储,并调用其内部的 InteractEvent 实例的 CallInteractEvent 方法,从而触发 HasInteracted 事件。
  • Chest 类中的 OnEnable 方法在对象启用时订阅 HasInteracted 事件,当事件触发时调用 OpenChest 方法来打开宝箱。

开单个箱子

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

按钮触发打开很多箱子

我们可以让一个按钮与多个对象进行交互,挂载脚本
在这里插入图片描述
效果
在这里插入图片描述

拾取物品(传参)

带玩家参数的拾取物品功能,脚本挂载在物体预制体上即可

public class ItemPickup : MonoBehaviour
{public string item; // 物品名称public int amount; // 物品数量public Interact interact; // 拾取物品的交互对象private void OnEnable(){Interact getInteract = GetComponent<Interact>();if (getInteract == null){getInteract = gameObject.AddComponent<Interact>(); // 如果没有,则添加Interact组件   }interact = getInteract;interact.GetInteractEvent.HasInteracted += InteractPickup;}private void OnDisable(){if (interact){interact.GetInteractEvent.HasInteracted -= InteractPickup; // 取消监听交互事件}}public void InteractPickup(){AddItem(interact.GetPlayer); // 执行AddItem方法,传入交互对象的玩家信息}public void AddItem(Player player){// 给玩家添加物品的逻辑在这里实现}
}

参考

https://www.youtube.com/watch?v=MdOi9ymb07s

完结

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

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

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

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue中用JSON格式查看数据(vue-json-viewer)

vue中把string用JSON格式展示数据 vue-json-viewer使用 官网地址&#xff1a;https://www.npmjs.com/package/vue-json-viewer 1. 安装插件vue-json-viewer //vue2 npm install vue-json-viewer2 --save //vue3 npm install vue-json-viewer3 --save2. 引入vue-json-viewer…

Kubernetes Dashboard

Minikube 环境搭建 Kubernetes 的基本架构 Kubernetes 声明式语言 YAML YAML操作Kubernetes核心对象 CentOs搭建Kubernetes集群 Kubernetes进阶对象Deployment、DaemonSet、Service Kubernetes进阶对象Ingress、Ingress Class、Ingress Controller Kubernetes集群部署项目实践 …

本地离线模型搭建指南-中文大语言模型底座选择依据

搭建一个本地中文大语言模型&#xff08;LLM&#xff09;涉及多个关键步骤&#xff0c;从选择模型底座&#xff0c;到运行机器和框架&#xff0c;再到具体的架构实现和训练方式。以下是一个详细的指南&#xff0c;帮助你从零开始构建和运行一个中文大语言模型。 本地离线模型搭…

基于Springboot + vue 的抗疫物质管理系统的设计与实现

目录 &#x1f4da; 前言 &#x1f4d1;摘要 &#x1f4d1;系统流程 &#x1f4da; 系统架构设计 &#x1f4da; 数据库设计 &#x1f4da; 系统功能的具体实现 &#x1f4ac; 系统登录注册 系统登录 登录界面 用户添加 &#x1f4ac; 抗疫列表展示模块 区域信息管理 …

APP自动化测试-Appium常见操作之详讲

一、基本操作 1、点击操作 示例&#xff1a;element.click() 针对元素进行点击操作 2、初始化&#xff1a;输入中文的处理 说明&#xff1a;如果连接的是虚拟机&#xff08;真机无需加这两个参数&#xff0c;加上可能会影响手工输入&#xff09;&#xff0c;在初始化配置中…

【初阶数据结构】深入解析栈:探索底层逻辑

&#x1f525;引言 本篇将深入解析栈:探索底层逻辑&#xff0c;理解底层是如何实现并了解该接口实现的优缺点&#xff0c;以便于我们在编写程序灵活地使用该数据结构。 &#x1f308;个人主页&#xff1a;是店小二呀 &#x1f308;C语言笔记专栏&#xff1a;C语言笔记 &#x1…

论坛实现随机发帖的学习

1、badboy操作&#xff0c;录制发帖全过程&#xff0c;录制结果保存&#xff0c;生成为.jmx格式的文件 2、在Jmeter中打开该.jmx文件&#xff0c;重命名&#xff0c;便于了解步骤 3、生成结果树&#xff0c;查看所以步骤是否正确 4、实现随机发帖 断言&#xff1a;具有唯一表…

Java面试八股之什么是分布式垃圾回收

什么是分布式垃圾回收 分布式垃圾回收&#xff08;Distributed Garbage Collection, DGC&#xff09;是Java中一种特殊的垃圾回收机制&#xff0c;主要用于处理跨Java虚拟机&#xff08;JVM&#xff09;的远程对象引用时的内存管理问题。在分布式系统中&#xff0c;当一个JVM中…

yolov10打包为exe

一、前言 本节实验将官方yolov10推理程序打包为exe运行 二、代码 首先下载官方代码至本机&#xff0c;并使用conda创建虚拟环境&#xff0c;并安装好yolov10所需库 conda create --prefix E:/pyenv/myYolo10 python3.8 pip install -r requirements.txt 下载官方模型权重 …

【面试干货】Java中的四种引用类型:强引用、软引用、弱引用和虚引用

【面试干货】Java中的四种引用类型&#xff1a;强引用、软引用、弱引用和虚引用 1、强引用&#xff08;Strong Reference&#xff09;2、软引用&#xff08;Soft Reference&#xff09;3、弱引用&#xff08;Weak Reference&#xff09;4、虚引用&#xff08;Phantom Reference…

在线装修管理系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;管理员管理&#xff0c;装修队管理&#xff0c;用户管理&#xff0c;装修管理&#xff0c;基础数据管理&#xff0c;论坛管理 前台账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;…

【计算机网络】[第4章 网络层][自用]

1 概述 (1)因特网使用的TCP/IP协议体系(四层)的网际层,提供的是无连接、不可靠的数据报服务; (2)ATM、帧中继、X.25的OSI体系(七层)中的网络层,提供的是面向连接的、可靠的虚电路服务。 (3)路由选择分两种: 一种是由用户or管理员人工进行配置(只适用于规…

【开发工具】git服务器端安装部署+客户端配置

自己安装一个轻量级的git服务端&#xff0c;仅仅作为代码维护&#xff0c;尤其适合个人代码管理。毕竟代码的版本管理是很有必要的。 这里把git服务端部署在centos系统里&#xff0c;部署完成后可以通过命令行推拉代码&#xff0c;进行版本和用户管理。 一、服务端安装配置 …

爬虫阶段思考

内容&#xff1a;写这篇文章是因为最近帮同学改了很多的爬虫代码&#xff0c;感触良多。 我用豆瓣为例&#xff0c;并不是不会用别的&#xff0c;而是这个我个人感觉最经典。然后还会写我遇到的一些问题以及解决方法。 首先&#xff0c;我们得先知道怎样爬取。我用的scrapy框…

算法基础精选题单 动态规划(dp)(递推+线性dp)(个人题解)

前言&#xff1a; 一些简单的dp问题。 正文&#xff1a; 题单&#xff1a;237题】算法基础精选题单_ACM竞赛_ACM/CSP/ICPC/CCPC/比赛经验/题解/资讯_牛客竞赛OJ_牛客网 (nowcoder.com) 递推&#xff1a; NC235911 走楼梯&#xff1a; #include<bits/stdc.h> using na…

linux 关闭防火墙

文章目录 关闭系统防火墙关闭 linux 防火墙 关闭系统防火墙 systemctl stop firewalld systemctl disable firewalld // 关闭开机自启动 systemctl status firewalld // 查看防火墙状态关闭 linux 防火墙 setenforce 0 getenforce // 查看状态 vim /etc/sysconfig/selinux //…

USB2.0学习4--USB包结构和包类型

目录 1. USB包基本结构 1.1 SOP域&#xff08;Start Of Packet&#xff09; 1.2 SYNC域&#xff08;同步域&#xff09; 1.3 PID域&#xff08;标识域&#xff09; 1.4 地址域&#xff08;ADDR&#xff09; 1.5 帧号域&#xff08;Fram&#xff09; 1.6 数据域&#xff…

jeecg 框架的excel导入 含图片(嵌入式,浮动式)

jeecg 框架的excel导入 含图片&#xff08;嵌入式&#xff0c;浮动式&#xff09; 一、啰嗦二、准备三、 代码1、代码&#xff08;修改覆写的ExcelImportServer&#xff09;2、代码&#xff08;修改覆写的PoiPublicUtil&#xff09;3、代码&#xff08;新增类SAXParserHandler&…

根据正则表达式查找字符串中第一次出现的一个或多个连续数字并返回起止位置re.rearch

【小白从小学Python、C、Java】 【考研初试复试毕业设计】 【Python基础AI数据分析】 根据正则表达式 查找字符串中 第一次出现的 一个或多个连续数字 并返回起止位置 re.rearch [太阳]选择题 根据给定的Python代码&#xff0c;哪个选项是正确的&#xff1f; import re patte…

基于Java图书馆管理系统详细设计和实现(源码+LW+调试文档+讲解等)

&#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f; 感兴趣的可以先收藏起来&#xff0c;…