在VR(HTC VIVE)开发中,经常会使用到手柄发射射线指向VR菜单,菜单因此就有了射线进入、射线停留、射线停留时通过按下手柄扳机键或者其他按键后执行指定事件和射线离开四种状态。以前都是自己写的代码,来模仿Button组件的效果。可是今天一个UI设计师就想UI上面各个子对象都要用到Button组件,就想通过获取Button组件来控制四种状态,查看Button源码,找到了至关重要的一个函数:DoStateTransition(SelectionState.Normal, false);然后取得了控制权。
以下是实现这个功能的父类,继承自Button。
using UnityEngine.UI;
public class RayButton : Button
{
/// <summary>
/// 射线进入(对外接口)
/// </summary>
public virtual void RayEnter()
{
DoStateTransition(SelectionState.Highlighted, false);
}
/// <summary>
/// 射线停留(对外接口)
/// </summary>
public virtual void RayStay()
{
ResetButtonState();
}
/// <summary>
/// 射线离开(对外接口)
/// </summary>
public virtual void RayExit()
{
DoStateTransition(SelectionState.Normal, false);
}
/// <summary>
/// 射线一直处于进入状态时,可能需要执行的事件
/// </summary>
public virtual void TriggerEvent()
{
DoStateTransition(SelectionState.Pressed, false);
}
/// <summary>
/// 事件完成
/// </summary>
public virtual void ResetButtonState()
{
DoStateTransition(SelectionState.Highlighted, false);
}
}
父类提供了对外的接口,子类继承时可重写这些方法。通过射线检测获取到射线碰撞对象,然后从碰撞对象上获取RayButton对象,再调用对应的函数即可。
对了,推荐一款工具——ILSpy,用来反编译一般的DLL文件。
下面上一个简单的测试代码:
using UnityEngine;
using System.Collections;
public class RayButtonTest : RayButton {
public override void RayEnter()
{
base.RayEnter();
}
public override void RayStay()
{
base.RayStay();
}
public override void RayExit()
{
base.RayExit();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
RayEnter();
}
else if(Input.GetKeyDown(KeyCode.A))
{
RayExit();
}
}
}