zoukankan      html  css  js  c++  java
  • HTC Vive小场地与大场景空间的解决方案

    本文章由cartzhang编写,转载请注明出处。 所有权利保留。
    文章链接:http://blog.csdn.net/cartzhang/article/details/52780621
    作者:cartzhang

    HTC Vive小场地与大场景空间的解决方案


    对于Vive,我们可以正常使用,运动追踪功能是 HTC Vive 的一大亮点,这也让很多适配 HTC Vive 的游戏能够让用户动起来,听起来很酷,体验起来也很酷。在小范围移动1:·1的范围内活动或固定位置的游戏中,定位精确,并且延迟很低,各种优点不一而足。

    但是空间问题,让想在小空间大场景的游戏中的玩家排在了门外,HTC官方建议:HTC 建议消费者在至少 20 平米空间使用全套装备,这也意味着你的游戏房要足够大。土豪就不用往下看了!!!
    但是对于想要开疆扩土的用户,在实际中场地大小就成为了局限,用户没有恰好游戏场景大小的场地,游戏场地过大,而玩家场地太小,怎么解决呢?

    还有就是要是1:1的场地,会有一种游戏场景非常局促,感觉没有走多远就到了边际,让玩家十分不爽。
    所以这里给出了变比空间的HTC头盔的移动问题的解决方案。

    当然,若你有更好的办法,也欢迎讨论

    我们重点来说,游戏场景过大,而实际场地台较小,需要对位移进行比例加速问题。
    我们要解决问题有三个

    1. 边界放大
    2. 起点位置平移
    3. 游戏空间与场地非等比空间速度缩放

    一、边界放大

    首先,来看看官方SteamVR给出的预制体的顶视图:
    这里写图片描述
    发现没有。
    在HTC 头盔的游戏中,玩家总在蓝色框的中间位置。而对于需要从(0,0)作为起点的游戏,需要在房间内到处移动,并且根据游戏剧情,需要空间移动的游戏,这个就只可以用原有场地的1/4的场地了,更造成了场地的浪费。
    我们首先解决的就是位置需要偏移问题
    其次,看到蓝色边框的大小了没有。其实蓝色框范围很小,
    这里写图片描述
    看代码:

    public enum Size
    {
        Calibrated,
        _400x300,
        _300x225,
        _200x150
    }


    这个面积小,不满足需求,怎么办呢? 自己来增加啊,搞大场地!!
    我就自己做了一个区域标识。
    这里写图片描述
    小的蓝色框为它原本的400*300的,大的为我自己缩放的区域。
    选择Size为Calibrated这个选项,缩放即可。特地添加了一个父节点,以防止在直接节点上缩放出问题,xz均缩放为4,Y仍旧为1。
    这个标识就基本满足游戏中场地大小为9*9米的一个大场地了。

    二、起点位置平移

    好了。现在回来说,起点的平移问题。
    分两部:
    一个是视觉上,就是在游戏编辑器模式下,让玩家在蓝色区域的起点角点位置。这个容易,就是还是平移。平移谁呢,平移蓝色区域,把刚才缩放的那个预制体的父节点做了平移,项目中的平移位置为(4.2,0,4.2)即可。
    这部分就搞定了。
    第二部分,就是比较繁琐一点了。
    说这个问题之前,需要稍微说下SteamVR插件的运行时和编辑状态的相机差别。
    这里写图片描述
    这个是编辑器模式下的相机状态。
    但是在运行时候,相机的层级结构会发生较大的变化。
    这里写图片描述
    可以看到eye作为父节点,ears作为子节点,而head则被隐藏了。
    具体代码处理是在SteamVR_Camera.cs中的OnEnable中处理。

    部分代码:

    if (head != t)
    {
        Expand();
    
        t.parent = origin;
    
        while (head.childCount > 0)
            head.GetChild(0).parent = t;
    
        // Keep the head around, but parent to the camera now since it moves with the hmd
        // but existing content may still have references to this object.
        head.parent = t;
        head.localPosition = Vector3.zero;
        head.localRotation = Quaternion.identity;
        head.localScale = Vector3.one;
        head.gameObject.SetActive(false);
    
        _head = t;
    }


    还有ears的处理代码,设置ears的相机参数:

    if (ears == null)
    {
        var e = transform.GetComponentInChildren<SteamVR_Ears>();
        if (e != null)
            _ears = e.transform;
          }
    
    if (ears != null)
        ears.GetComponent<SteamVR_Ears>().vrcam = this;


    为什么讲了这么多结构呢?因为它影响到了玩家起点平移的算法和处理。
    怎么处理呢?
    其实是蛮简单。给相机的父节点在初始化时候,重置一个与相机初始化一个相反的参数。
    为什么呢?这正是为了抵消相机在场景中从(0,0)点作为起点的变化啊.

    具体代码:

    using UnityEngine;
    using System.Collections;
    
    public class PlayerPosIntitial : MonoBehaviour
    {
        private bool bUseOnce = false;
        public Transform eye;
    
        private float starttime;
        private float delaytime = 4.0f;
        // Use this for initialization
        void Start ()
        {
            starttime = Time.time;  
        }
    
        // Update is called once per frame
        void Update () 
        {
            if (!bUseOnce && (Input.GetMouseButton(0) || Input.GetKey(KeyCode.JoystickButton0) || Time.time - starttime >= delaytime))
            {
    
                bUseOnce = true;
                if (null != eye) 
                {               
                    this.transform.localPosition = new Vector3(-eye.transform.localPosition.x,0,-eye.transform.localPosition.z);
                    Debug.Log ("set player initila position");
                }
            }
        }
    }


    这个根据自己需要来处理的按键和时间自动开始。可以不这样用按键啥的。

    这里写图片描述
    这里顺便说一句:
    就是要添加手柄,只需要把手柄脚本放这节点下,然后设置左右手柄即可。
    手柄在随后中,并不会由于位移的加速对其造成影响。

    三、游戏空间与场地非等比空间速度缩放

    好了,说完了平移。
    最后,那就是场景为9*9米,而我场地只有三米或5米,怎么办呢?
    其实结果已经比较明显了。就是刚才FPSController还有个缩放的父节点。

    那有人可能会有异议?直接来控制HTCvive相机的脚本来给得出的相机位置进行修改缩放不就可以了吗?
    哎呀,这个方法确实很好啊。但是无法实现。为什么呢?

    因为相机无法在脚本层控制。
    在编辑器下运行模型下,把所有脚本代码勾选掉,相机的位置旋转均还可以正常使用。
    这基本说明,相机的控制在脚本层的机会很少。
    但是,我并不死心。下面就开始了各种尝试。
    当然是在脚本中,看代码吧。

    // 在数据更新层,让他设置为zero.
        void Update()
        {
            transform.position = Vector3.zero;
        }
        void LateUpdate()
        {
            transform.position = Vector3.zero;
        }
        //在渲染层的某个阶段处理,设置为零。
        void PreRender()
        {
            transform.position = Vector3.zero;
        }
    
        void OnPostRender()
        {
            transform.position = Vector3.zero;
        }


    要说的是:以上代码对与HTC头盔的相机设置下工均没有任何的作用。看清楚是对实际效果有任何作用。
    要说有作用,在编辑器模式下,编辑器里面现实为零,但是相机数据仍可以变化,这是由于编辑器的数据显示要先于真实的相机坐标,只是个假象,都是幻觉。

    最终的解决方案,给FPSController添加一个父节点,这样就基本搞定了。

    UpdatCamera的代码:
    using UnityEngine;
    using System.Collections;
    
    public class UpdateCamra : MonoBehaviour 
    {
        public Transform ViveCamera;
        public float ScaleLength = 0.5f;
        // Use this for initialization
        void Start () 
        {
            #if UNITY_EDITOR
            #else
            ScaleLength = PlayerControl.m_Cfg.MaxDeltaVel;
            #endif
        }
    
        // Update is called once per frame
        void Update () 
        {
            if (null != ViveCamera) 
            {
                transform.position = new Vector3 (ViveCamera.position.x * ScaleLength, ViveCamera.position.y, ViveCamera.position.z * ScaleLength);
            }
    
        }
    }


    为了便于根据场地的大小和游戏场景的大小调节匹配,缩放参数做了一个配置文件。这里就不过多的详述了。

    至此,我们完成了,边界放大,起点位置平移,游戏空间与场地非等比空间速度缩放。
    顺便说下,我们游戏场景为9*9而实际测试场地为2.5米左右的时候,缩放系数为0.5,这时候由于场地过小,速度过快有少于不适。而在5*5左右时候,调节参数,整体感觉还是非常舒服的,也没有由于空间的大小而在游戏中感到局促。

    参考:

    SteamVR Unity官方的插件quikstart.pdf。

    —————————-THE———END—————————–
    若有问题,请随时联系!!!
    非常感谢!!!

    昨天天气好,晚上有人看到了两个月亮。
    这里写图片描述

  • 相关阅读:
    双向认证SSL原理
    p12证书转keystore签名
    Loadrunner对https协议(单双向SSL)的web端性能测试
    关于Unity中新版动画系统的使用
    关于Unity中旧版动画系统的使用
    关于Unity中Mesh网格的详解
    关于Unity中Time.deltaTime的使用
    关于Unity中的光照(七)
    关于Unity中的光照(六)
    关于Unity中的光照(五)
  • 原文地址:https://www.cnblogs.com/qitian1/p/6461896.html
Copyright © 2011-2022 走看看