UI模块在前面已经讲完了,从本章开始,会着重介绍手柄与3d游戏物体之间的交互,我们平时项目开发,最常用的就是手柄射线点击物体、手柄触碰以及手柄拾取物体,先来聊聊射线点击物体。
沿用的思想我们之前有说过,利用SteamVR_LaserPointer组件的PointerIn、PointerClick、PointerOut,来监听射线进入物体、点击物体、离开物体,这样就可以实现射线与3d物体的交互,直接上干货。
一、前期准备
新建场景,删除默认相机,将Player拖拽进入场景内
新建Plane,修改为Floor,上一个黑色材质球,Transform信息如下:
场景内随意添加两个Cube,将其命名为CubeA、CubeB
二、编写游戏物体射线交互组件
using UnityEngine;using UnityEngine.Events;/// <summary>/// 物体射线交互/// </summary>public class SteamVR_InteractRay : MonoBehaviour{ public UnityAction OnRayEnter { get; set; } public UnityAction OnRayClick { get; set; } public UnityAction OnRayExit { get; set; } private void Start() { OnRayEnter = () => Debug.Log("射线进入 " + transform.name); OnRayClick = () => Debug.Log("射线点击 " + transform.name); OnRayExit = () => Debug.Log("射线离开 " + transform.name); } /// <summary> /// 射线进入 /// </summary> public void RayEnter() { OnRayEnter?.Invoke(); } /// <summary> /// 射线点击 /// </summary> public void RayClick() { OnRayClick?.Invoke(); } /// <summary> /// 射线离开 /// </summary> public void RayExit() { OnRayExit?.Invoke(); }}
这里逻辑很简单,我们只需要定义三个回调,来触发射线进入、点击、离开即可,为了方便测试,这里直接在Start函数内部实现了Debug逻辑,实际上我们可以编写脚本来继承此组件,来实现不同游戏物体被点击后触发不同逻辑,也可以直接挂载此组件,通过外部对委托进行逻辑触发。
CubeA与CubeB上挂载此脚本。
三、编写手柄射线监听组件
using UnityEngine;using Valve.VR.Extras;/// <summary>/// 物体射线交互管理/// </summary>public class SteamVR_RayHandler : MonoBehaviour{ private SteamVR_LaserPointer laserPointer; //激光组件 private void Awake() { laserPointer = GetComponent<SteamVR_LaserPointer>(); } private void Start() { laserPointer.PointerIn += LaserPointer_PointerIn; laserPointer.PointerClick += LaserPointer_PointerClick; laserPointer.PointerOut += LaserPointer_PointerOut; } private void LaserPointer_PointerIn(object sender, PointerEventArgs e) { if (e.target.GetComponent<SteamVR_InteractRay>() != null) { e.target.GetComponent<SteamVR_InteractRay>().RayEnter(); } } private void LaserPointer_PointerClick(object sender, PointerEventArgs e) { if (e.target.GetComponent<SteamVR_InteractRay>() != null) { e.target.GetComponent<SteamVR_InteractRay>().RayClick(); } } private void LaserPointer_PointerOut(object sender, PointerEventArgs e) { if (e.target.GetComponent<SteamVR_InteractRay>() != null) { e.target.GetComponent<SteamVR_InteractRay>().RayExit(); } }}
该组件挂载至RightHand上,同时RightHand上要挂载SteamVR_LaserPointer组件
运行游戏,手柄射线分别与CubeA、CubeB交互,正常打印信息