【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.mzph.cn/web/33150.shtml

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

相关文章

ONLYOFFICE8.1版本桌面编辑器测评

OO官方链接点这里&#xff1a;ONLYOFFICE 文档 8.1 现已发布&#xff1a;功能全面的 PDF 编辑器、幻灯片版式、优化电子表格的协作等等 | ONLYOFFICE 博客 一、界面与用户体验 整体布局和设计的美观性、易用性&#xff1a; ONLYOFFICE 8.1 版本的桌面编辑器展现出了令人眼前一亮…

深入解析H100、A100和4090三款显卡的性能对比与应用场景

在当今的计算机领域&#xff0c;显卡的性能对于人工智能、深度学习和高性能计算等领域的影响至关重要。本文将深入解析NVIDIA最新的三款显卡&#xff1a;H100、A100和4090&#xff0c;比较它们的性能参数&#xff0c;并探讨各自的应用场景。 一、显卡性能参数对比 参数H100A1…

磁芯电感 晶谷电容可镀银浆用玻璃 晶谷电阻银浆料低温玻璃粉(耐强酸)

晶谷电阻银浆料低温玻璃粉&#xff08;耐强酸&#xff09;软化点在490至580度之间&#xff0c;线膨胀系数为&#xff08;75至95&#xff09;10-7&#xff0c;粒径为1.5至3微米&#xff08;可按要求订做&#xff09;&#xff0c;外观颜色为白色超细粉末&#xff0c;烧后颜色无色…

新能源汽车 LabCar 测试系统方案(-)

什么是LabCar测试 LabCar测试目标是进行整车黄板台架功能测试&#xff0c;用于整车开发和测试阶段&#xff0c;满足设计人员和测试人员的试验需求&#xff0c;以验证整车性能&#xff0c;减少开发工作量。系统主要用于测试静态及动态工况下的纯电动汽车的各项功能实现情况。 …

设计模式原则——里氏替换原则

设计模式原则 设计模式示例代码库地址&#xff1a; https://gitee.com/Jasonpupil/designPatterns 里氏替换原则 继承必须确保父类所拥有的性质在子类中依然成立 与开闭原则不同的是开闭原则可以改变父类原有的功能&#xff0c;里氏替换原则不能修改父类的原有的性质&#…

在线装修管理系统的设计

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

197.回溯算法:复原IP地址(力扣)

