#unity##HTC VIVE#实现简单的无人机操作模拟

为了在我们的VR项目中增添有用功能,就添加了这个模块。

无人机的操控是模拟现实无人机的双摇杆手柄操作方式,对htc vive两个手柄的touchpad的功能进行继承重写,实现操控:

#unity##HTC VIVE#实现简单的无人机操作模拟_第1张图片

如图,左touchpad分成四个区域,根据touchpad的触摸检测触碰位置的区域,同时根据按压touchpad来执行操控。分别对应的:水平轴左右转向,以及竖直轴上升下降。

而右touchpad根据触摸位置相对圆中心的向量方向,来控制飞行器水平面上的位移方向,为了效果更真实,还设置了加速度。

下面来看一下代码:

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

public class Flying : MonoBehaviour {

	public bool IsFlying = false;

	public GameObject leftController;
	public GameObject rightController;

	public float maxVelocityXZ=2.0f;
	public float velocityY=1.0f;
	public float accelerationXZ=10.0f;

	private float velocityXZ=0;

	SteamVR_TrackedObject trackedLeft;
	SteamVR_TrackedObject trackedRight;
	Vector3 right;

	void Awake(){
		trackedLeft = leftController.GetComponent ();
		trackedRight = rightController.GetComponent ();
	}
	// Use this for initialization
	void Start () {

	}
	
	// Update is called once per frame
	void Update () {
		var deviceLeft = SteamVR_Controller.Input ((int)trackedLeft.index);
		var deviceRight = SteamVR_Controller.Input ((int)trackedRight.index);
		if (IsFlying == true) {
			
			if(deviceLeft.GetPress(SteamVR_Controller.ButtonMask.Touchpad)){
				Vector2 left = deviceLeft.GetAxis ();
				float angle = VectorAngle (new Vector2 (1, 0), left);
				if (angle > 45 && angle < 135) {//上
					transform.Translate (Vector3.down * velocityY*Time.deltaTime);
				}
				if(angle<-45&&angle>-135){//下
					transform.Translate (Vector3.up * velocityY*Time.deltaTime);
				}
				if((angle<180&&angle>135)||(angle<-135&&angle>-180)){
					transform.Rotate (Vector3.down * Time.deltaTime*150);
				}
				if ((angle < 45 && angle > 0) || (angle <0 && angle > -45)) {
					transform.Rotate (Vector3.up * Time.deltaTime*150);
				}
			}
			if(deviceRight.GetPress(SteamVR_Controller.ButtonMask.Touchpad)){
				if (velocityXZ < maxVelocityXZ) {
					velocityXZ += accelerationXZ * Time.deltaTime;
				}
				Vector2 rightTouchPad = deviceRight.GetAxis ();
				right = new Vector3 (rightTouchPad.x,0, rightTouchPad.y);
				transform.Translate (velocityXZ * Time.deltaTime * right.normalized);
			}
			if(velocityXZ>0&&!deviceRight.GetPress(SteamVR_Controller.ButtonMask.Touchpad)){
				velocityXZ -= accelerationXZ * Time.deltaTime;
				transform.Translate (velocityXZ * Time.deltaTime * right.normalized);
			}
			//transform.Rotate (Vector3.Cross (Vector3.up, right) * velocityXZ,Space.World);

	}

	}

		float VectorAngle(Vector2 from, Vector2 to)
	{  
		float angle;  
		Vector3 cross = Vector3.Cross(from, to);  
		angle = Vector2.Angle(from, to);  
		return cross.z > 0 ? -angle : angle;  
	}  
}

到这里我们对于用touchpad控制无人机的飞行就完成了。但是touchpad在普通场景里用于控制手柄发出射线进行碰撞检测来实现 传送位移。因此我们再直升机室里加了一个cube当做trigger,通过手柄扳机触发来进入飞行状态,飞行状态时,向前面的代码的bool值IsFlying传值为true,同时将手柄上的VRTK_SimplePointer组件的enable设置为false,这样就不会发出射线了。

下面是绑在这个触发器Cube上的代码:

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

public class FlyingTrigger : VRTK_InteractableObject {

	public GameObject airVehicle;
	public Transform airVehiclePos;

	[Header("ControllerDevices", order = 1)]
	public GameObject controllerLeft;
	public GameObject controllerRight;

	VRTK_SimplePointer pointerLeft;
	VRTK_SimplePointer pointerRight;
	// Use this for initialization
	public override void StartUsing(GameObject usingObject)
	{
		base.StartUsing(usingObject);
		airVehicle.GetComponent ().IsFlying = true;
		pointerLeft.enabled = false;
		pointerRight.enabled = false;
	}

	public override void StopUsing(GameObject usingObject)
	{
		base.StopUsing(usingObject);
		airVehicle.GetComponent ().IsFlying = false;
		pointerLeft.enabled = true;
		pointerRight.enabled = true;
		airVehicle.transform.position = airVehiclePos.position;

	}

	protected override void Start()
	{
		base.Start();
	}

	protected override void Awake()
	{
		base.Awake ();
		pointerLeft = controllerLeft.GetComponent ();
		pointerRight = controllerRight.GetComponent ();
	}
}

这样一来就实现了无人机模拟操纵的功能,最后将资源都搭好放置在一个房间里。

你可能感兴趣的:(训练项目)