当前位置: 首页 > news >正文

Unity Meta Quest 一体机开发(十三):【手势追踪】自定义交互事件 EventWrapper

文章目录

  • 📕教程说明
  • 📕交互事件概述
  • 📕自定义交互逻辑
    • ⭐方法一:Inspector 面板赋值
    • ⭐方法二:纯代码处理

此教程相关的详细教案,文档,思维导图和工程文件会放入 Spatial XR 社区。这是一个高质量 XR 社区,博主目前在内担任 XR 开发的讲师。此外,该社区提供教程答疑、及时交流、进阶教程、外包、行业动态等服务。

社区链接:
Spatial XR 高级社区(知识星球)
Spatial XR 高级社区(爱发电)

在这里插入图片描述


📕教程说明

这篇教程将会介绍如何用 Meta XR SDK,自定义交互事件触发时执行的逻辑。最后会实现一个功能:用手指点击 UI 按钮后,在前方召唤一把剑。

环境配置可参考:https://blog.csdn.net/qq_46044366/article/details/133967343

配置一个基本的玩家物体可以参考前几期教程:https://blog.csdn.net/qq_46044366/article/details/134097455

系列教程专栏:https://blog.csdn.net/qq_46044366/category_12118293.html

配套的视频链接:
上半部分:https://www.bilibili.com/video/BV1rK4y1B7Zs
下半部分:https://www.bilibili.com/video/BV1vT4y1p7EK

​电脑操作系统:Windows 11

使用的 VR 设备:Meta Quest 3(Quest 系列都适用)

使用的 Unity 版本:2021.3.5 LTS (这里推荐使用 2021 及以上的 LTS 版本)

Meta XR SDK 版本:v57

官方文档:https://developer.oculus.com/documentation/unity/unity-gs-overview/

Event Wrapper 介绍文档:
https://developer.oculus.com/documentation/unity/unity-isdk-event-wrappers/

最终效果:

在这里插入图片描述


📕交互事件概述

交互事件是 XR 开发中经常使用的一个东西。当一个交互动作发生的时候,可能会伴随着一些事情的发生。比如点击一个 “游戏开始” 的UI按钮,就会触发 “游戏开始” 事件,从而对游戏场景里的一些东西进行初始化。这个时候 “点击UI按钮” 就是一个交互事件,对游戏场景里的东西初始化就是这个事件触发后需要执行的事。在 Meta XR SDK 中,交互事件一般会在一个交互过程中的不同状态下触发,以点击 UI 按钮为例,这个动作属于 Poke 交互,我们知道交互的发生需要有 Interactor 和 Interactable 两个对象的参与,那么 Poke 交互对应的 Interactor 在手上,对应的 Interactable 在 UI 按钮物体上。对于 UI 按钮这个 Interactable 来说,当手指靠近按钮的时候,按钮自身会进入到 Hover 状态,这个时刻就可以当作一个交互事件发生了。然后当手指点击到按钮,将按钮按到底的时候,按钮自身会进入到 Select 状态,这边需要注意的是对于一个可以被推动的按钮来说,必须要推到底,也就是推到按钮 Surface 的位置才会进入到 Select 状态,当手指刚刚触碰到按钮表面的时候是不会进入到 Select 状态的。那么进入到 Select 状态这个瞬间也可以当作一个交互事件发生了。

其实前几期教程我们已经有接触到交互事件,我这里是在场景中添加了一个 Poke 教程里配置的 UI 按钮(教程链接:Unity Meta Quest 一体机开发(十二):【手势追踪】Poke 交互 - 用手指点击由 3D 物体制作的 UI 按钮)。

在这里插入图片描述

比如按钮身上的 Interactable Color Visual 脚本,这个脚本能够实现物体在进入不同状态的时候改变物体的颜色。那么这就和交互事件的概念比较像了,进入到不同的状态相当于不同交互事件的触发,改变颜色相当于事件触发后执行的事。Meta XR SDK 会自动检测相应的交互事件什么发生,但是这个脚本把交互事件触发后执行的逻辑写死了,它只能改变物体的颜色,无法处理其他的事。而接下来我会介绍如何去自定义交互事件触发时执行的逻辑。