代码解决 class Solution { public:// 存储最终结果的向量vector<string> result;// 判断字符串s从start到end范围内的子串是否是一个合法的IP地址段bool isValid(const string& s, int start, int end){if (start > end) {return false; // 起始位置大于结束位置…

vue项目集成CanvasEditor实现Word在线编辑器

CanvasEditor实现Word在线编辑器 官网文档&#xff1a;https://hufe.club/canvas-editor-docs/guide/schema.html 源码地址&#xff1a;https://github.com/Hufe921/canvas-editor 前提声明&#xff1a; 由于CanvasEditor目前不支持vue、react 等框架开箱即用版&#xff0c;所以…

开源seata的分布式事务解决方案-XA、AT、TCC、SAGA哪个模式好

分布式事务是分布式系统中非常重要的一部分。假设一个用户购买商品的业务逻辑&#xff0c;系统有3个微服务组成&#xff0c;分别是订单服务、账户服务、库存服务&#xff0c;用户在提交订单后会从用户账户余额中扣款&#xff0c;同时扣减库存数量。在这样的场景下扣款和减库存需…

IDEA中 pom.xml 设置自动提示

IDEA中 pom.xml 自动提示 IDEA中 pom.xml 自动提示设置如下&#xff1a; file–>Settings–>Build,Execution…–>Build Tools–>Maven–>Repositories 会看到类似表格的画面&#xff0c;内容是你的maven地址&#xff0c;选中后&#xff0c;右边有个Update的按…

开放式耳机哪种好用又实用?开放式耳机必入品牌推荐,内行人分享

随着数码技术的不断推出各种各样的新产品&#xff0c;开放式耳机已经逐渐成为有份音乐发烧友的选择&#xff0c;这类耳机从早期的简单音质发展至今日的高解析度&#xff0c;其技术进步&#xff0c;也吸引了一大批开放式耳机的爱好者&#xff0c;开放式耳机以其开放式的设计&…

Springboot3.3 整合ClickHouse注意事项

Spring 3 整合 ClickHouse 的方法可以通过JDBC来实现。首先&#xff0c;确保你有Spring 3和ClickHouse的JDBC驱动。然后&#xff0c;在Spring的配置文件中配置数据源和模板。 Maven依赖示例&#xff1a; <!-- https://mvnrepository.com/artifact/com.clickhouse/clickhou…

对称/非对称加密

对称加密和非对称加密是两种主要的加密方式&#xff0c;用于保护数据的机密性和完整性。它们在密钥的使用和管理上有着显著的不同。 对称加密 原理 对称加密&#xff08;Symmetric Encryption&#xff09;使用相同的密钥进行加密和解密。这意味着发送方和接收方必须共享相同…

2024中国第三方算力中心服务商发展研究报告

来源&#xff1a;科智咨询 近期历史回顾&#xff1a;《江苏省绿色建筑评价标识实施细则》(1).pdf 《江苏省绿色建筑评价标识实施细则》.pdf 【计算工具】钢铁企业碳排放各工序数据收集表.xlsx 【深度报告】钢铁产品碳足迹核算及报告指南.pdf 【专家PPT】宝钢低碳钢铁技术策划及…

巧用newSingleThreadExecutor让异步任务顺序跑

背景 Flume 是 Cloudera 提供的一个高可用的&#xff0c;高可靠的&#xff0c;分布式的海量日志采集、聚合和传输的系统 。一个用来控制 Flume 采集任务的 Web 应用&#xff0c;需要对任务进行管理&#xff0c;主要操作「启动、停止、新建、编辑、删除」&#xff0c;本质就是对…

头歌——机器、深度学习——手写体识别

第1关&#xff1a;神经网络基本概念 任务描述 本关任务&#xff1a;根据本节课所学知识完成本关所设置的选择题。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a;1.神经网络基本概念。 神经网络基本概念 神经网络由输入层、隐藏层、输出层组成&#xff1b;…

【华为OD机试】最左侧冗余覆盖子串(C++ Java JavaScript Python )

题目 题目描述 给定两个字符串s1和s2和正整数K,其中s1长度为n1,s2长度为n2,在s2中选一个子串,满足: 该子串长度为n1+k该子串中包含s1中全部字母,该子串每个字母出现次数不小于s1中对应的字母,我们称s2以长度k冗余覆盖s1,给定s1,s2,k,求最左侧的s2以长度k冗余覆盖s1的…

逆向学习网络篇:心跳包与TCP服务器

本节课在线学习视频&#xff08;网盘地址&#xff0c;保存后即可免费观看&#xff09;&#xff1a; ​​https://pan.quark.cn/s/31c74a06f8db​​ 在网络通信中&#xff0c;心跳包是一种重要的机制&#xff0c;用于维持客户端与服务器之间的连接状态。本文将深入探讨心跳包的…

动手学深度学习(Pytorch版)代码实践 -卷积神经网络-22池化层

22池化层 import torch from torch import nn# 最大汇聚层和平均汇聚层 def pool2d(X, pool_size, modemax):p_h, p_w pool_sizeY torch.zeros((X.shape[0] - p_h 1, X.shape[1] - p_w 1))for i in range(Y.shape[0]):for j in range(Y.shape[1]):if mode max:Y[i, j] X…

【源码】含70演示高转化率Magento2外贸时装女装跨境电商模板V1.2.2

MagMog是下一代最高转化率和可扩展的跨境电商Magento2主题&#xff0c;让您几乎可以立即上手。这是一个终极解决方案&#xff1a;主题附带一系列电子商务功能&#xff0c;可以启用您商店的隐藏功能&#xff0c;并且您无需支付任何额外费用。 100% 免费。 MagMog从定制设计到内…