26 VR開(kāi)發(fā)—— HTC Vive瞬移功能的實(shí)現(xiàn)

一坎匿、為什么要實(shí)現(xiàn)瞬移這個(gè)功能##

因?yàn)镠TC Vive活動(dòng)范圍有限制(3m * 5m)奈惑,所以我們?cè)趯?shí)際的使用中慌申,為了更好的瀏覽場(chǎng)景陌选,查看場(chǎng)景,會(huì)使用這種移動(dòng)的方式蹄溉,達(dá)到游戲中的視野移動(dòng)咨油。
一般來(lái)說(shuō)就是手柄選取一個(gè)位置,通過(guò)扳機(jī)鍵確認(rèn)移動(dòng)柒爵。
移動(dòng)的方式有兩種:一種是水平移動(dòng)即X役电,Z軸移動(dòng);另一種就是垂直移動(dòng),即Y軸移動(dòng)。

二棉胀、實(shí)現(xiàn)過(guò)程##

這瞬移過(guò)程中最重要的是拿到目標(biāo)位置的坐標(biāo)法瑟,我們可以通過(guò)射線檢測(cè)拿到位置.
在Steam VR插件給我們提供了封裝好的類與方法冀膝,我們做出相應(yīng)的改變得到我們需要的結(jié)果.
射線檢測(cè)腳本
重寫代碼展示:
using UnityEngine;
using System.Collections;

//public struct PointerEventArgs
//{
//    public uint controllerIndex;
//    public uint flags;
//    public float distance;
//    public Transform target;
//}

//public delegate void PointerEventHandler(object sender, PointerEventArgs e);



public class Test_LaserPointer : MonoBehaviour
{
    public bool active = true;
    public Color color;
    public float thickness = 0.002f;
    public GameObject holder;
    public GameObject pointer;
    bool isActive = false;
    public bool addRigidBody = false;
    public Transform reference;
    public event PointerEventHandler PointerIn;
    public event PointerEventHandler PointerOut;

    public Vector3 HitPoint;//添加的量找到目標(biāo)位置
    Transform previousContact = null;

    // Use this for initialization
    void Start ()
    {
        holder = new GameObject();
        holder.transform.parent = this.transform;
        holder.transform.localPosition = Vector3.zero;
        holder.transform.localRotation = Quaternion.identity;

        pointer = GameObject.CreatePrimitive(PrimitiveType.Cube);
        pointer.transform.parent = holder.transform;
        pointer.transform.localScale = new Vector3(thickness, thickness, 100f);
        pointer.transform.localPosition = new Vector3(0f, 0f, 50f);
        pointer.transform.localRotation = Quaternion.identity;
        BoxCollider collider = pointer.GetComponent<BoxCollider>();
        if (addRigidBody)
        {
            if (collider)
            {
                collider.isTrigger = true;
            }
            Rigidbody rigidBody = pointer.AddComponent<Rigidbody>();
            rigidBody.isKinematic = true;
        }
        else
        {
            if(collider)
            {
                Object.Destroy(collider);
            }
        }
        Material newMaterial = new Material(Shader.Find("Unlit/Color"));
        newMaterial.SetColor("_Color", color);
        pointer.GetComponent<MeshRenderer>().material = newMaterial;
    }

    public virtual void OnPointerIn(PointerEventArgs e)
    {
        if (PointerIn != null)
            PointerIn(this, e);
    }

    public virtual void OnPointerOut(PointerEventArgs e)
    {
        if (PointerOut != null)
            PointerOut(this, e);
    }


    // Update is called once per frame
    void Update ()
    {
        if (!isActive)
        {
            isActive = true;
            this.transform.GetChild(0).gameObject.SetActive(true);
        }

        float dist = 100f;

        SteamVR_TrackedController controller = GetComponent<SteamVR_TrackedController>();

        Ray raycast = new Ray(transform.position, transform.forward);
        RaycastHit hit;
        bool bHit = Physics.Raycast(raycast, out hit);

        if(previousContact && previousContact != hit.transform)
        {
            PointerEventArgs args = new PointerEventArgs();
            if (controller != null)
            {
                args.controllerIndex = controller.controllerIndex;
            }
            args.distance = 0f;
            args.flags = 0;
            args.target = previousContact;
            OnPointerOut(args);
            previousContact = null;
        }
        if(bHit && previousContact != hit.transform)
        {
            PointerEventArgs argsIn = new PointerEventArgs();
            if (controller != null)
            {
                argsIn.controllerIndex = controller.controllerIndex;
            }
            argsIn.distance = hit.distance;
            argsIn.flags = 0;
            argsIn.target = hit.transform;
            OnPointerIn(argsIn);
            previousContact = hit.transform;
        }
        if(!bHit)
        {
            previousContact = null;
        }
        if (bHit && hit.distance < 100f)
        {
            dist = hit.distance;
        }

        if (bHit)//添加的實(shí)現(xiàn)代碼;
        {
            HitPoint = hit.point;
        }

        if (controller != null && controller.triggerPressed)
        {
            pointer.transform.localScale = new Vector3(thickness * 5f, thickness * 5f, dist);
        }
        else
        {
            pointer.transform.localScale = new Vector3(thickness, thickness, dist);
        }
        pointer.transform.localPosition = new Vector3(0f, 0f, dist/2f);
    }
}

