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

【unity】Pico VR 开发笔记(基础篇)

Pico VR 开发笔记(基础篇)

XR Interaction Tooikit 版本 2.3.2

一、环境搭建

其实官方文档已经写的很详细了,这里只是不废话快速搭建,另外有一项官方说明有误的,补充说明一下,在开发工具部分说明

插件安装——安装pico的sdk和XR Interaction Tooikit

环境配置——在场景里添加头显和手柄,并进行配置和项目配置

开发工具——Pico提供的串流开发工具,可以在不打包的情况的,使用手柄和头显进行调试。

1、插件安装

pico SDK安装

pico SDK下载地址:SDK - PICO 开发者平台 (pico-interactive.com)

SDK下载后解压

打开unity→Window→PackgeManager→Add Package From disk(左上角+)→选择解压后文件里的package.json

XR Interaction Tooikit安装

在packgeManager里搜索XR Interaction Tooikit

选择版本尽量高版本,不要低于2.1.0。

打开Samples 面板,导入 Starter Assets、**XR Device Simulater **和 Tunneling Vignette

2、环境配置

场景配置

添加XR Origin:Hierarchy→Add(左上角+)→XR→XR Origin(VR)

手柄设置

  1. 选中Hierarchy的XR Origin子物体LeftHand Controller

  2. 配置LeftHand Controller的控件XR Controller,点击在右上角的预设,选择XRI Default Left Controller (右手柄同样配置,选择XRI Default Right Controller )

  3. 选择手柄模型,在XR Controller的Model Prefab选择LeftControllerModel(Tranform)

打包设置

选择:Edit→Player→settings for Android→other Setting

Minimum API Level 选择Android 10.0

Target API Level 选择Automatic(Highest installed)

Scripting Backend 选择IL2CPP

勾选ARM64

选择:Edit→Project Settings→XR Plug-in Management→Android Standalone Settings→选择PICO

3、开发工具

SDK安装

下载地址:SDK - PICO 开发者平台 (PICO Unity Live Preview Plugin)

SDK下载后解压

打开unity→Window→PackgeManager→Add Package From disk(左上角+)→选择解压后文件里的package.json

windows下载客户端

下载地址:SDK - PICO 开发者平台 (PICO Developer Center)

在本地安装后会安装steam串流工具

为一体机开启开发者模式

  1. 开启 PICO VR 一体机。
  2. 前往 设置 > 通用
  3. 射线对准 设置 字段并连续点击多次,直到左侧导航栏下方出现 开发者 选项。
  4. 点击 开发者,进入开发者选项界面。
  5. 打开右上角的 USB 调试开关

*这里官方文档有误,开启开发者模型要多次点击设置键

项目设置

选择:Edit→Project Settings→XR Plug-in Management→ PC Standalone Settings→选择 PICO Live Preview

二、开发

1、手柄输入

得到手柄

    InputDevice deviceLeft;//左手柄InputDevice deviceRight;//右手柄private void Start(){deviceLeft = InputDevices.GetDeviceAtXRNode(XRNode.LeftHand);deviceRight = InputDevices.GetDeviceAtXRNode(XRNode.RightHand);}

手柄触发核心方法 TryGetFeatureValue

手柄扳机键触发

    /// <summary>/// 扳机键/// </summary>/// <param name="inputDevice">手柄</param>/// <param name="action">触发委托</param>/// <param name="Value">触发参数</param>void triggerButton(InputDevice inputDevice, ref bool Value, Action action){if (inputDevice.TryGetFeatureValue(CommonUsages.triggerButton,out Value)&&Value){action();}}

扳机键力度

    /// <summary>/// 扳机键力度/// </summary>/// <param name="inputDevice">手柄</param>/// <param name="action">触发委托</param>/// <param name="Value">触发参数</param>void trigger(InputDevice inputDevice, ref float Value, Action<float> action){if (inputDevice.TryGetFeatureValue(CommonUsages.trigger, out Value)&& !Value.Equals(0)){action(Value);}}

抓握键

    /// <summary>/// 抓握键/// </summary>/// <param name="inputDevice"></param>/// <param name="action"></param>/// <param name="Value"></param>void gripButton(InputDevice inputDevice, ref bool Value, Action action){if (inputDevice.TryGetFeatureValue(CommonUsages.gripButton, out Value) && Value){action();}}

抓握键力度

    /// <summary>/// 抓握键力度/// </summary>/// <param name="inputDevice"></param>/// <param name="action"></param>/// <param name="Value"></param>void grip(InputDevice inputDevice, ref float Value, Action<float> action){if (inputDevice.TryGetFeatureValue(CommonUsages.grip, out Value) && !Value.Equals(0)){action(Value);}}

