diff Orchestland/Assets/OVR/Scripts/Util/OVRPlayerController.cs @ 1:f7675884f2a1

Add Orchestland project
author Daiki OYAKAWA <e135764@ie.u-ryukyu.ac.jp>
date Fri, 17 Jul 2015 23:09:20 +0900
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Orchestland/Assets/OVR/Scripts/Util/OVRPlayerController.cs	Fri Jul 17 23:09:20 2015 +0900
@@ -0,0 +1,405 @@
+/************************************************************************************
+
+Copyright   :   Copyright 2014 Oculus VR, LLC. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
+which is provided at the time of installation or download, or which
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.2
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+using UnityEngine;
+using System.Collections.Generic;
+
+/// <summary>
+/// Controls the player's movement in virtual reality.
+/// </summary>
+[RequireComponent(typeof(CharacterController))]
+public class OVRPlayerController : MonoBehaviour
+{
+	/// <summary>
+	/// The rate acceleration during movement.
+	/// </summary>
+	public float Acceleration = 0.1f;
+
+	/// <summary>
+	/// The rate of damping on movement.
+	/// </summary>
+	public float Damping = 0.3f;
+
+	/// <summary>
+	/// The rate of additional damping when moving sideways or backwards.
+	/// </summary>
+	public float BackAndSideDampen = 0.5f;
+
+	/// <summary>
+	/// The force applied to the character when jumping.
+	/// </summary>
+	public float JumpForce = 0.3f;
+
+	/// <summary>
+	/// The rate of rotation when using a gamepad.
+	/// </summary>
+	public float RotationAmount = 1.5f;
+
+	/// <summary>
+	/// The rate of rotation when using the keyboard.
+	/// </summary>
+	public float RotationRatchet = 45.0f;
+
+	/// <summary>
+	/// The player's current rotation about the Y axis.
+	/// </summary>
+	private float YRotation = 0.0f;
+
+	/// <summary>
+	/// If true, tracking data from a child OVRCameraRig will update the direction of movement.
+	/// </summary>
+	public bool HmdRotatesY = true;
+
+	/// <summary>
+	/// Modifies the strength of gravity.
+	/// </summary>
+	public float GravityModifier = 0.379f;
+
+	private float MoveScale = 1.0f;
+	private Vector3 MoveThrottle = Vector3.zero;
+	private float FallSpeed = 0.0f;	
+	private OVRPose? InitialPose;
+	
+	/// <summary>
+	/// If true, each OVRPlayerController will use the player's physical height.
+	/// </summary>
+	public bool useProfileHeight = true;
+
+	protected CharacterController Controller = null;
+	protected OVRCameraRig CameraController = null;
+
+	private float MoveScaleMultiplier = 1.0f;
+	private float RotationScaleMultiplier = 1.0f;
+	private bool  SkipMouseRotation = false;
+	private bool  HaltUpdateMovement = false;
+	private bool prevHatLeft = false;
+	private bool prevHatRight = false;
+	private float SimulationRate = 60f;
+
+	void Awake()
+	{
+		Controller = gameObject.GetComponent<CharacterController>();
+
+		if(Controller == null)
+			Debug.LogWarning("OVRPlayerController: No CharacterController attached.");
+
+		// We use OVRCameraRig to set rotations to cameras,
+		// and to be influenced by rotation
+		OVRCameraRig[] CameraControllers;
+		CameraControllers = gameObject.GetComponentsInChildren<OVRCameraRig>();
+
+		if(CameraControllers.Length == 0)
+			Debug.LogWarning("OVRPlayerController: No OVRCameraRig attached.");
+		else if (CameraControllers.Length > 1)
+			Debug.LogWarning("OVRPlayerController: More then 1 OVRCameraRig attached.");
+		else
+			CameraController = CameraControllers[0];
+
+		YRotation = transform.rotation.eulerAngles.y;
+
+#if UNITY_ANDROID && !UNITY_EDITOR
+		OVRManager.display.RecenteredPose += ResetOrientation;
+#endif
+	}
+
+	protected virtual void Update()
+	{
+		if (useProfileHeight)
+		{
+			if (InitialPose == null)
+			{
+				InitialPose = new OVRPose() {
+					position = CameraController.transform.localPosition,
+					orientation = CameraController.transform.localRotation
+				};
+			}
+
+			var p = CameraController.transform.localPosition;
+			p.y = OVRManager.profile.eyeHeight - 0.5f * Controller.height;
+			p.z = OVRManager.profile.eyeDepth;
+			CameraController.transform.localPosition = p;
+		}
+		else if (InitialPose != null)
+		{
+			CameraController.transform.localPosition = InitialPose.Value.position;
+			CameraController.transform.localRotation = InitialPose.Value.orientation;
+			InitialPose = null;
+		}
+
+		UpdateMovement();
+
+		Vector3 moveDirection = Vector3.zero;
+
+		float motorDamp = (1.0f + (Damping * SimulationRate * Time.deltaTime));
+
+		MoveThrottle.x /= motorDamp;
+		MoveThrottle.y = (MoveThrottle.y > 0.0f) ? (MoveThrottle.y / motorDamp) : MoveThrottle.y;
+		MoveThrottle.z /= motorDamp;
+
+		moveDirection += MoveThrottle * SimulationRate * Time.deltaTime;
+
+		// Gravity
+		if (Controller.isGrounded && FallSpeed <= 0)
+			FallSpeed = ((Physics.gravity.y * (GravityModifier * 0.002f)));
+		else
+			FallSpeed += ((Physics.gravity.y * (GravityModifier * 0.002f)) * SimulationRate * Time.deltaTime);
+
+		moveDirection.y += FallSpeed * SimulationRate * Time.deltaTime;
+
+		// Offset correction for uneven ground
+		float bumpUpOffset = 0.0f;
+
+		if (Controller.isGrounded && MoveThrottle.y <= 0.001f)
+		{
+			bumpUpOffset = Mathf.Max(Controller.stepOffset, new Vector3(moveDirection.x, 0, moveDirection.z).magnitude);
+			moveDirection -= bumpUpOffset * Vector3.up;
+		}
+
+		Vector3 predictedXZ = Vector3.Scale((Controller.transform.localPosition + moveDirection), new Vector3(1, 0, 1));
+
+		// Move contoller
+		Controller.Move(moveDirection);
+
+		Vector3 actualXZ = Vector3.Scale(Controller.transform.localPosition, new Vector3(1, 0, 1));
+
+		if (predictedXZ != actualXZ)
+			MoveThrottle += (actualXZ - predictedXZ) / (SimulationRate * Time.deltaTime);
+	}
+
+	public virtual void UpdateMovement()
+	{
+		if (HaltUpdateMovement)
+			return;
+
+		bool moveForward = Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow);
+		bool moveLeft = Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow);
+		bool moveRight = Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow);
+		bool moveBack = Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.DownArrow);
+
+		bool dpad_move = false;
+
+		if (OVRGamepadController.GPC_GetButton(OVRGamepadController.Button.Up))
+		{
+			moveForward = true;
+			dpad_move   = true;
+
+		}
+		if (OVRGamepadController.GPC_GetButton(OVRGamepadController.Button.Down))
+		{
+			moveBack  = true;
+			dpad_move = true;
+		}
+
+		MoveScale = 1.0f;
+
+		if ( (moveForward && moveLeft) || (moveForward && moveRight) ||
+			 (moveBack && moveLeft)    || (moveBack && moveRight) )
+			MoveScale = 0.70710678f;
+
+		// No positional movement if we are in the air
+		if (!Controller.isGrounded)
+			MoveScale = 0.0f;
+
+		MoveScale *= SimulationRate * Time.deltaTime;
+
+		// Compute this for key movement
+		float moveInfluence = Acceleration * 0.1f * MoveScale * MoveScaleMultiplier;
+
+		// Run!
+		if (dpad_move || Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))
+			moveInfluence *= 2.0f;
+
+		Quaternion ort = (HmdRotatesY) ? CameraController.centerEyeAnchor.rotation : transform.rotation;
+		Vector3 ortEuler = ort.eulerAngles;
+		ortEuler.z = ortEuler.x = 0f;
+		ort = Quaternion.Euler(ortEuler);
+
+		if (moveForward)
+			MoveThrottle += ort * (transform.lossyScale.z * moveInfluence * Vector3.forward);
+		if (moveBack)
+			MoveThrottle += ort * (transform.lossyScale.z * moveInfluence * BackAndSideDampen * Vector3.back);
+		if (moveLeft)
+			MoveThrottle += ort * (transform.lossyScale.x * moveInfluence * BackAndSideDampen * Vector3.left);
+		if (moveRight)
+			MoveThrottle += ort * (transform.lossyScale.x * moveInfluence * BackAndSideDampen * Vector3.right);
+
+		bool curHatLeft = OVRGamepadController.GPC_GetButton(OVRGamepadController.Button.LeftShoulder);
+
+		Vector3 euler = transform.rotation.eulerAngles;
+
+		if (curHatLeft && !prevHatLeft)
+			euler.y -= RotationRatchet;
+
+		prevHatLeft = curHatLeft;
+
+		bool curHatRight = OVRGamepadController.GPC_GetButton(OVRGamepadController.Button.RightShoulder);
+
+		if(curHatRight && !prevHatRight)
+			euler.y += RotationRatchet;
+
+		prevHatRight = curHatRight;
+
+		//Use keys to ratchet rotation
+		if (Input.GetKeyDown(KeyCode.Q))
+			euler.y -= RotationRatchet;
+
+		if (Input.GetKeyDown(KeyCode.E))
+			euler.y += RotationRatchet;
+
+		float rotateInfluence = SimulationRate * Time.deltaTime * RotationAmount * RotationScaleMultiplier;
+
+		if (!SkipMouseRotation)
+			euler.y += Input.GetAxis("Mouse X") * rotateInfluence * 3.25f;
+
+		moveInfluence = SimulationRate * Time.deltaTime * Acceleration * 0.1f * MoveScale * MoveScaleMultiplier;
+
+#if !UNITY_ANDROID // LeftTrigger not avail on Android game pad
+		moveInfluence *= 1.0f + OVRGamepadController.GPC_GetAxis(OVRGamepadController.Axis.LeftTrigger);
+#endif
+
+		float leftAxisX = OVRGamepadController.GPC_GetAxis(OVRGamepadController.Axis.LeftXAxis);
+		float leftAxisY = OVRGamepadController.GPC_GetAxis(OVRGamepadController.Axis.LeftYAxis);
+
+		if(leftAxisY > 0.0f)
+			MoveThrottle += ort * (leftAxisY * moveInfluence * Vector3.forward);
+
+		if(leftAxisY < 0.0f)
+			MoveThrottle += ort * (Mathf.Abs(leftAxisY) * moveInfluence * BackAndSideDampen * Vector3.back);
+
+		if(leftAxisX < 0.0f)
+			MoveThrottle += ort * (Mathf.Abs(leftAxisX) * moveInfluence * BackAndSideDampen * Vector3.left);
+
+		if(leftAxisX > 0.0f)
+			MoveThrottle += ort * (leftAxisX * moveInfluence * BackAndSideDampen * Vector3.right);
+
+		float rightAxisX = OVRGamepadController.GPC_GetAxis(OVRGamepadController.Axis.RightXAxis);
+
+		euler.y += rightAxisX * rotateInfluence;
+
+		transform.rotation = Quaternion.Euler(euler);
+	}
+
+	/// <summary>
+	/// Jump! Must be enabled manually.
+	/// </summary>
+	public bool Jump()
+	{
+		if (!Controller.isGrounded)
+			return false;
+
+		MoveThrottle += new Vector3(0, JumpForce, 0);
+
+		return true;
+	}
+
+	/// <summary>
+	/// Stop this instance.
+	/// </summary>
+	public void Stop()
+	{
+		Controller.Move(Vector3.zero);
+		MoveThrottle = Vector3.zero;
+		FallSpeed = 0.0f;
+	}
+
+	/// <summary>
+	/// Gets the move scale multiplier.
+	/// </summary>
+	/// <param name="moveScaleMultiplier">Move scale multiplier.</param>
+	public void GetMoveScaleMultiplier(ref float moveScaleMultiplier)
+	{
+		moveScaleMultiplier = MoveScaleMultiplier;
+	}
+
+	/// <summary>
+	/// Sets the move scale multiplier.
+	/// </summary>
+	/// <param name="moveScaleMultiplier">Move scale multiplier.</param>
+	public void SetMoveScaleMultiplier(float moveScaleMultiplier)
+	{
+		MoveScaleMultiplier = moveScaleMultiplier;
+	}
+
+	/// <summary>
+	/// Gets the rotation scale multiplier.
+	/// </summary>
+	/// <param name="rotationScaleMultiplier">Rotation scale multiplier.</param>
+	public void GetRotationScaleMultiplier(ref float rotationScaleMultiplier)
+	{
+		rotationScaleMultiplier = RotationScaleMultiplier;
+	}
+
+	/// <summary>
+	/// Sets the rotation scale multiplier.
+	/// </summary>
+	/// <param name="rotationScaleMultiplier">Rotation scale multiplier.</param>
+	public void SetRotationScaleMultiplier(float rotationScaleMultiplier)
+	{
+		RotationScaleMultiplier = rotationScaleMultiplier;
+	}
+
+	/// <summary>
+	/// Gets the allow mouse rotation.
+	/// </summary>
+	/// <param name="skipMouseRotation">Allow mouse rotation.</param>
+	public void GetSkipMouseRotation(ref bool skipMouseRotation)
+	{
+		skipMouseRotation = SkipMouseRotation;
+	}
+
+	/// <summary>
+	/// Sets the allow mouse rotation.
+	/// </summary>
+	/// <param name="skipMouseRotation">If set to <c>true</c> allow mouse rotation.</param>
+	public void SetSkipMouseRotation(bool skipMouseRotation)
+	{
+		SkipMouseRotation = skipMouseRotation;
+	}
+
+	/// <summary>
+	/// Gets the halt update movement.
+	/// </summary>
+	/// <param name="haltUpdateMovement">Halt update movement.</param>
+	public void GetHaltUpdateMovement(ref bool haltUpdateMovement)
+	{
+		haltUpdateMovement = HaltUpdateMovement;
+	}
+
+	/// <summary>
+	/// Sets the halt update movement.
+	/// </summary>
+	/// <param name="haltUpdateMovement">If set to <c>true</c> halt update movement.</param>
+	public void SetHaltUpdateMovement(bool haltUpdateMovement)
+	{
+		HaltUpdateMovement = haltUpdateMovement;
+	}
+
+	/// <summary>
+	/// Resets the player look rotation when the device orientation is reset.
+	/// </summary>
+	public void ResetOrientation()
+	{
+		Vector3 euler = transform.rotation.eulerAngles;
+		euler.y = YRotation;
+		transform.rotation = Quaternion.Euler(euler);
+	}
+}
+