Steam VR的使用(二)

SteamVR 抛物线移动

其实实现抛物线很简单,生成一组抛物点,然后将点渲染成线就好。渲染成线有很多方式,你可以用模型,也可以用GL的绘制线段,也可以用LineRender。重点是优化点的生成计算。

楼主上班比较忙,很少写demo。我做项目一般有严密的框架,但是为了更加简明的为大家展示功能的实现剔除了很多代码,并且写了不符合我风格的代码,就是为了让大家能看清楚功能的实现。

我不是个人开发者,家中无测试环境,如果有问题可以在下面回复。本教程中的代码已经用在实际的案例上,因为工作保密我不能截图或者共享项目源码,只是把开发过程的部分代码功能以个人的名义分享,欢迎交流。

如何生成抛物点,一个很简单的公式:

nextPos = lastPos + 水平位移 + 垂直位移。

稍后的代码有详尽的注释我就不多赘述了。

重点是对点集的优化,优化抛物点分两个部分,一是如何计算碰撞点,二是内存开销的优化。考虑到一般的VR项目只在水平面上进行移动,所以通过判断抛物点的y轴来判定碰撞。关于内存开销,我们可以限定生成的抛物点个数,同时优化计算。我们使用一个List来保存点集,动态的根据点的情况来生成点,或者改变点的位置。例如当手柄角度不变时,只需要将List集合中的点改变Y轴就行了。

现在思路已经明了了。以下是伪代码:

int i = 0;

while( nextPos.y>0 && maxPoint>0 ){

if(list.count<=i){

list.add(nextPos);

}

else{

list[i] = nextPos;

}

///生成,优化,计算下一个抛物点

i++;

}

list.remove(i,list.count-i);//移除上一个点集的多余数据

生成抛物线点集后,接下来就是绘制曲线,LineRender,GL都可以很方便的绘制。但是就性能来说,GL更加快一点。建议大家用GL。当然大家也可以使用自己的模型绘制,原理就是,在对应的点生成你的模型,然后计算对应的角度即可。这几种实现方案我都会写到代码中,效果大家自己调用查看。

最后就是生成抛物线的终点,因为我是按照y轴来判断抛物线的落点,但是落点可能有障碍物等等,或者落点在墙角,这些位置显然是不能跳跃的,所以我们需要对落点进行判断。在Physics中有一个方法可以检测一个球形范围是否会碰撞,我们可以给地面添加一个层,以便忽略地面的检测,这样就可以安全的着陆了。

好了,也许你没听懂,没关系,接下来就是代码,代码中也有详尽的注释。

using UnityEngine;
using System.Collections.Generic;
using System;

/// <summary>
/// 抛物线脚本
/// </summary>
public class HandRay : MonoBehaviour
{

    private Transform CurrentHand; //当前触发的手
    private List<Vector3> pointList; //曲线点集合
    private Quaternion lastRotation; //上一个移动的角度
    private Vector3 lastPostion; //上一个位置
    private Vector3 lastPos; //上一个点,为了优化将一个临时变量做成全局的,节省内存开销
    private Vector3 nextPos;//下一个点,理由同上
    private event Action OnChangeTransform;//一个事件,用来检测手柄位置和角度变化的
    private Material material;//渲染射线的材质球
    private Vector3 HitPoint;//抛物线的碰撞点
    private Ray ray;
    private bool canJump = false;//

    public GameObject PointEffect;//一个特效,就是在射线的终点放置一个光柱什么的,大家可以自己做这个特效

    public int MaxPoint;  //生成曲线的点最大数量
    public float Distence;//水平位移
    public float Grity;//垂直位移
    public float CheckRange;//检测位置是否存在障碍物

    public void Awake()
    {
        SetData();
    }

    public void Start()
    {
        pointList = new List<Vector3>();
        OnChangeTransform += OnChangeTransformCallBack;
        HitPoint = -Vector3.one;
        ray = new Ray();

    }
    public void Update()
    {
        //当手柄按下触摸键同时角度合适时触发事件开始计算点
        if (CurrentHand != null && ((CurrentHand.eulerAngles.x > 275 && CurrentHand.eulerAngles.x <= 360) || (CurrentHand.eulerAngles.x >= -0.01f && CurrentHand.eulerAngles.x < 85)))
        {
            if (OnChangeTransform != null) OnChangeTransform();
        }
        else
        {
            pointList.Clear();
            PointEffect.SetActive(false);
        }
    }
    /// <summary>
    /// 计算抛物线的点
    /// 此方法已经优化过性能
    ///
    /// </summary>
    private void OnChangeTransformCallBack()
    {
        if (lastRotation != CurrentHand.rotation || lastPostion != CurrentHand.position)
        {
            lastPos = nextPos = CurrentHand.position;
            int i = 0;
            while (nextPos.y > 0 && (i < MaxPoint))
            {
                if (pointList.Count <= i)
                {
                    pointList.Add(nextPos);
                }
                else
                {
                    pointList[i] = nextPos;
                }
                if (lastRotation == CurrentHand.rotation && lastPostion != CurrentHand.position && i < pointList.Count - 1)
                {
                    nextPos = pointList[i + 1] + CurrentHand.position - lastPostion;
                }
                else
                {
                    nextPos = lastPos + CurrentHand.rotation * Vector3.forward * Distence + Vector3.up * Grity * 0.1f * i * Time.fixedDeltaTime;
                }
                lastPos = nextPos;
                i++;
            }
            if (pointList.Count > i)
            {
                pointList.RemoveRange(i, pointList.Count - i);
            }
            lastRotation = CurrentHand.rotation;
            lastPostion = CurrentHand.position;
            if (pointList.Count > 1)
            {
                HitPoint = pointList[pointList.Count - 1];
                PointEffect.SetActive(true);
                PointEffect.transform.position = HitPoint;
            }
            else
            {
                HitPoint = -Vector3.one;
                PointEffect.SetActive(false);
            }
        }
    }

