在物理实验室模块中,设计加一个模拟失重环境的房间,使用户能够体验到虚拟的失重的状态。
在htc vive的运行中,摄像机元素绑定在camerarig的head子物体中的eye上,使用者自身也就是camerarig,在运行时,会被添加一个rigidbody刚体组件以及一个胶囊体的碰撞体。为了更好的模拟人在环境中的交互。
为了更好的体验,我们需要设置camerarig所在的rigidbody的属性。虽然在失重的环境下,一个很小的力,也会造成很大的位移,但第一人称视角的情况下,位移的幅度太大,会产生眩晕感;这是需要调整所在的刚体的质量mass,或者增大位移阻力和旋转阻力,虽然在失重情况下,并不现实,但模拟体验效果会比较好。
我是采用增大drag和angular drag。
using System.Collections; using System.Collections.Generic; using UnityEngine; public class changeRigidbody : MonoBehaviour { private Rigidbody rrd; // Use this for initialization void Start () { rrd = GetComponent<Rigidbody> (); rrd.drag = 100.0f; rrd.angularDrag = 100.0f; } // Update is called once per frame void Update () { } }
在其他的物体上添加摩擦力,质量等属性,不施加重力;设置物理属性。并添加VRTK_Interactable和
VRTK_InteractableObject为了使手柄可以抓取。(详见《基于VRTK的Unity HTC Vive模型拼接(组件的抓取交互)
》)
除此之外,我加了一个“黑洞”的功能,扣动左手扳机的时候;物体都被吸引到左手扳机的位置。
using System.Collections; using System.Collections.Generic; using UnityEngine; using VRTK; using VRTK.Highlighters; public class suction : MonoBehaviour { public float distance; public Vector3 sucPos; public bool isAddForce = false; private GameObject LeftController; public SteamVR_TrackedObject trackedObjec; // Use this for initialization void Start () { sucPos = this.transform.position; LeftController = VRTK_DeviceFinder.GetControllerLeftHand (); } // Update is called once per frame void Update () { sucPos = LeftController.transform.position; var device = SteamVR_Controller.Input((int)trackedObjec.index); if(device.GetTouchDown(SteamVR_Controller.ButtonMask.Trigger) && !isAddForce){ isAddForce = true; } if(device.GetTouchUp(SteamVR_Controller.ButtonMask.Trigger) && isAddForce){ isAddForce = false; } } }
左手手柄绑定的脚本,首先通过VRTK_DeviceFinder获取左手手柄的位置,记录位置并设置为public属性的变量,方便其他物体的调用。
检测到当手柄按下时,设置一个布尔值,isAddForce至为true。
using System.Collections; using System.Collections.Generic; using UnityEngine; public class forced : MonoBehaviour { public float gravity = 1.0f; public float distance; public suction suct; private Rigidbody rg; public float julicanshu; // Use this for initialization void Start () { rg = GetComponent<Rigidbody> (); } // Update is called once per frame void Update () { if(suct.isAddForce){ distance = System.Math.Abs((suct.sucPos - transform.position).magnitude); julicanshu = (System.Math.Abs (100.0f - distance))/100.0f; rg.AddForce (((suct.sucPos - transform.position).normalized)*(2.0f-gravity)*julicanshu); } } }
其他物体上的force脚本,获取到脚本的rigidbody,为了下面执行addforce方法,施力。
当前面监听到手柄按下时,执行吸引的方法。
首先计算与手柄的距离,计算绝对值,通过距离计算距离参数,方便下面施加力的时候调用。距离参数与距离成反比。施力的时候,通过两者间的位置计算出方向,并归一化。除了方向外,施加的力还受到质量,距离的影响。距离越近受力越大,质量越小受力越大。