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

news2024/10/7 12:26:20

文章目录

  • 前言
  • 实现
    • 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.coloradmin.cn/o/1856916.html

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

相关文章

系统编程:线程相关

线程 相关函数及过程: 创建线程号; pthread_t tid; 创建线程:pthread_create(&tid, NULL, task, argv[1]); 定义线程执行函数:void *task(void *arg){ 线程退出:pthread_exit(ret);//线程结束后退出 } 等待所有线程结束:pthread_join(tid, (void **)&ret); 编译时增加…

系统思考—结构影响行为

思‮问考‬题时&#xff0c;从“结构”的‮度角‬出发&#xff0c;能‮示揭‬许多不‮人为‬知的‮层深‬次真相。我‮常们‬认为“努‮必力‬有回报”&#xff0c;从‮误而‬信‮过通‬坚‮就持‬能‮抗抵‬诱惑。然而&#xff0c;如‮深果‬入理解“结‮影构‬响行为”&#…

力扣-两数之和

文章目录 题目题解方法1-暴力方法2-哈希 题目 原题链接&#xff1a;两数之和 题解 方法1-暴力 我最先想到的方法就是暴力&#xff0c;两层for循环&#xff0c;也能通过。&#xff08;拿到算法题在没有思路的时候暴力就是思路&#xff0c;哈哈哈&#xff09; public class T…

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

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

华为HDC开发者大会鸿蒙进展超预期

本文首发于公众号“AntDream”&#xff0c;欢迎微信搜索“AntDream”或扫描文章底部二维码关注&#xff0c;和我一起每天进步一点点 在数字化浪潮的推动下&#xff0c;华为鸿蒙系统&#xff08;HarmonyOS&#xff09;以其革命性的创新&#xff0c;引领着全球科技的新趋势。2024…

【科技前沿】电子设计新贵SmartEDA:为何它引领行业风潮?

在当今这个电子科技日新月异的时代&#xff0c;电子设计工具如同设计师的魔法棒&#xff0c;不断推动着产品创新的速度。而近期&#xff0c;一款名为SmartEDA的电子国产设计仿真软件异军突起&#xff0c;成为了行业内的新宠。那么&#xff0c;SmartEDA究竟有何过人之处&#xf…

智能客服到个人助理,国内AI大模型如何改变我们的生活?

引言 随着人工智能&#xff08;AI&#xff09;技术的高速发展&#xff0c;AI大模型越来越多地出现在我们的日常生活和工作中。国内的AI大模型在过去几年里取得了显著的进展&#xff0c;不少独创的技术点和实际应用令人瞩目。 那么&#xff0c;国内的AI大模型有哪些独创的技术…

时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测

时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测 目录 时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测基本介绍程序设计参考资料基本介绍 MATLAB实现LSTM时间序列未来多步预测-递归预测。LSTM是一种含有LSTM区块(blocks)或其他的一种类神经网络,文献或其…

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

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

csp 2023 入门级题解(上)

csp 2023 入门级题解 上 第一题第二题第三题结构体联合体 第四题第五题第六题第7题第八题 第一题 unsigned是指无符号,用于int类型,是指自然数. const是定义常量,定义后的值不可修改. static是将系统栈中的变量放入内存,可以让其他程序调用 答案是c 第二题 答案d 第三题 s…

PowerToys常用工具安装使用

1、上个链接&#xff1a; Release Release v0.81.1 microsoft/PowerToys GitHub 2、看一下界面 3、我们看一下颜色选择器&#xff0c;经常会用到 winshiftc可以启用。 屏幕也可以直接取色。还是比较方便的。 直接复制&#xff0c;就可以了。

Spring Boot集成Redisson

文章目录 Spring Boot集成Redisson1. Redisson概述2. Redission作用3. 集成Redission前提&#xff1a;步骤 1: 添加依赖步骤 2: 配置Redisson 4. 结论 Spring Boot集成Redisson 1. Redisson概述 Redisson是一个在Redis基础上实现的Java驻内存数据网格&#xff08;In-Memory D…

LLM之表格理解任务-文本模态

这一章我们聊聊大模型表格理解任务&#xff0c;在大模型时代主要出现在包含表格的RAG任务&#xff0c;以及表格操作数据抽取文本对比等任务中。这一章先聊单一的文本模态&#xff0c;既你已经通过OCR或者多模态等方式从PDF或者图片中获取了表格的文本数据。和前文相同&#xff…

开放式耳机哪个品牌最好?五大必看开放式耳机推荐2024

想要购买开放式耳机&#xff0c;但面对众多品牌和型号&#xff0c;你是否感到无从下手&#xff1f;别担心&#xff0c;作为耳机发烧友和测评专家&#xff0c;我为大家带来了几款热门开放式耳机的横向对比。从音质、设计、功能等方面进行详细对比&#xff0c;让你一目了然地了解…

受用一生的三种顶级思维

斯坦福大学心理学教授卡罗尔德韦克在《终身成长》中提到&#xff1a; 决定人与人之间差异的&#xff0c;不是天赋&#xff0c;不是勤奋程度&#xff0c;而是思维模式。 在许多情况下&#xff0c;拥有恰当的思维方式&#xff0c;甚至比单纯的努力更加关键。 普通的人改变结果…

贺尔碧格流量阀比例放大器PSR2BE10P25、PSR2BE10P30、PSR2BE10P25

PSR2BE04N06、PSR2BE04P10、PSR2BE04P06、PSR2BE04N10、PSR2BE10N12、PSR2BE10P25、PSR2BE10P30、PSR2BE10P25、PSR3BE10N25、PSR3BE10P30、PSR3BE10P12贺尔碧格HOERBIGER液压比例流量阀由比例电磁铁和流量阀组合而成&#xff0c;利用输入的电信号来改变节流阀的开度&#xff0…

适用于 Android 的 几种短信恢复应用程序

Android 设备上的短信丢失可能由于多种原因而丢失&#xff0c;例如意外删除、恢复出厂设置、系统崩溃或病毒攻击。是否有应用程序可以恢复 Android 上已删除的短信&#xff1f;幸运的是&#xff0c;有几款短信恢复应用程序可以扫描您的 Android 手机并从内存或 SIM 卡中检索已删…

手机照片怎么恢复?3个方法,从灾难中崛起

已经成为了我们随身携带的必备品。而在这些小巧玲珑的设备中&#xff0c;存储着我们大量的个人回忆和重要资料。其中&#xff0c;手机拍摄的照片更是承载着我们的欢笑、泪水、成长与经历&#xff0c;但它们会因为意外从此消失。 面对这样的困境&#xff0c;我们是否只能无奈接…

邮件群发推送的方法技巧?有哪些注意事项?

邮件群发推送的策略如何实现&#xff1f;邮件推送怎么评估效果&#xff1f; 电子邮件营销是现代企业进行推广和沟通的重要工具。有效的邮件群发推送不仅能提高客户参与度&#xff0c;还能促进销售增长。AokSend将探讨一些关键的邮件群发推送方法和技巧&#xff0c;以帮助企业优…

安装虚拟环境

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 Flask依赖两个外部库&#xff1a;Werkzeug和Jinja2。Werkzeug是一个WSGI&#xff08;在Web应用和多种服务器之间的标准 Python 接口&#xff09;工具…