    public void Enable()
    {
        SteamVR_InitManager.Instance.OnLeftDeviceActive += OnHandActive;
        SteamVR_InitManager.Instance.OnRightDeviceActive += OnHandActive;
        OnChangeTransform += OnChangeTransformCallBack;
    }
    public void OnHandActive(SteamVR_TrackedObject obj)
    {
        DeviceInput device = obj.GetComponent<DeviceInput>();
        device.OnPressDownPadV3 += OnPressDownPad;
        device.OnPressUpPad += OnPressUpPadAction;
    }

    public void OnHandDis(SteamVR_TrackedObject obj)
    {
        if (obj && obj.gameObject.activeSelf)
        {
            DeviceInput device = obj.GetComponent<DeviceInput>();
            device.OnPressDownPadV3 -= OnPressDownPad;
            device.OnPressUpPad -= OnPressUpPadAction;
        }
    }

    public void Disable()
    {
        SteamVR_InitManager.Instance.OnLeftDeviceActive -= OnHandActive;
        SteamVR_InitManager.Instance.OnRightDeviceActive -= OnHandActive;
        OnHandDis(SteamVR_InitManager.Instance.LeftObject);
        OnHandDis(SteamVR_InitManager.Instance.LeftObject);
        OnChangeTransform -= OnChangeTransformCallBack;
    }

    public void SetData()
    {
        if (PointEffect)
            PointEffect.SetActive(false);
    }

    /// <summary>
    /// 抬起触摸板时,计算落脚点
    /// </summary>
    private void OnPressUpPadAction()
    {
        if (CurrentHand == null) return;
        canJump = true;
        ray.origin = CurrentHand.position;
        Vector3 dir = HitPoint - CurrentHand.position;
        ray.direction = dir;
        if (Physics.CheckSphere(HitPoint, CheckRange, ~(1 << 8)))
        {
            canJump = false;
        }
        if (canJump)
        {
            JumpPoint(HitPoint);
        }
        CurrentHand = null;
    }
    /// <summary>
    /// 跳到指定的点
    /// </summary>
    /// <param name="point"></param>
    public void JumpPoint(Vector3 point)
    {
        point.y = transform.position.y;
        transform.position = point;
    }

    private void OnPressDownPad(Transform parent)
    {

        CurrentHand = parent;

    }

    /// <summary>
    /// 使用GL来绘制曲线
    /// 将点绘制出来
    /// </summary>
    void OnRenderObject()
    {
        material.SetPass(0);
        if (pointList == null) return;
        GL.Begin(GL.LINES);
        for (int i = 0; i < pointList.Count; i++)
        {
            GL.Vertex(pointList[i]);
        }
        GL.End();
    }

    /// <summary>
    /// 一个额外的附加方法,即用一个曲线来绘制抛物线,性能较低,因为点数比较多
    /// 感兴趣的可以把此方法添加到Update中更新
    /// </summary>

    public void ShowLineByRender()
    {

        LineRenderer line = GetComponent<LineRenderer>();
        if (line)
        {
            line.SetVertexCount(pointList.Count);
            for (int i = 0; i < pointList.Count; i++)
            {
                line.SetPosition(i, pointList[i]);
            }
        }
    }
}

  

时间: 2024-10-22 13:01:32

Steam VR的使用(二)的相关文章

【Android开发VR实战】二.播放360&amp;#176;全景视频

转载请注明出处:http://blog.csdn.net/linglongxin24/article/details/53924006 本文出自[DylanAndroid的博客] [Android开发VR实战]二.播放360°全景视频 VR即Virtual Reality虚拟现实.虚拟现实技术是一种能够创建和体验虚拟世界的计算机仿真系统它利用计算机生成一种模拟环境是一种多源信息融合的交互式的三维动态视景和实体行为的系统仿真使用户沉浸到该环境中. 那么,怎样在Android中去开发VR功能的APP

【Android开发VR实战】二.播放360&#176;全景视频