SteamVR_TrackedController腳本
下面就是自己寫代碼實(shí)現(xiàn)瞬移過(guò)程:
代碼展示及邏輯:
public class Test_Teleporter : MonoBehaviour {

    // 拿到手柄對(duì)象
    public GameObject LeftController;
    //修改后的射線檢測(cè)腳本
    private Test_LaserPointer Pointer;
    // 右手柄的控制器
    private SteamVR_TrackedController LeftSt;
    // 事件調(diào)用函數(shù)
    ClickedEventHandler ce;
    // 當(dāng)前的目標(biāo)位置
    Transform currentTransform;
    // 碰撞事件
    PointerEventArgs arg;
    void Start()
    {
        Pointer = LeftController.GetComponent<Test_LaserPointer>();
        LeftSt = LeftController.GetComponent<SteamVR_TrackedController>();
        // 利用Laserpoint里面的事件函數(shù)來(lái)檢測(cè)目標(biāo)位置
        Pointer.PointerIn += LeftPointIn;
        //  利用Laserpoint里面的事件函數(shù)來(lái)檢測(cè)目標(biāo)位置
        Pointer.PointerOut += LeftPointOut;
        // 利用手柄控制器來(lái)檢測(cè)我們的扳機(jī)事件
        LeftSt.TriggerClicked += TriggerClicked;
    }

    // 沒(méi)有檢測(cè)到碰撞信息
    void LeftPointOut(object sender, PointerEventArgs e)
    {   // 當(dāng)前位置沒(méi)有
        currentTransform = null;
    }
    // 檢測(cè)到碰撞信息
    void LeftPointIn(object sender, PointerEventArgs e)
    {   // 設(shè)置目標(biāo)位置為檢測(cè)到的目標(biāo)
        currentTransform = e.target;
    }
    // 扳機(jī)事件
    void TriggerClicked(object sender, ClickedEventArgs e)
    {
        // 如果檢測(cè)到目標(biāo)位置
        if (currentTransform != null)
        {    // 移動(dòng)
            this.gameObject.transform.position = new Vector3(Pointer.HitPoint.x - LeftController.transform.localPosition.x, Pointer.HitPoint.y, Pointer.HitPoint.z - LeftController.transform.localPosition.z);
        }
    }
}

三霎挟、結(jié)果實(shí)現(xiàn)##

掛載腳本窝剖,實(shí)現(xiàn)結(jié)果
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市氓扛,隨后出現(xiàn)的幾起案子枯芬,更是在濱河造成了極大的恐慌论笔,老刑警劉巖采郎,帶你破解...
    沈念sama閱讀 218,858評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異狂魔,居然都是意外死亡蒜埋,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門最楷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)整份,“玉大人,你說(shuō)我怎么就攤上這事籽孙×移溃” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 165,282評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵犯建,是天一觀的道長(zhǎng)讲冠。 經(jīng)常有香客問(wèn)我,道長(zhǎng)适瓦,這世上最難降的妖魔是什么竿开? 我笑而不...
    開(kāi)封第一講書人閱讀 58,842評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮玻熙,結(jié)果婚禮上否彩,老公的妹妹穿的比我還像新娘。我一直安慰自己嗦随,他們只是感情好列荔,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著枚尼,像睡著了一般贴浙。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上姑原,一...
    開(kāi)封第一講書人閱讀 51,679評(píng)論 1 305
  • 那天悬而,我揣著相機(jī)與錄音,去河邊找鬼锭汛。 笑死笨奠,一個(gè)胖子當(dāng)著我的面吹牛袭蝗,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播般婆,決...
    沈念sama閱讀 40,406評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼到腥,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了蔚袍?” 一聲冷哼從身側(cè)響起乡范,我...
    開(kāi)封第一講書人閱讀 39,311評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎啤咽,沒(méi)想到半個(gè)月后晋辆,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,767評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡宇整,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年瓶佳,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鳞青。...
    茶點(diǎn)故事閱讀 40,090評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡霸饲,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出臂拓,到底是詐尸還是另有隱情厚脉,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評(píng)論 5 346
  • 正文 年R本政府宣布胶惰,位于F島的核電站傻工,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏童番。R本人自食惡果不足惜精钮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望剃斧。 院中可真熱鬧轨香,春花似錦、人聲如沸幼东。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,988評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)根蟹。三九已至脓杉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間简逮,已是汗流浹背球散。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,101評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留散庶,地道東北人蕉堰。 一個(gè)月前我還...
    沈念sama閱讀 48,298評(píng)論 3 372
  • 正文 我出身青樓凌净,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親屋讶。 傳聞我的和親對(duì)象是個(gè)殘疾皇子冰寻,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容