为了能方便的移动,需要给VR中添加传送功能。
传送的位置需要做一个标记,让用户知道传送到什么位置。
我用3DSMax简单的画了一个标记

将其导入Unity,拖入Hierarchy中,名字改为TeleportReticle

创建一个Material并将其Shader改为Unlit/Color

然后将它赋给传送标记,并将做好的传送标记拖到项目中的prefabs文件夹中,然后删除场景中的传送标记。
要使用传送标记,需要修改之前的LaserPointer脚本
代码思路:
1. 声明相关的变量,包括预制件引用实例引用等等
2. 修改场景中的Layer,并在发射激光中加入判断,防止传送到墙上(或其他禁止传送的地方)
3. 编写传送方法
4. 检查传送偏移
5. 将传送方法加到按键事件中
现在,打开之前的LaserPointer脚本,增加一些代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LaserPointer : MonoBehaviour {
privateSteamVR_TrackedObject trackedObj;
publicGameObject laserPrefab;
privateGameObject laser;
privateTransform laserTransform;
//传送模块新加变量
//[cameraRig]的transform组件
publicTransform cameraRigTransform;
//传送标记预制件的引用
publicGameObject teleportReticlePrefab;
//传送实例的引用
privateGameObject reticle;
//传送标记的transform引用
privateTransform teleportReticleTransform;
//摄像机的transform引用
publicTransform headTransform;
//标记距离地板的偏移
public Vector3 teleportReticleoffset;
//用于过滤是否允许传送的遮罩
publicLayerMask teleportMask;
//保存判断是否允许传送
private bool shouldTeleport;
private Vector3 hitPoint;
privateSteamVR_Controller.Device Controller
{
get { returnSteamVR_Controller.Input((int)trackedObj.index); }
}
void Awake()
{
trackedObj = GetComponent();
}
private voidShowLaser(RaycastHit hit)
{
laser.SetActive(true);
laserTransform.position = Vector3.Lerp(trackedObj.transform.position,hitPoint,0.5f);
laserTransform.LookAt(hitPoint);
laserTransform.localScale = newVector3(laserTransform.localScale.x , laserTransform.localScale.y,hit.distance);
}
private void Start()
{
laser = Instantiate(laserPrefab);
laserTransform = laser.transform;
//同样实例化传送标记
reticle = Instantiate(teleportReticlePrefab);
//同样保存标记点的transform组件
teleportReticleTransform = reticle.transform;
}
void Update () {
if(Controller.GetPress(SteamVR_Controller.ButtonMask.Touchpad))
{
RaycastHit hit;
//在100后加上“, teleportMask”防止激光和传送点指到墙上
if(Physics.Raycast(trackedObj.transform.position, transform.forward, out hit, 100, teleportMask))
{
hitPoint = hit.point;
ShowLaser(hit);
//显示传送标记
reticle.SetActive(true);
//移动传送标记到激光点位置,并添加偏移防止冲突
teleportReticleTransform.position = hitPoint + teleportReticleoffset;
//表示找到可传送位置
shouldTeleport = true;
}
}
else
{
laser.SetActive(false);
//隐藏传送标记
reticle.SetActive(false);
}
//调用传送方法
if(Controller.GetPressUp(SteamVR_Controller.ButtonMask.Touchpad) && shouldTeleport)
{
Teleport();
}
}
//传送模块
private void Teleport() {
//正在传送时不能同时传送
shouldTeleport = false;
//隐藏传送标记
reticle.SetActive(false);
//计算玩家头盔到摄像机中心的坐标偏移
Vector3 difference = cameraRigTransform.position - headTransform.position;
//不考虑高度偏移
difference.y = 0;
//移动相机到照射点加上偏移后的坐标
cameraRigTransform.position = hitPoint + difference;
}
}
好了,编辑好代码之后,保存退出。
到unity中,将可传送的物体(地面、桌子等)的layer更改为canTeleport,使其可被传送。
选中两个手柄,会发现之前赋了Laser Pointer脚本的地方多了好多空。
将 [CameraRig] 拖到 Camera Rig Transform 栏,将传送标记从 Prefabs 文件夹拖到 Teleport Reticle Transform 栏,将 Camera (head) 拖到 Head Transform 栏。将 Teleport Reticle Offset 设为 (X:0, Y:0.05, Z:0) ,Teleport Mask 设为CanTeleport。

好了,到这里这个场景就结束了,开始玩吧~
本文详细介绍如何在虚拟现实(VR)环境中实现传送功能,包括创建传送标记、修改激光指示器脚本、调整层设置等内容。
515

被折叠的 条评论
为什么被折叠?



