環(huán)境:HtcVive灭忠,Unity简卧,C#屠橄,商店的SteamVR_Unity_Toolkit插件
目前htc交互比較主流的還是那個(gè)實(shí)體射線交互,工具包自帶的三種:
GetComponent().DestinationMarkerEnter
GetComponent().DestinationMarkerExit
GetComponent().DestinationMarkerSet
工具包自帶的三種交互使用起來不太靈活闰挡,自己在VRTK_SimplePointer基礎(chǔ)上拓展了一點(diǎn)功能锐墙,這里提供一個(gè)簡單的例子:
廢話不多說直接上:
/// <summary>
/// 這是M,不多說
/// </summary>
public class Msg_PointTrigger
{
public const string PointEnterMsg = "EnterTrigger";
public const string PointStayDownMsg = "PointStayDownMsg";
public const string PointStayUpMsg = "PointStayUPMsg";
public const string PointExittMsg = "ExittMsg";
/*
* 這里只做了4種长酗,后期可以跟進(jìn)
*/
}
1溪北、這是Base模版,大概思路是夺脾,觸發(fā)后根據(jù)消息解析做出相應(yīng)處理之拨,還是比較靈活的。
public class SteamVR_PointTriggerBase : MonoBehaviour {
//左右手柄輸入器
public SteamVR_TrackedObject rightTracket;
public SteamVR_TrackedObject leftTracket;
//左右射線頭位置
public Transform rightPoint;
public Transform leftPoint;
protected string msg;
/// <summary>
/// 有響應(yīng)
/// </summary>
/// <param name="msg"></param>
public virtual void Trigger(string msg)
{
this.msg = msg;
ExplainMSg();
}
private void ExplainMSg()
{
switch (msg)
{
case Msg_PointTrigger.PointEnterMsg :
OnPointEnter();
break;
case Msg_PointTrigger.PointStayDownMsg:
OnPointStayDown();
break;
case Msg_PointTrigger.PointStayUpMsg:
OnPointStayUp();
break;
case Msg_PointTrigger.PointExittMsg:
OnExitState();
break;
default:
break;
}
}
/// <summary>
/// 射線按下進(jìn)入
/// </summary>
protected virtual void OnPointEnter() { Debug.Log("OnPointEnter"); }
/// <summary>
/// 射線按下且在物體上
/// </summary>
protected virtual void OnPointStayDown()
{
//以下時(shí)我目前根據(jù)項(xiàng)目加新增的咧叭,后期可以獨(dú)立出來
EffectHighting.AddConstantHighting(gameObject);
if (null!=rightTracket)
{
SteamVR_Controller.Device rightDevice = SteamVR_Controller.Input((int)rightTracket.index);
if (rightDevice.GetTouch(SteamVR_Controller.ButtonMask.Trigger))
{
Debug.Log("右手Triger按下");
OnPointStayDownRightTriggerTouch();
}
}
if (null!=leftTracket)
{
SteamVR_Controller.Device leftDevice = SteamVR_Controller.Input((int)leftTracket.index);
if (leftDevice.GetTouch(SteamVR_Controller.ButtonMask.Trigger))
{
Debug.Log("左手Triger按下");
OnPointStayDownLeftTriggerTouch();
}
}
}
//這倆是臨時(shí)加的為:當(dāng)進(jìn)入時(shí)左右手鉤住扳機(jī)
protected virtual void OnPointStayDownRightTriggerTouch() { }
protected virtual void OnPointStayDownLeftTriggerTouch() { }
//當(dāng)射線在物體上時(shí)彈起發(fā)射線按鈕
protected virtual void OnPointStayUp() { Debug.Log("OnPointStayUp"); }
//退出
protected virtual void OnExitState() {EffectHighting.ResetRemoveHightingEffect();Debug.Log("OnExitState"); }
2蚀乔、使用的例子:
如我寫的一個(gè)控制燈的開關(guān)的功能,只需要利用其中一種就可以了:
public class SteamVR_PointTriggerLights : SteamVR_PointTriggerBase
{
public bool isOn = false;
//變色
public void TrunColor(Color openColor, Color closeColor)
{
if (isOn)
{
gameObject.GetComponent<MeshRenderer>().material.color = openColor;
}
else
{
gameObject.GetComponent<MeshRenderer>().material.color = closeColor; ;
}
}
//開關(guān)燈
private void TurnLights(bool isOn)
{
PointLightControler.instance.TurnLights(isOn);
}
protected override void OnPointEnter()
{
base.OnPointEnter();
}
protected override void OnPointStayDown()
{
base.OnPointStayDown();
}
protected override void OnPointStayDownRightTriggerTouch()
{
base.OnPointStayDownRightTriggerTouch();
}
protected override void OnPointStayDownLeftTriggerTouch()
{
base.OnPointStayDownLeftTriggerTouch();
}
//只個(gè)只用到了一種回調(diào):當(dāng)射線進(jìn)入并在內(nèi)部彈起后響應(yīng)
protected override void OnPointStayUp()
{
base.OnPointStayUp();
isOn = !isOn;
TrunColor(Color.green, Color.red);
TurnLights(isOn);
Debug.Log("OnPointStayUp");
}
protected override void OnExitState()
{
base.OnExitState();
}
}
3菲茬、下面是改寫的VRTK_SimplePointer吉挣,臨時(shí)改的,還沒有優(yōu)化過婉弹,后期可以補(bǔ)上睬魂,思路就是利用射線檢測判斷一些情況的邏輯,主要是改了Update方法镀赌,附上參考一下
protected override void Update()
{
base.Update();
if (pointer.gameObject.activeSelf)
{
RaycastHit pointerCollidedWith;
Ray pointerRaycast = new Ray(transform.position, transform.forward);
var rayHit = Physics.Raycast(pointerRaycast, out pointerCollidedWith, pointerLength, ~layersToIgnore);
var pointerBeamLength = GetPointerBeamLength(rayHit, pointerCollidedWith);
SetPointerTransform(pointerBeamLength, pointerThickness);
//增加射線觸發(fā)事件
//是否檢測到物體
if (null!=pointerCollidedWith.collider)
{
selectObj = pointerCollidedWith.collider.gameObject;
}
else
{
/*
* -------------NO1
* 按下射線移出物體
*/
if (null!=selectObj)
{
if (null != selectObj.GetComponent<SteamVR_PointTriggerBase>())
{
selectObj.GetComponent<SteamVR_PointTriggerBase>().Trigger(Msg_PointTrigger.PointExittMsg);
}
}
selectObj = null;
canEnter = true;
}
//當(dāng)檢檢測到物體時(shí)
if (null != selectObj)
{
//物體是VR交互物體
if (null != selectObj.GetComponent<SteamVR_PointTriggerBase>())
{
/*
* --------------NO2
* 射線按下Enter事件
*/
if (canEnter)
{
canEnter = false;
if (transform.root.GetComponent<SteamVR_ControllerManager>().right.activeSelf)
{
selectObj.GetComponent<SteamVR_PointTriggerBase>().rightTracket = transform.root.GetComponent<SteamVR_ControllerManager>().right.GetComponent<SteamVR_TrackedObject>();
selectObj.GetComponent<SteamVR_PointTriggerBase>().rightPoint = pointerTip.transform;
//Debug.Log(pointerTip.transform.position);
}
if (transform.root.GetComponent<SteamVR_ControllerManager>().left.activeSelf)
{
selectObj.GetComponent<SteamVR_PointTriggerBase>().leftTracket = transform.root.GetComponent<SteamVR_ControllerManager>().left.GetComponent<SteamVR_TrackedObject>();
selectObj.GetComponent<SteamVR_PointTriggerBase>().leftPoint = pointerTip.transform;
}
selectObj.GetComponent<SteamVR_PointTriggerBase>().Trigger(Msg_PointTrigger.PointEnterMsg);
}
/*
* ------------NO3
* 射線按下Stay事件
*/
selectObj.GetComponent<SteamVR_PointTriggerBase>().Trigger(Msg_PointTrigger.PointStayDownMsg);
}
}
}
else
{
if (null != selectObj)
{
if (null != selectObj.GetComponent<SteamVR_PointTriggerBase>())
{
/*
* --------------------------NO4
* 當(dāng)射線在檢測物體內(nèi)氯哮,彈按鈕回掉
*/
selectObj.GetComponent<SteamVR_PointTriggerBase>().Trigger(Msg_PointTrigger.PointStayUpMsg);
selectObj.GetComponent<SteamVR_PointTriggerBase>().Trigger(Msg_PointTrigger.PointExittMsg);
selectObj = null;
}
}
}
}