转载请注明出处:http://blog.csdn.net/linglongxin24/article/details/53924006 本文出自[DylanAndroid的博客] [Android开发VR实战]二.播放360°全景视频 VR即Virtual Reality虚拟现实.虚拟现实技术是一种可以创建和体验虚拟世界的计算机仿真系统它利用计算机生成一种模拟环境是一种多源信息融合的交互式的三维动态视景和实体行为的系统仿真使用户沉浸到该环境中. 那么,如何在Android中去开发VR功能的APP

Unity 5.3 官方VR教程(二) 创建第一个VR项目

为了准备好学习使用Unity开发VR应用,我们首先要检查下自己的电脑硬件和软件配置是否满足要求.简单来说,显卡要NVIDIA GTX970或AMD290以上,CPU要Intel i5-459以上,内存8GB以上,要有两个USB3.0接口,一个USB2.0接口,一个HDMI 1.3接口. 注意在打开Unity前要把DK2连接好并开启. 在继续之前,打开Oculus Configuration Utility应用,并检查Demo Scene可以正常运行.注意在运行Demo Scene之前看可能需要在

VR原理讲解及开发入门

本文是作者obuil根据多年心得专门为想要入门的VR开发者所写,由52VR网站提供支持. 1. VR沉浸感和交互作用产生的原理: 在之前,我们观看一个虚拟的创造内容是通过平面显示器的,52VR上次发布过一篇文章<一张图让你认识VR>,在其中,你会看到很多10年前的虚拟现实装备,他们基本是平面显示器,或者将产生的画面投影到一个弧形甚至是球形屏幕上:或者在这些屏幕上叠加左右眼分别的图像,从而产生更加立体的效果. 而这类装置往往很大型,也很昂贵. 而近几年发展起来的VR头戴显示器,则达到了更好的使用

VR设备介绍

对于很多没有体验过现实增强,甚至虚拟现实眼镜产品的童鞋而言,这东西究竟应该怎么理解,硬件配置如何,用了什么操作系统,相比市面上的其他眼镜产品有何不同,这是个值得一说的问题.今天,我们先带大家一起领略下,各品牌研发的VR虚拟与现实设备吧. 首先我们科普下什么是虚拟设备 简单来说虚拟设备包括虚拟眼镜,虚拟头盔等.它们简称为VR(Virtual Reality虚拟现实).通过人机交互,语言,动作,口令进入到虚拟现实世界.可以在虚拟世界中实现:再生旅游,医疗学习,经营房产,游戏,生物,科学等一切人文有关

《图说VR》——HTC Vive控制器按键事件解耦使用

本文章由cartzhang编写,转载请注明出处. 全部权利保留. 文章链接:http://blog.csdn.net/cartzhang/article/details/53915229 作者:cartzhang Unity的 Steam VR插件本身也带有事件处理.可是我还想把事件给解耦出来,这样方便在各个项目中,不用关心硬件的各种处理而只用关心使用的,且能够随意的通过接受事件来触发对应的操作. 项目的參考图片可下载地址:https://github.com/cartzhang/ImgSayV

VR&HTC課程

課程目標: 第1天課程學完之後,您會充分理解VR(含AR.MR)技術的本質.原理和產業發展趨勢.包括掌握VR技術風潮下的完整產業生態.投資策略和文創出版的IP授權模式等新機會. 第2天課程學完之後,您會深刻領會VR身歷其境(定位其中)的沉浸感(帶入感)是來自於幕後的3D素材(Material),您先學會360全景拍攝的技巧和後製作流程,並實際演練.此外,您還會熟悉其他的VR素材製作途徑和工具. 第3天課程學完之後,您會完整認識當今全球最先進的HTC Vive產品的結構.安裝和使用.然後深入學習使

Daydream & HTC VR課程

--給您扎實的VR(含AR)內容開發技 --發揮您的素材創作天賦,大幅提升內容品質 --應用於HTC Vive和 Android Daydream VR平台 課程簡介: 虛擬實境( VR)是當今產業大趨勢,無限商機等待我們去開發.近年VR相關技術與發展日漸受到各界重視,並且被逐漸應用在醫療.農業.觀光.娛樂與教育等領域,是未來行動載具不可或缺的發展項目.擴增實境(AR)的也替人類帶來多采多姿的樂趣,君不見Pokemon Go讓眾人為之瘋狂的情境. 台灣HTC Vive也成為當今世界上最卓越的VR

VR廣告設計與商業

<VR廣告設計與商業>培訓營 課程 By 高煥堂/台灣VR產業聯盟 主席  2016.11月 在Buy+購物的浪潮下,<VR廣告製作>也水漲船高,歡迎您一起來學習VR廣告製作技術. 進入無框世界 我們知道,傳統多媒體大多給觀眾圈定了一個"框",例如TV建構了一個有框世界,讓人們從框外觀看框裡的節目.而VR技術則打破了傳統螢幕的"框",引導人們進入螢幕的框內,給予一個完整的世界.在廣告方面,從"有框"到"無框&qu