摇杆方向

    /// <summary>/// 摇杆方向/// </summary>/// <param name="inputDevice"></param>/// <param name="action"></param>/// <param name="Value"></param>void primary2DAxis(InputDevice inputDevice, ref Vector2 Value, Action<Vector2> action){if (inputDevice.TryGetFeatureValue(CommonUsages.primary2DAxis, out Value) && !Value.Equals(Vector2.zero)){action(Value);}}

摇杆

    /// <summary>/// 摇杆/// </summary>/// <param name="inputDevice"></param>/// <param name="Value"></param>/// <param name="action"></param>void primary2DAxisClick(InputDevice inputDevice, ref bool Value, Action action){if (inputDevice.TryGetFeatureValue(CommonUsages.primary2DAxisClick, out Value) && Value){action();}}

X/A

    /// <summary>/// X/A/// </summary>/// <param name="inputDevice"></param>/// <param name="Value"></param>/// <param name="action"></param>void primaryButton(InputDevice inputDevice, ref bool Value, Action action){if (inputDevice.TryGetFeatureValue(CommonUsages.primaryButton, out Value) && Value){action();}}

Y/B

    /// <summary>/// Y/B/// </summary>/// <param name="inputDevice"></param>/// <param name="Value"></param>/// <param name="action"></param>void secondaryButton(InputDevice inputDevice, ref bool Value, Action action){if (inputDevice.TryGetFeatureValue(CommonUsages.secondaryButton, out Value) && Value){action();}}

2、射线

得到射线的方法

XRRayInteractor.TryGetCurrent3DRaycastHit(out hit)

XRRayInteractor是手柄上挂载的XRRayInteractor脚本。

Demo

    public XRRayInteractor rayInteractor;RaycastHit hit;Vector3 getRayPoint(){if (rayInteractor.TryGetCurrent3DRaycastHit(out hit)){string name = hit.collider.name;Debug.Log(name);return hit.point;}else{return Vector3.zero;}}

补充设置

射线的类型

类型说明
Staight Line直线
Projectile Curve抛物线
Bezier Curve贝塞尔曲线

修改方法

 rayInteractor.lineType = XRRayInteractor.LineType.ProjectileCurve;

不同类型的射线还有自己的参数可以修改,比如Stailght Line的MaxRaycastDistance(最远射线距离)和ProjectileCurve的Additional Flight Time(射线飞行时间)都可以直接赋值。

有效射线和无效射线

当射线触碰到可触发的UI或者模型时,射线为有效射线,反馈则是使用了ValidColorGradient。否则是使用InvalidColorGradient。

无效射线和有效射线触碰到有碰撞的模型时同样可以返回RaycastHit,区别在XR射线本身的设置上,比如碰撞Reticle。

实现有效碰撞,需要另外在模型上添加Tracked Device Physics Raycaster脚本等

Reticle (十字线)

Reticle 是射线和模型(UI)碰撞的点。

添加方法:

在手柄的上找到XR Interactor Line Visual脚本,创建Reticle 预制体后直接添加上。

3、UI触发

触发条件

手柄射线要触发到UI,在完成VR基础场景搭建的前提下,需要挂载两个脚本。

在Canvas上增加Tracked Device Graphic Raycaster

替换EventSystem上的Standalone Input Module为XR UI Input Module(模型上添加的Tracked Device Physics Raycaster脚本也是受XR UI Input Module影响的)

注意事项

Canvas的Order in Layer 最好设置为负值。如果为0或者正值,十字线可能会被UI遮挡。

为0时

为-1时

相关文章:

【unity】Pico VR 开发笔记(基础篇)

Pico VR 开发笔记(基础篇) XR Interaction Tooikit 版本 2.3.2 一、环境搭建 其实官方文档已经写的很详细了&#xff0c;这里只是不废话快速搭建&#xff0c;另外有一项官方说明有误的&#xff0c;补充说明一下&#xff0c;在开发工具部分说明 插件安装——安装pico的sdk和XR…...

竞争之王CEO商战课,聚百家企业在京举行

竞争之王CEO商战课&#xff0c;于2023年7月29-31日在北京临空皇冠假日酒店举办&#xff0c;近百家位企业家齐聚一堂&#xff0c;共享饕餮盛宴。 竞争之王CEO商战课是打赢商战的第一课。 竞争环境不是匀速变化&#xff0c;而是加速变化。 在未来的市场环境中&#xff0c;企业间…...

【shell】获取ping的时延数据并分析网络情况及常用命令学习

文章目录 获取ping的时延数据并分析网络情况|、||、&、&&辨析teetailkillall 获取ping的时延数据并分析网络情况 网络情况经常让我们头疼&#xff0c;每次都需要手动在终端ping太麻烦了&#xff0c;不如写个脚本ping并将数据带上时间戳存入文件&#xff0c;然后也…...

石子合并一章通(环形石子合并,四边形不等式,GarsiaWachs算法)(内附封面)

