首先,这里有一个需求,就是要用手柄在vr里边去点击按钮,当然可以用vrtk去实现该功能,但是我们这里还要让这个界面同时及接受手势操作,这里就得用碰撞盒3d检测,这就和原本 的2D冲突了,此时也难以实现按钮的高亮显示。
为了解决这个问题,在3D中实现高亮动画等效果,想出了一下解决方案。
由于我们要让该按钮不限制于只接受射线来触发,可以让3d物体来触发。给按钮添加碰撞盒,调整大小位置,将tag等改为你射线能检测的tag,以接受射线的触发。勾选trigger。即可穿
添加如下脚本
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;
#region 接受扩展实现
public delegate void OnRayEnter(GameObject obj);
public delegate void OnRayExit(GameObject obj);
public delegate void OnRayStay(GameObject obj);
public delegate void OnClickTrigger(GameObject obj);
#endregion
public enum RayState
{
None,
Enter,
Stay,
Exit,
}
/// <summary>
/// 需要添加射线相关事件的物体挂载此脚本
/// </summary>
public class RayObject : Selectable
{
public OnRayEnter onenter;
public OnRayExit onexit;
public OnRayStay onstay;
public OnClickTrigger onclick;
[HideInInspector ]
public string Name;
protected override void Start()
{
Name = gameObject.name;
}
/// <summary>
/// 射线事件
/// </summary>
/// <param name="state"></param>
public void OnRayState(RayState state)
{
switch (state)
{
case RayState.None:
break;
case RayState.Enter:
OnPointerEnter(null);
if (onenter != null)
onenter.Invoke(this .gameObject );
break;
case RayState.Stay:
if (onstay != null)
onstay.Invoke(gameObject);
break;
case RayState.Exit:
OnPointerExit(null);
if (onexit != null)
onexit.Invoke(gameObject);
break;
default:
break;
}
}
public void OnTriggerClick()
{
if (onclick != null)
onclick.Invoke(gameObject);
}
public override void OnPointerEnter(PointerEventData eventData)
{
base.OnPointerEnter(eventData);
}
public override void OnPointerExit(PointerEventData eventData)
{
base.OnPointerExit(eventData);
}
}
对于检测触发就不做赘述了,你可以用射线,也可以用3D物体,只需要在触发的时候获取物体上的这个脚本,调用OnRayState方法和click方法,这里将click方法独立了出来,你自己注册绑定,而射线的触发就可以像鼠标触发2D界面一样,你不用再做好几个图片啥的来切换 了。
这里的脚本是做一个桥梁来使用,你可以在外部给它添加额外的事件,它还包含自身原有的显示事件,关键在于Selectable 的继承,手动去调用pointer事件,注意的是click方法手动掉传入null是会报空异常的,这里点击事件就注册就行。如有大佬研究出来,可以留言分享,感谢!