这一篇主要是关于PIco的内容开发,基础配置请查看我的博客中的PIco基础配置篇文章
一、导入PIco_Unity资源文件
下载好资源文件以后直接拖入UnityAssets文件夹点击Import就导入了Unity当中,导入后会多出很多文件夹,都是SDK中自带的,其中最常用的就是PIcoMobileSDK文件夹(如下图)
注意:这里我是已经导入了资源了,所以Import Unity Package这边都没勾选,正常来说是要都勾选的
二、拖入PIco_UnitySDK预制体
在PIcoMobileSDK/Pvr_UnitySDK/Prefabs中找到PIco_UnitySDK预制体,该预制体包括了相机,手柄,脚本等内容,是PIco开发最为主要的预制体,找到后直接拖入场景中,并删除场景中原有的MainCamera,以免产生干扰。
操作成功后运行效果
三、手柄相关操作
(1)替换手柄模型
前言:在PIco的开发中,偶尔会遇到需要替换手柄模型的情况,需要替换手柄模型的话只需要找到预制体中的controller物体,删除掉,然后拖入做好的手柄模型(在这里我是隐藏了原来的controller然后拖入了我的荧光棒模型)
这里需要注意的是,在PvrControler0/1中外部引用了原本的controller,需要把新拖入的模型拖过去替换一下(如下图)
注:默认的controller模型为了适应PIcoNeon3,所以手柄默认向下倾斜15度,替换后的模型如果出现模型和手柄射线位置不对的情况只需旋转一下模型调整即可。
(2)手柄的按钮的认识和对应的代码接口
PIcoG2 4K手柄按钮及输入绑定如下图,手柄按钮的名称就是输入绑定“.”后面的英文,例如Pvr_KeyCode.APP,对应的就是手柄APP键
G2控制器按键 | 输入绑定 |
| Pvr_KeyCode.APP |
| Pvr_KeyCode.Home |
| Pvr_KeyCode.TOUCHPAD |
| Pvr_KeyCode.TRIGGER |
| Pvr_KeyCode.VOLUMEUP |
| Pvr_KeyCode.VOLUMEDOWN |
例:在Unity中获取手柄按钮的输入:
①获取引用Pvr_UnitySDKAPI(获取引用以后才能调用手柄的API):
②用代码检测按钮是否触发(在这里以检测Trigger按钮按下为例):
(3)手柄与Caves的交互
前言:在VR世界中的UI和普通电脑中的UI并不一样,普通的UI是直接显示在电脑屏幕上,但是VR中的UI如果直接显示在屏幕上的话就没法看咯,所以,UI的交互和普通Unity开发略有不同
①关于Caves的调整:
②关于手柄的调整
调整好了就可以实现UI的简单交互了(设置好了如下图,没有设置好之前点击按钮是没有反应的)
(4)手柄与物体的交互(基于Pico的射线)
前言:大多数使用过Unity的同学应该都了解,在Unity中需要和场景中的3D物体进行交互,射线是必不可少的,PIco的交互也类似,接下来是我的一个简单案例(直接上代码和效果)
脚本名为PicoRay,主要包括射线,Pico按钮事件和材质的颜色的修改
具体效果如下:(射线对准物体时变成红色,离开物体恢复原来的颜色,按下Trigger(扳机)键变为绿色,且按下后可以进行拖拽移动)
using Pvr_UnitySDKAPI;
using UnityEngine;
public class PicoRay : MonoBehaviour
{
public Transform direction;//终点坐标
public Transform origin;//起点坐标
//public LineRenderer lineRenderer;//画线
public Color Keycolor;//按下的颜色
Color Normal;//物体的初始颜色
GameObject CachegGam = null;//用于缓存物体
GameObject CachegGamcolor = null;//用于缓存物体的颜色
Transform CachegTrans;//用于缓存物体的坐标
Vector3 Vec;//用于暂存坐标变量
[Range(0, 1)]
[Tooltip("数值为0-1,0左手,1右手")]
public int HandNumber;
void Update()
{
picoRay();
}
void picoRay()
{
Vector3 V = origin.position - direction.position;//计算两个坐标之差,用作射线发射向量
Ray ray = new Ray(origin.position, -V.normalized);//以origin.position为起点,向-V方向发射射线
RaycastHit hit;//结构体 用于存储与射线相交或者说被射线打到的物体的信息
if (Physics.Raycast(ray, out hit))//射线打到物体时触发
{
if (hit.collider.gameObject.GetComponent<MeshRenderer>().material == null)//如果被射线打到的物体没有材质则不执行一下操作
{
return;
}
//射线打到物体对颜色进行判断
if (CachegGamcolor != null && CachegGamcolor.name != hit.collider.gameObject.name)//如果打到的物体不为空且信息和上一个不一样
{
CachegGamcolor.GetComponent<MeshRenderer>().material.color = Normal;//还原上个物体的颜色
CachegGamcolor = hit.collider.gameObject;//暂存射线打到的物体
Normal = CachegGamcolor.GetComponent<MeshRenderer>().material.color;//暂存物体初始颜色
}
else if (CachegGamcolor == null)//如果缓存颜色为空
{
CachegGamcolor = hit.collider.gameObject;//暂存射线打到的物体
Normal = CachegGamcolor.GetComponent<MeshRenderer>().material.color;//暂存物体颜色
}
else
{
CachegGamcolor.GetComponent<MeshRenderer>().material.color = Color.red;//打到的物体颜色红色
}
//手柄按下Trigger键进行物体信息的获取
if (Controller.UPvr_GetKeyDown(HandNumber, Pvr_KeyCode.TRIGGER) || Input.GetMouseButtonDown(0))//获取到鼠标按下时射线打到的物体 修改:每帧获取相对位置,修改前:不稳定
{
//核心
//CachegTrans = hit.transform;//把打到的物体存起来方便后面要使用
//Vec = CachegTrans.transform.position - direction.position;//计算两个物体之间的差量,也就是两个物体的中心的距离
if (CachegGam != null && CachegGam.name != hit.collider.gameObject.name)//如果这次的物体和上一次的物体不是同一个东西并且上一次打到的物体不为空
{
CachegGamcolor.GetComponent<MeshRenderer>().material.color = Normal;//将上一个物体的颜色还原
CachegGam = hit.collider.gameObject;//记录被新打到的物体的信息
CachegTrans = CachegGam.transform;//记录位置信息物体
Vec = CachegTrans.transform.position - direction.position;//计算差量
}
else if (CachegGam == null)
{
CachegGam = hit.collider.gameObject;//记录被新打到的物体的信息
CachegTrans = CachegGam.transform;//记录位置信息物体
Vec = CachegTrans.transform.position - direction.position; //计算差量
}
}
if (Controller.UPvr_GetKey(HandNumber, Pvr_KeyCode.TRIGGER) || Input.GetMouseButton(0))//如果长按Trigger键就修改颜色并跟随移动
{
//核心
if (CachegTrans != null&& CachegGam.name == hit.collider.gameObject.name)//如果保存的位置信息为空的话,就不执行后面的代码.如果这个物体和按下时检测的物体不一样,则不执行
{
CachegGam.transform.position = new Vector3(direction.position.x + Vec.x, direction.position.y + Vec.y, CachegTrans.transform.position.z);
//让被打到的物体的跟随Pico手柄的位置进行相对运行,在这里需要加上两个物体之间的差量才能保证两个物体之间的相对移动
CachegGamcolor.GetComponent<MeshRenderer>().material.color = Keycolor;//按下Trigger时物体的材质
}
}
}
else//射线没打到物体时触发/射线离开物体时触发
{
if (CachegGamcolor != null)//如果该物体不为空,则将其材质还原,并清空两个变量的赋值
{
CachegGamcolor.GetComponent<MeshRenderer>().material.color = Normal;//将上一个物体的颜色还原
CachegGam = null;//将缓存物体还原
CachegTrans = null;//将缓存坐标还原
}
}
}
}