> 文档中心 > SteamVR 2.x UGUI-凝视交互(8)

SteamVR 2.x UGUI-凝视交互(8)

除了手部触碰以及射线交互UI以外,还有一个目前很多VR一体机使用的凝视交互,这种方式不需要使用手柄去和UI交互,直接使用凝视,几秒钟自动触发事件,不过这种方式,目前只支持Button,其他UI控件不支持,做项目UI交互的话,还是使用前两种UI交互方式。

一、前期准备

新建场景,删除默认相机,将Player拖拽进入场景内
SteamVR 2.x UGUI-凝视交互(8)
新建Plane,修改为Floor,上一个黑色材质球,Transform信息如下:
SteamVR 2.x UGUI-凝视交互(8)

二、添加UI及组件

结构如下,添加画布、按钮
SteamVR 2.x UGUI-凝视交互(8)
SteamVR 2.x UGUI-凝视交互(8)
1、Canvas/画布信息
Render Mode要设置为World Space/世界模式
SteamVR 2.x UGUI-凝视交互(8)
2、Button信息
SteamVR 2.x UGUI-凝视交互(8)

三、制作凝视组件

将图片下载并保存至项目中
在这里插入图片描述
组件结构如下:
SteamVR 2.x UGUI-凝视交互(8)
1、画布信息:
SteamVR 2.x UGUI-凝视交互(8)
2、Cursor信息
我们可以手动改变Iamge的透明度和颜色
SteamVR 2.x UGUI-凝视交互(8)
3、Process信息
进度我们可以改为黄色,Image Type改为Filled填充类型
SteamVR 2.x UGUI-凝视交互(8)

四、编写脚本并挂载

using UnityEngine;using UnityEngine.UI;using Valve.VR.InteractionSystem;public class SteamVR_HeadGaze : MonoBehaviour{    private Transform headCamera;    //头部相机    private Transform cursor; //射线光标    private Image progress;   //凝视进度    private LayerMask layerMask;     //凝视交互层    private float stareTimer; //凝视时间    private Vector3 rayPositionOffset = new Vector3(0, 0.005f, 0);      //射线偏移量    private float rayLength = 50f;   //射线长度    private GameObject currentInteractable; //当前交互对象    private GameObject previousInteractable;//上一个交互对象    [Header("凝视激活时间")]    public float activateTime = 3;    private void Awake()    { layerMask= 1 << LayerMask.NameToLayer("UI"); headCamera = Camera.main.transform; cursor = transform.GetChild(0).transform; progress = cursor.GetChild(0).GetComponent<Image>();    }    private void Update()    { if (headCamera == null) return; if (progress != null) { progress.fillAmount = 0; } EyeRaycast();    }    ///     /// 眼部射线    ///     private void EyeRaycast()    { Vector3 adjustedPosition = headCamera.position + (headCamera.right * rayPositionOffset.x) +(headCamera.up * rayPositionOffset.y) +(headCamera.forward * rayPositionOffset.z); Ray ray = new Ray(adjustedPosition, headCamera.forward); RaycastHit hit; if (Physics.Raycast(ray, out hit, rayLength, layerMask)) {     if (cursor != null)     {  cursor.gameObject.SetActive(true);  cursor.position = hit.point;  cursor.rotation = headCamera.rotation;     }     Button aButton = hit.transform.GetComponent<Button>();     if (aButton == null)     {  ResetInteractable();  currentInteractable = null;  return;     }     currentInteractable = aButton.gameObject;     if (currentInteractable && currentInteractable != previousInteractable)     {  InputModule.instance.HoverBegin(currentInteractable);     }     else if (currentInteractable == previousInteractable)     {  stareTimer += Time.deltaTime;  if (progress != null)  {      progress.fillAmount = (stareTimer / activateTime);  }  if (stareTimer > activateTime)  {      InputModule.instance.Submit(currentInteractable);      stareTimer = 0;      ResetInteractable();  }     }     if (currentInteractable != previousInteractable) { ResetInteractable(); }     previousInteractable = currentInteractable; } else  {     ResetInteractable();     currentInteractable = null; }    }    ///     /// 重置交互    ///     private void ResetInteractable()    { stareTimer = 0; if (progress != null) { progress.fillAmount = 0; } if (previousInteractable == null) { return; } InputModule.instance.HoverEnd(previousInteractable); previousInteractable = null; if (cursor != null) {     cursor.gameObject.SetActive(false); }    }}

脚本就100来行,直接挂载到HeadGazeUI组件上,什么参数都不需要进行设置。
至此,只要Button上挂载了碰撞器,运行游戏后,头盔视野看向Button,会看到有一个黄色的圆圈在自动填充,3s后自动触发按钮