📕自定义交互逻辑

Meta XR SDK 提供了一个 EventWrapper 的概念,叫做事件包装器(官方文档:https://developer.oculus.com/documentation/unity/unity-isdk-event-wrappers/)。它能够处理 Interaction SDK 中的一些交互事件,并且我们能够自定义交互事件发生时执行的逻辑。如下图所示,Meta 提供了不同类型的 EventWrapper:

在这里插入图片描述

我们这期教程主要关注可交互物体,也就是 Interactable 的交互事件,那么可以使用这两种 EventWrapper:InteractableUnityEventWrapper 和 PointableUnityEventWrapper。这两个脚本有一些相同的交互事件,也有一些不同的交互事件。不过最常用的是下图中标出的 4 个共同的交互事件:

在这里插入图片描述

Hover 是悬停的状态,Interactor 靠近 Interactable 的时候触发。当交互动作完成的时候,也就是 Interactor 选中 Interactable 时,由 Hover 状态转变为 Select 状态。

我们这期教程会介绍 InteractableUnityEventWrapper 脚本的用法,它用起来会稍微简单一点。

我们需要把 InteractableUnityEventWrapper 脚本添加到 UI 按钮物体上:

在这里插入图片描述
我们可以在脚本的 Inspector 面板上看到这个脚本提供的交互事件。

⭐方法一:Inspector 面板赋值

Event Wrapper 提供交互事件,并且检测交互事件什么时候触发。但是触发交互事件后需要执行什么事情需要我们自己处理。第一种处理方式是在 Event Wrapper 脚本的 Inspector 面板上直接进行赋值。我们会实现按下 UI 按钮后在前方生成一把剑的功能,判断什么时候按下 UI 按钮会由 Event Wrapper 来处理,我们这里把按下 UI 按钮视为 Select 交互事件触发,也就是将按钮按到底的时候,触发 Select 事件,然后执行生成剑的逻辑。那么我们需要自己写个脚本实现生成物体的功能,然后让 Event Wrapper 在判断到 Select 事件触发时去调用我们脚本中生成物体的方法。

脚本如下:

using Oculus.Interaction;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class ItemSpawner : MonoBehaviour
{public GameObject spawnObj;public Transform spawnPoint;public void SpawnItem(){GameObject obj = GameObject.Instantiate(spawnObj);obj.transform.position = spawnPoint.position;}
}

spawnObj 是需要生成的物体,spawnPoint 是物体生成的位置,SpawnItem 方法负责将需要生成的物体生成在需要生成的位置上。

然后将这个脚本挂载到按钮物体身上,并且在面板上进行赋值:

在这里插入图片描述

我这边将一个剑的模型制作成了 Prefab,拖到了 spawnObj 变量上。然后在按钮物体上新建了一个子物体,作为生成剑的位置。

在这里插入图片描述
我们可以在场景中调整 SpawnPoint 子物体的位置。

然后点击 InteractableUnityEventWrapper 脚本上的 WhenSelect 事件的 “+”号,进行事件触发执行逻辑的添加:

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

当按钮被按到底的时候, WhenSelect 事件触发,然后调用 SpawnButton 物体上的 ItemSpawner 脚本中的 SpawnItem 方法,在设定的生成点生成剑的游戏物体。

⭐方法二:纯代码处理

我们修改 ItemSpawner 脚本:

using Oculus.Interaction;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class ItemSpawner : MonoBehaviour
{public GameObject spawnObj;public Transform spawnPoint;private InteractableUnityEventWrapper eventWrapper;void Start(){eventWrapper = GetComponent<InteractableUnityEventWrapper>();eventWrapper.WhenSelect.AddListener(SpawnItem);}private void OnDestroy(){eventWrapper.WhenSelect.RemoveListener(SpawnItem);}public void SpawnItem(){GameObject obj = GameObject.Instantiate(spawnObj);obj.transform.position = spawnPoint.position;}
}

和方法一的区别是,我们在代码中获取了 InteractableUnityEventWrapper 脚本,然后用代码为 InteractableUnityEventWrapper 的 WhenSelect 事件添加了事件触发后需要执行的方法。

InteractableUnityEventWrapper 的 WhenSelect 事件的监听器(AddListener 方法)需要传入一个 UnityAction 类型的参数。UnityAction 是 Unity 中的一种委托类型,可以绑定无返回值,无参数的方法。我们写的 SpawnItem 方法正好符合条件,所以能直接传入 AddListener 方法中,相当于我们把 SpawnItem 方法的执行委托给了 Event Wrapper,当 Event Wrapper 检测到 WhenSelect 事件触发后,会执行我们委托的事情,也就是调用 SpawnItem 方法,在设定的生成点生成指定的物体。

另外需要注意的是,当我们调用了 AddListener 后,需要在合适的地方调用 RemoveListener 方法,将事件监听器移除掉。

如果我们选用纯代码的方法处理交互事件,就不用在 Unity 的 Inspector 面板中拖拽赋值了。然后 ItemSpawner 脚本需要和 InteractableUnityEventWrapper 脚本挂载到同一个游戏物体身上。

最终效果:

在这里插入图片描述

相关文章:

Unity Meta Quest 一体机开发(十三):【手势追踪】自定义交互事件 EventWrapper

文章目录 &#x1f4d5;教程说明&#x1f4d5;交互事件概述&#x1f4d5;自定义交互逻辑⭐方法一&#xff1a;Inspector 面板赋值⭐方法二&#xff1a;纯代码处理 此教程相关的详细教案&#xff0c;文档&#xff0c;思维导图和工程文件会放入 Spatial XR 社区。这是一个高质量…...

13、Redis高频面试题

1、项目中为什么用Redis 我们项目中之所以选择Redis&#xff0c;主要是因为Redis有下面这些优点&#xff1a; 操作速度快&#xff1a;Redis的数据都保存在内存中&#xff0c;相比于其它硬盘类的存储&#xff0c;速度要快很多数据类型丰富&#xff1a;Redis支持 string&#x…...

Koa学习笔记

1、npm 初始化 npm init -y生成 package.json 文件,记录项目的依赖2、git 初始化 git init生成 .git 隐藏文件夹,.git 的本地仓库创建 .gitignore 文件,添加不提交文件的名称3、创建 ReadMe.md 文件 记录项目笔记4、搭建项目 安装 Koa 框架npm install koa5、编写最基本的…...

HiDataPlus 3.3.2-005 搭建(个人的一点心得体会 x86 平台)

HDP 集群搭建 前置安装 yum -y install createrepo yum install -y lrzsz yum install -y wget yum install -y vim修改当前集群机器的主机名 hostnamectl set-hostname XXX​ 这里的 XXX 就是要设置的当前机器的主机名称。主机名称是集群唯一的&#xff0c;一定不要重复&am…...

【PHP】PHP实现与硬件串口交互,接收硬件发送的实时数据

一、前言 目的&#xff1a;借助虚拟串口软件&#xff08;VSPD&#xff09;模拟硬件串口发送数据&#xff0c;使用PHP语言实现接收硬件发送的数据。 我这里的需求是连接天平&#xff0c;把天平的称量数据实时的传送到PHP使用。 使用工具&#xff1a;vspd串口调试工具 使用语…...

HNU-数据库系统-作业

数据库系统-作业 计科210X 甘晴void 202108010XXX 第一章作业 10.09 1.(名词解释)试述数据、数据库、数据库管理系统、数据库系统的概念。 数据&#xff0c;是描述事物的符号记录。 数据库&#xff08;DB&#xff09;&#xff0c;是长期存储在计算机内、有组织、可共享的大量…...

Python基础知识:整理10 异常相关知识

1 异常的捕获 1.1 基础写法 """基本语法&#xff1a;try:可能发生错误的代码except:如果出现异常&#xff0c;将执行的代码""" try:fr open("D:/abc.txt", "r", encoding"utf-8") except:print("出现异常…...

golang并发安全-select

前面说了golang的channel&#xff0c; 今天我们看看golang select 是怎么实现的。 数据结构 type scase struct {c *hchan // chanelem unsafe.Pointer // 数据 } select 非默认的case 中都是处理channel 的 接受和发送&#xff0c;所有scase 结构体中c是用来存储…...

微软Visual Studio产品之Visual C++编程进阶——一维数组(画画版)

我是荔园微风&#xff0c;作为一名在IT界整整25年的老兵&#xff0c;看到不少初学者在学习编程语言的过程中如此的痛苦&#xff0c;我决定做点什么&#xff0c;我小时候喜欢看小人书&#xff08;连环画&#xff09;&#xff0c;在那个没有电视、没有手机的年代&#xff0c;这是…...

Moonbeam生态项目分析 — — 下一代DeFi协议HydraDX

作者&#xff1a;David 概览 HydraDX是一个基于Substrate区块链框架构建的DeFi协议&#xff0c;旨在为波卡带来大量流动性。HydraDX的特色服务&#xff0c;HydraDX Omnipool&#xff0c;是一种创新的自动化做市商&#xff08;AMM&#xff09;&#xff0c;通过将所有资产组合在…...

Spark九:Spark调优之Shuffle调优

Spark shuffle调优方法 map端和reduce端缓存大小设置&#xff0c;reduce端重试次数和等待时间间隔&#xff0c;以及bypass设置 学习资料&#xff1a;https://mp.weixin.qq.com/s/caCk3mM5iXy0FaXCLkDwYQ 一、map和reduce端缓冲区大小 1.1 map端 在Spark任务运行过程中&…...

linux c多线程优先级

在 Linux 系统中&#xff0c;可以使用 pthread_setschedparam 函数来设置线程的优先级。该函数需要传入一个指向 pthread_t 类型的线程 ID&#xff0c;以及一个指向 struct sched_param 类型的结构体对象。struct sched_param 结构体包含了线程的优先级信息。 下面是一个示例代…...

Redis在项目开发中的应用

Spring Boot集成Redis构建博客应用 在这个示例中&#xff0c;我们将展示如何使用Spring Boot和Redis构建一个简单的博客应用&#xff0c;包括文章发布、点赞和评论功能。 1. 添加依赖 首先&#xff0c;我们需要在pom.xml文件中添加Spring Boot和Redis的依赖项。 <!-- Sp…...

mapper向mapper.xml传参中文时的乱码问题

1.起因&#xff1a; 在idea中进行模糊查询传参时&#xff0c;发现在idea中查中文查不出记录&#xff0c;在navicate中可以查出来。 2.猜测&#xff1a; 1.idea中的编码问题导致的乱码。 2.idea和navicate的编码一致性导致的乱码。 3.mapper向mapper.xml传参后出现乱码。 3.解…...

基于Docker官方php:7.1.33-fpm镜像构建支持67个常见模组的php7.1.33镜像

实践说明&#xff1a;基于RHEL7(CentOS7.9)部署docker环境(23.0.1、24.0.2)&#xff0c;所构建的php7.1.33镜像应用于RHEL7-9(如AlmaLinux9.1)&#xff0c;但因为docker的特性&#xff0c;适用场景是不限于此的。 文档形成时期&#xff1a;2017-2023年 因系统或软件版本不同&am…...

Type-C PD充电器受电端sink诱骗取电汇总:小家电应用5V9V12V15V20V28V

小家电产品、美容产品、电动产品等升级采用Type-C接口&#xff0c;在Type-C接口上使用Type-C取电芯片&#xff0c;即可使用快速充电器的5V、9V、12V、15V、20V供电&#xff0c;无需再配充电器&#xff0c;各类品牌的充电器都可以支持。目前充电器常见的USB-PD功率为&#xff1a…...

禁用code server docker容器中的工作区信任提示

VSCode 添加受限模式&#xff0c;主要是防止自动运行代码的&#xff0c;比如在vscode配置的task和launch参数是可以运行自定义代码的。如果用VScode打开未知的工程文件就有可能直接运行恶意代码。 但是当我们的实验基础模板文件可控的情况下&#xff0c;要想禁用code server do…...

JSON格式插件-VUE

JsonEditor 安装&#xff1a; npm i bin-code-editor -S引入&#xff1a; import Vue from vue; import CodeEditor from bin-code-editor; import bin-code-editor/lib/style/index.css; import App from ./App.vue; Vue.use(CodeEditor); new Vue({el: #app,render: h > …...

dubbo的springboot集成

1.什么是dubbo&#xff1f; Apache Dubbo 是一款 RPC 服务开发框架&#xff0c;用于解决微服务架构下的服务治理与通信问题&#xff0c;官方提供了 Java、Golang 等多语言 SDK 实现。使用 Dubbo 开发的微服务原生具备相互之间的远程地址发现与通信能力&#xff0c; 利用 Dubbo …...

【人工智能】智能电网:未来能源的革命

未来能源的革命 智能电网革命的意义在于将电力行业从传统的集中式发电和集中式输配电模式转变为智能化、分布式、互动式的能源网络。 现在我们从以下方面详细认真的了解一下智能电网&#xff1a; 智能变电站&#xff0c;智能配电网&#xff0c;智能电能表&#xff0c;智能交互…...

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度​

一、引言&#xff1a;多云环境的技术复杂性本质​​ 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时&#xff0c;​​基础设施的技术债呈现指数级积累​​。网络连接、身份认证、成本管理这三大核心挑战相互嵌套&#xff1a;跨云网络构建数据…...

云计算——弹性云计算器(ECS)

弹性云服务器&#xff1a;ECS 概述 云计算重构了ICT系统&#xff0c;云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台&#xff0c;包含如下主要概念。 ECS&#xff08;Elastic Cloud Server&#xff09;&#xff1a;即弹性云服务器&#xff0c;是云计算…...

三维GIS开发cesium智慧地铁教程(5)Cesium相机控制

一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点&#xff1a; 路径验证&#xff1a;确保相对路径.…...

23-Oracle 23 ai 区块链表(Blockchain Table)

小伙伴有没有在金融强合规的领域中遇见&#xff0c;必须要保持数据不可变&#xff0c;管理员都无法修改和留痕的要求。比如医疗的电子病历中&#xff0c;影像检查检验结果不可篡改行的&#xff0c;药品追溯过程中数据只可插入无法删除的特性需求&#xff1b;登录日志、修改日志…...

可靠性+灵活性:电力载波技术在楼宇自控中的核心价值

可靠性灵活性&#xff1a;电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中&#xff0c;电力载波技术&#xff08;PLC&#xff09;凭借其独特的优势&#xff0c;正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据&#xff0c;无需额外布…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

【AI学习】三、AI算法中的向量

在人工智能&#xff08;AI&#xff09;算法中&#xff0c;向量&#xff08;Vector&#xff09;是一种将现实世界中的数据&#xff08;如图像、文本、音频等&#xff09;转化为计算机可处理的数值型特征表示的工具。它是连接人类认知&#xff08;如语义、视觉特征&#xff09;与…...

AI编程--插件对比分析:CodeRider、GitHub Copilot及其他

AI编程插件对比分析&#xff1a;CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展&#xff0c;AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者&#xff0c;分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

让AI看见世界:MCP协议与服务器的工作原理

让AI看见世界&#xff1a;MCP协议与服务器的工作原理 MCP&#xff08;Model Context Protocol&#xff09;是一种创新的通信协议&#xff0c;旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天&#xff0c;MCP正成为连接AI与现实世界的重要桥梁。…...