[NOI1995] 石子合并 题目描述 在一个圆形操场的四周摆放 N N N 堆石子&#xff0c;现要将石子有次序地合并成一堆&#xff0c;规定每次只能选相邻的 2 2 2 堆合并成新的一堆&#xff0c;并将新的一堆的石子数&#xff0c;记为该次合并的得分。 试设计出一个算法,计算出将 …...

Docker快速入门笔记

Docker快速入门 前言 当今软件开发领域的一股热潮正在迅速兴起&#xff0c;它融合了便捷性、灵活性和可移植性&#xff0c;让开发者们欣喜若狂。它就是 Docker&#xff01;无论你是一个初学者&#xff0c;还是一位经验丰富的开发者&#xff0c;都不能错过这个引领技术浪潮的工…...

【Excel】记录Match和Index函数的用法

最近一直用到的两个处理EXCEL表格数据的函数向大家介绍一下&#xff0c;写这篇博文的目的也是为了记录免得自己忘记了&#xff0c;嘻嘻。 先上百度的链接 Match函数的用法介绍&#xff1a;https://jingyan.baidu.com/article/2fb0ba40b4933941f3ec5f71.html 小结&#xff1a;…...

SolidUI社区-从开源社区角度思考苹果下架多款ChatGPT应用

文章目录 背景下架背景下架原因趋势SolidUI社区的未来规划结语如果成为贡献者 背景 随着文本生成图像的语言模型兴起&#xff0c;SolidUI想帮人们快速构建可视化工具&#xff0c;可视化内容包括2D,3D,3D场景&#xff0c;从而快速构三维数据演示场景。SolidUI 是一个创新的项目…...

插入排序讲解

插入排序&#xff08;Insertion-Sort&#xff09;一般也被称为直接插入排序。对于少量元素的排序&#xff0c;它是一个有效的算法。插入排序是一种最简单的排序方法&#xff0c;它的基本思想是将一个记录插入到已经排好序的有序表中&#xff0c;从而一个新的、记录数增1的有序表…...

杀疯了的ChatGPT——开启AI智能交流新纪元 「文末有彩蛋」

欢迎打开 ChatGPT 的新世纪大门 &#x1f30d; 目录 &#x1f60a; 引言&#x1f60e; ChatGPT 的高级之处1. 巨大的模型规模2. 广泛的知识覆盖3. 零样本学习4. 多语言支持5. 上下文感知对话 &#x1f916; 如何使用 ChatGPT1. 智能助手2. 个性化交互3. 语言学习伙伴4. 创造性写…...

web爬虫第五弹 - JS逆向入门(猿人学第一题)

0- 前言 爬虫是一门需要实战的学问。 而对于初学者来说&#xff0c;要想学好反爬&#xff0c;js逆向则是敲门砖。今天给大家带来一个js逆向入门实例&#xff0c;接下来我们一步一步来感受下入门的逆向是什么样的。该案例选自猿人学练习题。猿人学第一题 1- 拿到需求 进入页面…...

P5731 【深基5.习6】蛇形方阵

题目描述 给出一个不大于 9 9 9 的正整数 n n n&#xff0c;输出 n n n\times n nn 的蛇形方阵。 从左上角填上 1 1 1 开始&#xff0c;顺时针方向依次填入数字&#xff0c;如同样例所示。注意每个数字有都会占用 3 3 3 个字符&#xff0c;前面使用空格补齐。 输入格式…...

