通过手柄发射射线与UI按钮进行交互
在Button上需要添加的两个脚本和组件
手柄需要准备的内容
在手柄控制器上添加脚本SteamVR_LaserPointer,使得手柄可以发射射线,在创建脚本LaserInteraction实现UI交互功能
//为射线移入移出或点击Button时的三个事件添加监听事件,即UGUI中Button的移入、移出、点击事件
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using Valve.VR.Extras;
public class LaserInteraction : MonoBehaviour
{
// LaserPointer组件
private SteamVR_LaserPointer _laser;
// 当前交互的UI元素
private GameObject _uGUIElement;
// 是否开启激光指针交互
public bool isEnabled = true;
private void Awake()
{
// 获取到LaserPointer组件
_laser = GetComponent<SteamVR_LaserPointer>();
// 如果不为空
if (_laser != null)
{
// 如果不开启激光指针交互
if (!isEnabled)
{
// 激光指针不显示
_laser.enabled = false;
return;
}
else // 如果开启激光指针交互
{
_laser.PointerIn += LaserOnPointerIn;
_laser.PointerOut += LaserOnPointerOut;
_laser.PointerClick += LaserOnPointerClick;
}
}
}
private void LaserOnPointerIn(object sender, PointerEventArgs e)
{
IPointerEnterHandler _pointerEnterHandler = e.target.gameObject.GetComponent<IPointerEnterHandler>();
if (_pointerEnterHandler != null)
{
_pointerEnterHandler.OnPointerEnter(new PointerEventData(EventSystem.current));
}
}
private void LaserOnPointerOut(object sender, PointerEventArgs e)
{
IPointerExitHandler _pointerExitHandler = e.target.gameObject.GetComponent<IPointerExitHandler>();
if (_pointerExitHandler != null)
{
_pointerExitHandler.OnPointerExit(new PointerEventData(EventSystem.current));
}
}
private void LaserOnPointerClick(object sender, PointerEventArgs e)
{
IPointerClickHandler _pointerClickHandler = e.target.gameObject.GetComponent<IPointerClickHandler>();
if (_pointerClickHandler != null)
{
_pointerClickHandler.OnPointerClick(new PointerEventData(EventSystem.current));
}
}
}
另一种更简单的方式
首先手柄只需要挂上射线脚本Steam VR_Laser Pointer
然后对于UI元素,我们只需要在其上挂上碰撞器BoxCollider即可
最后也是最核心的就是我们需要为手柄射线移入移出点击 添加事件(上诉一样添加的是UGUI的按钮点击事件,这里是我们自身需要的逻辑函数)
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Valve.VR.Extras;
public class UIManager : MonoBehaviour
{
//将挂载了Steam VR_Laser Pointer的物体赋值给Hand,若两只手都需要请多定义一个并赋值和添加监听
[SerializeField] public GameObject Hand;
private void Start()
{
//为Hand的射线移入移出点击 绑定需要的函数
Hand.GetComponent<SteamVR_LaserPointer>().PointerIn += SceneOneUI_PointerIn;
Hand.GetComponent<SteamVR_LaserPointer>().PointerOut += SceneOneUI_PointerOut;
Hand.GetComponent<SteamVR_LaserPointer>().PointerClick += SceneOneUI_PointerClick;
}
private void SceneOneUI_PointerClick(object sender, PointerEventArgs e)
{
if (e.target.name == "Btn1")
{
Debug.log("挂载了碰撞体并且命为 Btn1 的物体被点击了");
}
//....扩展,若有其他UI元素需要交互,请为它添加BoxCollider组件,并命名
//例如下
/* if (e.target.name == "Btn2")
{
Debug.log("挂载了碰撞体并且命为 Btn1 的物体被点击了");
}*/
}
private void SceneOneUI_PointerOut(object sender, PointerEventArgs e)
{
if (e.target.name == "Btn1")
{
Debug.log("射线移出 挂载了碰撞体并且命为 Btn1 的物体");
}
}
private void SceneOneUI_PointerIn(object sender, PointerEventArgs e)
{
if (e.target.name == "Btn1")
{
Debug.log("射线移入 挂载了碰撞体并且命为 Btn1 的物体");
}
}
IEnumerator Btn1OnClick()
{
//点击后的游戏逻辑
}
}
如果我们还有其他UI 也可以在UIManager中扩展,只需要区别碰撞体不同的名字即可,当UI元素比较少时可以这么做,简单方便。