开启辅助访问
 找回密码
 注册帐号

扫一扫,访问微社区

VR/AR开发

关注:454

当前位置:游戏蛮牛 技术专区 VR/AR开发

查看: 1028|回复: 7

基于SteamVR_Unity_Toolkit自定义射线触发器简单结构

[复制链接]  [移动端链接]
5熟悉之中
716/1000
排名
3345
昨日变化
4

5

主题

140

帖子

716

积分

Rank: 5Rank: 5

UID
68545
好友
8
蛮牛币
2507
威望
0
注册时间
2015-1-14
在线时间
225 小时
最后登录
2017-9-14
发表于 2016-12-29 21:49:05 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册帐号

x
环境:HtcVive,Unity,C#,商店的SteamVR_Unity_Toolkit插件目前htc交互比较主流的还是那个实体射线交互,工具包自带的三种:GetComponent().DestinationMarkerEnterGetComponent().DestinationMarkerExitGetComponent().DestinationMarkerSet工具包自带的三种交互使用起来不太灵活,自己在VRTK_SimplePointer基础上拓展了一点功能,这里提供一个简单的例子:
废话不多说直接上:/// <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种,后期可以跟进     */}1、这是Base模版,大概思路是,触发后根据消息解析做出相应处理,还是比较灵活的。public class SteamVR_PointTriggerBase : MonoBehaviour {    //左右手柄输入器    public SteamVR_TrackedObject rightTracket;    public SteamVR_TrackedObject leftTracket;    //左右射线头位置    public Transform rightPoint;    public Transform leftPoint;    protected string msg;    /// <summary>    /// 有响应    /// </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>    /// 射线按下进入    /// </summary>    protected virtual void OnPointEnter() { Debug.Log("OnPointEnter"); }    /// <summary>    /// 射线按下且在物体上    /// </summary>    protected virtual void OnPointStayDown()     {        //以下时我目前根据项目加新增的,后期可以独立出来        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();            }        }    }    //这俩是临时加的为:当进入时左右手钩住扳机    protected virtual void OnPointStayDownRightTriggerTouch() { }    protected virtual void OnPointStayDownLeftTriggerTouch() { }     //当射线在物体上时弹起发射线按钮    protected virtual void OnPointStayUp() { Debug.Log("OnPointStayUp"); }    //退出    protected virtual void OnExitState() {EffectHighting.ResetRemoveHightingEffect();Debug.Log("OnExitState"); }2、使用的例子:
如我写的一个控制灯的开关的功能,只需要利用其中一种就可以了:
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; ;        }    }    //开关灯    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();    }    //只个只用到了一种回调:当射线进入并在内部弹起后响应    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,临时改的,还没有优化过,后期可以补上,思路就是利用射线检测判断一些情况的逻辑,主要是改了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);                //增加射线触发事件                //是否检测到物体                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;                }                      //当检检测到物体时                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                         * 当射线在检测物体内,弹按钮回掉                         */                        selectObj.GetComponent<SteamVR_PointTriggerBase>().Trigger(Msg_PointTrigger.PointStayUpMsg);                        selectObj.GetComponent<SteamVR_PointTriggerBase>().Trigger(Msg_PointTrigger.PointExittMsg);                        selectObj = null;                    }                }            }        }
[发帖际遇]: ztgg 发帖时在路边捡到 1 蛮牛币,偷偷放进了口袋. 幸运榜 / 衰神榜

回复

使用道具 举报

5熟悉之中
716/1000
排名
3345
昨日变化
4

5

主题

140

帖子

716

积分

Rank: 5Rank: 5

UID
68545
好友
8
蛮牛币
2507
威望
0
注册时间
2015-1-14
在线时间
225 小时
最后登录
2017-9-14
 楼主| 发表于 2016-12-29 21:50:29 | 显示全部楼层
坑爹的蛮牛,markdown居然不支持。。。
[发帖际遇]: ztgg 在网吧通宵,花了 2 蛮牛币. 幸运榜 / 衰神榜

回复 支持 反对

使用道具 举报

5熟悉之中
716/1000
排名
3345
昨日变化
4

5

主题

140

帖子

716

积分

Rank: 5Rank: 5

UID
68545
好友
8
蛮牛币
2507
威望
0
注册时间
2015-1-14
在线时间
225 小时
最后登录
2017-9-14
 楼主| 发表于 2016-12-29 21:51:31 | 显示全部楼层
[C#] 纯文本查看 复制代码
废话不多说直接上:

/// <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种,后期可以跟进
     */
}

回复 支持 反对

使用道具 举报

5熟悉之中
716/1000
排名
3345
昨日变化
4

5

主题

140

帖子

716

积分

Rank: 5Rank: 5

