VR开发实战之HTC Vive实现瞬移功能

一.什么是瞬移功能?

瞬移就是使用手柄选取一个位置,通过扳机键进行瞬间移动。
因为HTC Vive活动范围有限制(3m * 5m),所以我们在实际的使用中,为了更好的浏览场景,查看场景,会使用这种移动的方式,达到游戏中的视野移动。
移动的方式有两种:一种是水平移动即X,Z轴移动;另一种就是垂直移动,即Y轴移动。
PS : 我们通过射线检测的方法进行开发,因为HTC Vive有类似的脚本。所以我们只需更改脚本的某些部分就可实现瞬移功能。

二.案例详解

1.下载Steam VR,导入资源
2.将脚本复制,修改类名(部分脚本)
using UnityEngine;
using System.Collections;

public class SteamVR_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;


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)
    {
        HitPoint = hit.point;
    }
    if (bHit && hit.distance < 100f)
    {
        dist = hit.distance;
    }

    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);
   }
}
3.添加脚本
4.添加传送脚本
public class Test_TelePointer : MonoBehaviour {

//拿到手柄对象
public GameObject LeftController;
//修改后的射线检查脚本
private Test_LaserPointer Pointer;
//右手柄的控制器
private SteamVR_TrackedController LeftSt;
//事件调用函数
ClickedEventHandler ce;
//当前的目标位置
Transform currentTransform;
    //碰撞事件
PointerEventArgs arg;

void Start () {
    Pointer = LeftController.GetComponent<Test_LaserPointer>();
    LeftSt = LeftController.GetComponent<SteamVR_TrackedController>();
    //利用Laserpoint里面的事件函数来检测目标位置
    Pointer.PointerIn += LeftPointIn;
    //利用Laserpoint里面的事件函数来检测目标位置
    Pointer.PointerOut += LeftPointOut;
    //利用手柄控制器来检测我们的扳机事件
    LeftSt.TriggerClicked += TriggerClicked;
}


void Update () {

}

//没有检测到碰撞信息
void LeftPointOut(object sender, PointerEventArgs e)
{
    //当前位置为空
    currentTransform = null;
}
//检测到碰撞信息
void LeftPointIn(object sender, PointerEventArgs e)
{   
    // 设置目标位置为检测到的目标
    currentTransform = e.target;
}
//扳机事件
void TriggerClicked(object sender, ClickedEventArgs e)
{
    //如果检测到目标位置
    if (currentTransform != null)
    {
        //移动
        this.gameObject.transform.position = new Vector3(Pointer.HitPoint.x - LeftController.transform.localPosition.x, Pointer.HitPoint.y, Pointer.HitPoint.z - LeftController.transform.localPosition.z);
    }  
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容