Python实现GA遗传算法优化循环神经网络回归模型(LSTM回归算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 遗传算法&#xff08;Genetic Algorithm&#xff0c;GA&#xff09;最早是由美国的 John holland于20世…...

ESD防静电监控系统在SMT产线中的应用案例

作为电子厂的关键制造环节之一&#xff0c;SMT&#xff08;表面贴装技术&#xff09;产线的效率和质量对企业的竞争力至关重要。为了提高生产线的管理效率和保障生产环境的质量&#xff0c;许多电子厂开始采用MES生产管理系统和ESD防静电监控系统的综合解决方案。 在SMT产线中安…...

Vue+Nodejs+Express+Minio 实现本地图片上传

安装Minio,Minio server和Minio client都要下载可以自定义安装目录 安装完成之后,可以将minio配置成环境变量方便使用 配置了环境变量启动命令式 minio server start,默认账号密码minioadmin和minioadmin,点击9000端口的这个链接,即可访问客户端 nodejs连接Minio,简易服务进…...

em3288 linux_4.19 第一次烧写无法进入内核的情况

1. 情况一&#xff1a; /DDR Version 1.11 20210818 In SRX Channel a: DDR3 400MHz Bus Width32 Col10 Bank8 Row15 CS1 Die Bus-Width16 Size1024MB Channel b: DDR3 400MHz Bus Width32 Col10 Bank8 Row15 CS1 Die Bus-Width16 Size1024MB OUT Boot1 Release Time: Jul 22 2…...

【Java多线程学习5】什么是悲观锁,什么是乐观锁?如何实现乐观锁、乐观锁存在哪些问题

【Java多线程学习5】什么是悲观锁&#xff0c;什么是乐观锁&#xff1f;如何实现乐观锁、乐观锁存在哪些问题 一、什么是悲观锁 概述 悲观锁总是假设最坏的情况&#xff0c;认为共享资源每次被访问的时候就会出现问题(比如共享数据被修改)&#xff0c;所以每次在获取资源操作…...

OSPF协议RIP协议+OSPF实验(eNSP)

本篇博客主要讲解单区域的ospf&#xff0c;多区域的仅作了解。 目录 一、OSPF路由协议概述 1.内部网关协议和外部网关协议 二、OSPF的应用环境 1.从以下几方面考虑OSPF的使用 2.OSPF的特点 三、OSPF重要基本概念 3.1&#xff0c;辨析邻居和邻接关系以及七种邻居状态 3…...

leetcode每日一练-第108题-将有序数组转换为二叉搜索树

一、思路 递归 二、解题方法 在给定中序遍历序列数组的情况下&#xff0c;每一个子树中的数字在数组中一定是连续的&#xff0c;因此可以通过数组下标范围确定子树包含的数字&#xff0c;下标范围记为 [left,right]。对于整个中序遍历序列&#xff0c;下标范围从 left0到 ri…...

王道《操作系统》学习(二)—— 进程管理(二)

2.1 处理机调度的概念、层次 2.1.1 调度的基本概念 2.1.2 调度的三个层次 &#xff08;1&#xff09;高级调度&#xff08;作业调度&#xff09; &#xff08;2&#xff09;中级调度&#xff08;内存调度&#xff09; 补充知识&#xff1a;进程的挂起状态和七状态模型 &#x…...

Vulnhub: shenron: 3靶机

kali&#xff1a;192.168.111.111 靶机&#xff1a;192.168.111.171 信息收集 端口扫描 nmap -A -sC -v -sV -T5 -p- --scripthttp-enum 192.168.111.171 修改hosts后访问目标80端口&#xff0c;发现是wordpress wpscan收集目标用户&#xff0c;爆破出密码&#xff1a;ilov…...

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用&#xff1a;实现组件通用属性的渐变过渡效果&#xff0c;提升用户体验。支持属性&#xff1a;width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项&#xff1a; 布局类属性&#xff08;如宽高&#xff09;变化时&#…...

【Java学习笔记】Arrays类

Arrays 类 1. 导入包&#xff1a;import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序&#xff08;自然排序和定制排序&#xff09;Arrays.binarySearch()通过二分搜索法进行查找&#xff08;前提&#xff1a;数组是…...

数据链路层的主要功能是什么

数据链路层&#xff08;OSI模型第2层&#xff09;的核心功能是在相邻网络节点&#xff08;如交换机、主机&#xff09;间提供可靠的数据帧传输服务&#xff0c;主要职责包括&#xff1a; &#x1f511; 核心功能详解&#xff1a; 帧封装与解封装 封装&#xff1a; 将网络层下发…...

vue3 定时器-定义全局方法 vue+ts

1.创建ts文件 路径&#xff1a;src/utils/timer.ts 完整代码&#xff1a; import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...

重启Eureka集群中的节点,对已经注册的服务有什么影响

先看答案&#xff0c;如果正确地操作&#xff0c;重启Eureka集群中的节点&#xff0c;对已经注册的服务影响非常小&#xff0c;甚至可以做到无感知。 但如果操作不当&#xff0c;可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合

在汽车智能化的汹涌浪潮中&#xff0c;车辆不再仅仅是传统的交通工具&#xff0c;而是逐步演变为高度智能的移动终端。这一转变的核心支撑&#xff0c;来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒&#xff08;T-Box&#xff09;方案&#xff1a;NXP S32K146 与…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)

漏洞概览 漏洞名称&#xff1a;Apache Flink REST API 任意文件读取漏洞CVE编号&#xff1a;CVE-2020-17519CVSS评分&#xff1a;7.5影响版本&#xff1a;Apache Flink 1.11.0、1.11.1、1.11.2修复版本&#xff1a;≥ 1.11.3 或 ≥ 1.12.0漏洞类型&#xff1a;路径遍历&#x…...

算法:模拟

1.替换所有的问号 1576. 替换所有的问号 - 力扣&#xff08;LeetCode&#xff09; ​遍历字符串​&#xff1a;通过外层循环逐一检查每个字符。​遇到 ? 时处理​&#xff1a; 内层循环遍历小写字母&#xff08;a 到 z&#xff09;。对每个字母检查是否满足&#xff1a; ​与…...