UID
68545
好友
8
蛮牛币
2507
威望
0
注册时间
2015-1-14
在线时间
225 小时
最后登录
2017-9-14
 楼主| 发表于 2016-12-29 21:53:10 | 显示全部楼层
[C#] 纯文本查看 复制代码
1、这是Base模版,大概思路是,触发后根据消息解析做出相应处理,还是比较灵活的。

public class SteamVR_PointTriggerBase : MonoBehaviour {
    //左右手柄输入器
    public SteamVR_TrackedObject rightTracket;
    public SteamVR_TrackedObject leftTracket;
    //左右射线头位置
    public Transform rightPoint;
    public Transform leftPoint;
    protected string msg;
    /// <summary>
    /// 有响应
    /// </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>
    /// 射线按下进入
    /// </summary>
    protected virtual void OnPointEnter() { Debug.Log("OnPointEnter"); }
    /// <summary>
    /// 射线按下且在物体上
    /// </summary>
    protected virtual void OnPointStayDown() 
    {
        //以下时我目前根据项目加新增的,后期可以独立出来
        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();
            }
        }
    }
    //这俩是临时加的为:当进入时左右手钩住扳机
    protected virtual void OnPointStayDownRightTriggerTouch() { }
    protected virtual void OnPointStayDownLeftTriggerTouch() { } 
    //当射线在物体上时弹起发射线按钮
    protected virtual void OnPointStayUp() { Debug.Log("OnPointStayUp"); }
    //退出
    protected virtual void OnExitState() {EffectHighting.ResetRemoveHightingEffect();Debug.Log("OnExitState"); }
2、使用的例子:

如我写的一个控制灯的开关的功能,只需要利用其中一种就可以了:

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; ;
        }
    }
    //开关灯
    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();
    }
    //只个只用到了一种回调:当射线进入并在内部弹起后响应
    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,临时改的,还没有优化过,后期可以补上,思路就是利用射线检测判断一些情况的逻辑,主要是改了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);
                //增加射线触发事件
                //是否检测到物体
                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;
                }      
                //当检检测到物体时
                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
                         * 当射线在检测物体内,弹按钮回掉
                         */
                        selectObj.GetComponent<SteamVR_PointTriggerBase>().Trigger(Msg_PointTrigger.PointStayUpMsg);
                        selectObj.GetComponent<SteamVR_PointTriggerBase>().Trigger(Msg_PointTrigger.PointExittMsg);
                        selectObj = null;
                    }
                }
            }
        }
[发帖际遇]: 一个袋子砸在了 ztgg 头上,ztgg 赚了 1 蛮牛币. 幸运榜 / 衰神榜

回复 支持 反对

使用道具 举报

3偶尔光临
229/300
排名
9236
昨日变化
11

1

主题

111

帖子

229

积分

Rank: 3Rank: 3Rank: 3

UID
195727
好友
0
蛮牛币
481
威望
0
注册时间
2016-12-23
在线时间
33 小时
最后登录
2017-6-18
发表于 2016-12-29 23:30:12 | 显示全部楼层
666666666666666

回复 支持 反对

使用道具 举报

3偶尔光临
243/300
排名
31673
昨日变化
33

0

主题

44

帖子

243

积分

Rank: 3Rank: 3Rank: 3

UID
189111
好友
0
蛮牛币
16
威望
0
注册时间
2016-12-3
在线时间
193 小时
最后登录
2017-9-25
发表于 2017-1-18 11:29:41 | 显示全部楼层
这个真的6 最近一直在研究 射线与物体交互
[发帖际遇]: Sivona 乐于助人,奖励 2 蛮牛币. 幸运榜 / 衰神榜

回复 支持 反对

使用道具 举报

6蛮牛粉丝
1335/1500
排名
2175
昨日变化
15

0

主题

298

帖子

1335

积分

Rank: 6Rank: 6Rank: 6

UID
148634
好友
1
蛮牛币
2677
威望
0
注册时间
2016-5-15
在线时间
531 小时
最后登录
2017-9-25
发表于 2017-2-14 22:08:49 | 显示全部楼层
非常好!!!
[发帖际遇]: 一个袋子砸在了 ycmanniu 头上,ycmanniu 赚了 1 蛮牛币. 幸运榜 / 衰神榜

回复

使用道具 举报

4四处流浪
391/500
排名
5699
昨日变化
41

9

主题

69

帖子

391

积分

Rank: 4

UID
186163
好友
1
蛮牛币
773
威望
0
注册时间
2016-11-23
在线时间
135 小时
最后登录
2017-9-25
发表于 2017-9-5 19:56:36 | 显示全部楼层
最近一直在研究 射线与物体交互

回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则

快速回复 返回顶部 返回列表