CameraFlyControllerEditor

using UnityEngine;
using System.Collections.Generic;

#if UNITY_EDITOR
using UnityEditor;
#endif

namespace HighlightingSystem.Demo
{
	#if UNITY_EDITOR
	[CustomEditor(typeof(CameraFlyController))]
	public class CameraFlyControllerEditor : Editor
	{
		static private readonly GUIContent labelSetupAxes = new GUIContent("Setup Input Axes");

		public override void OnInspectorGUI()
		{
			base.OnInspectorGUI();

			if (GUILayout.Button(labelSetupAxes, GUILayout.Height(30f)))
			{
				SetupControllerAxes();
			}
		}

		private struct Axis
		{
			public string m_Name;
			public string descriptiveName;
			public string descriptiveNegativeName;
			public string negativeButton;
			public string positiveButton;
			public string altNegativeButton;
			public string altPositiveButton;
			public float gravity;
			public float dead;
			public float sensitivity;
			public bool snap;
			public bool invert;
			public int type;  // Enum
			public int axis;  // Enum
			public int joyNum;    // Enum

			// 
			public void Serialize(SerializedProperty p)
			{
				p.FindPropertyRelative("m_Name").stringValue = m_Name;
				p.FindPropertyRelative("descriptiveName").stringValue = descriptiveName;
				p.FindPropertyRelative("descriptiveNegativeName").stringValue = descriptiveNegativeName;
				p.FindPropertyRelative("negativeButton").stringValue = negativeButton;
				p.FindPropertyRelative("positiveButton").stringValue = positiveButton;
				p.FindPropertyRelative("altNegativeButton").stringValue = altNegativeButton;
				p.FindPropertyRelative("altPositiveButton").stringValue = altPositiveButton;
				p.FindPropertyRelative("gravity").floatValue = gravity;
				p.FindPropertyRelative("dead").floatValue = dead;
				p.FindPropertyRelative("sensitivity").floatValue = sensitivity;
				p.FindPropertyRelative("snap").boolValue = snap;
				p.FindPropertyRelative("invert").boolValue = invert;
				p.FindPropertyRelative("type").intValue = type;
				p.FindPropertyRelative("axis").intValue = axis;
				p.FindPropertyRelative("joyNum").intValue = joyNum;
			}
		}

		static public void SetupControllerAxes()
		{
			List<Axis> axes = new List<Axis>();
			Axis axis = new Axis();

			// JoystickAxis commons
			axis.dead = 0f;
			axis.sensitivity = 1f;
			axis.snap = false;
			axis.invert = false;
			axis.type = 2;
			axis.joyNum = 0;

			// JoystickAxis1
			axis.m_Name = CameraFlyController.axisJoystickAxis1;
			axis.axis = 0;
			axes.Add(axis);

			// JoystickAxis2
			axis.m_Name = CameraFlyController.axisJoystickAxis2;
			axis.axis = 1;
			axes.Add(axis);

			// JoystickAxis4
			axis.m_Name = CameraFlyController.axisJoystickAxis4;
			axis.axis = 3;
			axes.Add(axis);

			// JoystickAxis5
			axis.m_Name = CameraFlyController.axisJoystickAxis5;
			axis.axis = 4;
			axes.Add(axis);

			// Mouse commons
			axis.dead = 0f;
			axis.sensitivity = 0.1f;
			axis.snap = false;
			axis.invert = false;
			axis.type = 1;
			axis.joyNum = 0;

			// Mouse X
			axis.m_Name = CameraFlyController.axisMouseX;
			axis.axis = 0;
			axes.Add(axis);

			// Mouse Y
			axis.m_Name = CameraFlyController.axisMouseY;
			axis.axis = 1;
			axes.Add(axis);

			SetupAxes(axes);
		}

		static private void SetupAxes(List<Axis> samples)
		{
			string path = "ProjectSettings/InputManager.asset";
			Object inputManagerFile = AssetDatabase.LoadAllAssetsAtPath(path)[0];
			if (inputManagerFile == null)
			{
				Debug.LogErrorFormat("Failed to load asset at path '{0}'", path);
				return;
			}

			SerializedObject inputManagerAsset = new SerializedObject(inputManagerFile);

			HashSet<int> toIgnore = new HashSet<int>();
			SerializedProperty axesProperty = inputManagerAsset.FindProperty("m_Axes");
			for (int i = 0, l = axesProperty.arraySize; i < l; i++)
			{
				SerializedProperty axisProperty = axesProperty.GetArrayElementAtIndex(i);
				string name = axisProperty.FindPropertyRelative("m_Name").stringValue;
				int sampleIndex = samples.FindIndex(delegate(Axis obj) { return obj.m_Name == name; });
				if (sampleIndex != -1)
				{
					// Replace axis
					Axis sample = samples[sampleIndex];
					sample.Serialize(axisProperty);
					toIgnore.Add(sampleIndex);
				}
			}

			for (int i = 0, l = samples.Count; i < l; i++)
			{
				if (toIgnore.Contains(i)) { continue; }

				// Add axis
				Axis sample = samples[i];
				int arrayIndex = axesProperty.arraySize;
				axesProperty.InsertArrayElementAtIndex(arrayIndex);
				SerializedProperty p = axesProperty.GetArrayElementAtIndex(arrayIndex);
				sample.Serialize(p);
			}

			inputManagerAsset.ApplyModifiedProperties();
		}
	}
	#endif

	public class CameraFlyController : MonoBehaviour
	{
		#region Constants
		public const string axisJoystickAxis1 = "JoystickAxis1";
		public const string axisJoystickAxis2 = "JoystickAxis2";
		public const string axisJoystickAxis4 = "JoystickAxis4";
		public const string axisJoystickAxis5 = "JoystickAxis5";
		public const string axisMouseX = "Mouse X";
		public const string axisMouseY = "Mouse Y";

		private float keyboardMoveSpeed = 4f;

		private float joystickAxisThresholdMin = 0.2f;
		private float joystickAxisThresholdMax = 1f;

		private float joystickMoveSpeedXMin = 0f;
		private float joystickMoveSpeedXMax = 5f;
		private float joystickMoveSpeedY = 4f;
		private float joystickMoveSpeedZMin = 0f;
		private float joystickMoveSpeedZMax = 5f;

		private float joystickRotationSpeedMin = 0f;
		private float joystickRotationSpeedMax = 126f;

		static private readonly KeyCode[] keysForward = new KeyCode[] { KeyCode.W, KeyCode.UpArrow };
		static private readonly KeyCode[] keysBackward = new KeyCode[] { KeyCode.S, KeyCode.DownArrow };

		static private readonly KeyCode[] keysLeft = new KeyCode[] { KeyCode.A, KeyCode.LeftArrow };
		static private readonly KeyCode[] keysRight = new KeyCode[] { KeyCode.D, KeyCode.RightArrow };

		static private readonly KeyCode[] keysUp = new KeyCode[] { KeyCode.E, KeyCode.Space };
		static private readonly KeyCode[] keysDown = new KeyCode[] { KeyCode.Q, KeyCode.C };

		static private readonly KeyCode[] keysRun = new KeyCode[] { KeyCode.LeftShift, KeyCode.RightShift };

		static private readonly KeyCode[] joystickUp = new KeyCode[] { KeyCode.Joystick1Button5, KeyCode.Joystick2Button5, KeyCode.Joystick3Button5, KeyCode.Joystick4Button5 };
		static private readonly KeyCode[] joystickDown = new KeyCode[] { KeyCode.Joystick1Button4, KeyCode.Joystick2Button4, KeyCode.Joystick3Button4, KeyCode.Joystick4Button4 };
		#endregion

		#region PrivateFields
		private Transform tr;
		private bool rmbDownInRect;
		private Vector3 mpStart;
		private Vector3 originalRotation;
		private float t;
		#endregion

		private Vector3 mousePosition
		{
			get
			{
				Camera cam = GetComponent<Camera>();
				return cam == null ? Vector3.Scale(Input.mousePosition, new Vector3(1f/Screen.width, 1f/Screen.height, 1f)) : cam.ScreenToViewportPoint(Input.mousePosition);
			}
		}

		// 
		void Awake()
		{
			tr = GetComponent<Transform>();
		}

		// 
		void OnEnable()
		{
			t = Time.realtimeSinceStartup;
		}

		// 
		void Update()
		{
			float timeNow = Time.realtimeSinceStartup;
			float dT = timeNow - t;
			t = timeNow;

			HandleMouseInput(dT);
			HandleControllerInput(dT);
		}

		// 
		void HandleMouseInput(float dT)
		{
			Vector3 mp = mousePosition;

			// Unlock cursor on mouse move
			if (InputHelper.GetAxis(axisMouseX) != 0f || InputHelper.GetAxis(axisMouseY) != 0f)
			{
				Cursor.lockState = CursorLockMode.None;
			}

			bool rmbDown = Input.GetMouseButtonDown(1);
			bool rmbHeld = Input.GetMouseButton(1);
			bool mouseInCameraRect = mp.x >= 0f && mp.x < 1f && mp.y >= 0f && mp.y < 1f;

			rmbDownInRect = (rmbDownInRect && rmbHeld) || (mouseInCameraRect && rmbDown);

			// Movement
			if (rmbDownInRect || (!rmbHeld && mouseInCameraRect))
			{
				Vector3 moveDirection = new Vector3(InputHelper.GetKey(keysRight, keysLeft), InputHelper.GetKey(keysUp, keysDown), InputHelper.GetKey(keysForward, keysBackward));
				float speedMultiplier = InputHelper.GetKey(keysRun) ? 2f : 1f;
				tr.position += tr.TransformDirection(moveDirection * keyboardMoveSpeed * speedMultiplier * dT);
			}

			// Rotation
			if (rmbDownInRect)
			{
				// Right Mouse Button Down
				if (rmbDown)
				{
					originalRotation = tr.localEulerAngles;
					mpStart = mp;
				}

				// Right Mouse Button Hold
				if (rmbHeld)
				{
					Vector2 offs = new Vector2((mp.x - mpStart.x), (mpStart.y - mp.y));
					tr.localEulerAngles = originalRotation + new Vector3(offs.y * 360f, offs.x * 360f, 0f);
				}
			}
		}

		// 
		void HandleControllerInput(float dT)
		{
			float axis1 = InputHelper.GetAxis(axisJoystickAxis1);
			float axis2 = InputHelper.GetAxis(axisJoystickAxis2);
			float axis4 = InputHelper.GetAxis(axisJoystickAxis4);
			float axis5 = InputHelper.GetAxis(axisJoystickAxis5);
			int vertical = InputHelper.GetKey(joystickUp, joystickDown);
			bool run = Input.GetKey(KeyCode.JoystickButton8);

			Vector3 moveDirection = new Vector3
			(
				InputHelper.Remap(axis1, joystickAxisThresholdMin, joystickAxisThresholdMax, joystickMoveSpeedXMin, joystickMoveSpeedXMax), 
				vertical * joystickMoveSpeedY, 
				InputHelper.Remap(-axis2, joystickAxisThresholdMin, joystickAxisThresholdMax, joystickMoveSpeedZMin, joystickMoveSpeedZMax) 
			);

			Vector3 rotation = new Vector3
			(
				InputHelper.Remap(axis5, joystickAxisThresholdMin, joystickAxisThresholdMax, joystickRotationSpeedMin, joystickRotationSpeedMax), 
				InputHelper.Remap(axis4, joystickAxisThresholdMin, joystickAxisThresholdMax, joystickRotationSpeedMin, joystickRotationSpeedMax), 
				0f 
			);

			bool anyInput = moveDirection.sqrMagnitude > 0f || rotation.sqrMagnitude > 0f || vertical != 0 || run;

			// Lock cursor on gamepad input
			if (anyInput)
			{
				Cursor.lockState = CursorLockMode.Locked;
			}

			float speedMultiplier = run ? 2f : 1f;
			tr.position += tr.TransformDirection(moveDirection * speedMultiplier * dT);
			tr.localEulerAngles += rotation * dT;
		}
	}

	static public class InputHelper
	{
		// 
		static public bool GetKey(KeyCode[] keys)
		{
			if (keys != null)
			{
				for (int i = 0, l = keys.Length; i < l; i++)
				{
					if (Input.GetKey(keys[i])) { return true; }
				}
			}
			return false;
		}

		// 
		static public bool GetKeyDown(KeyCode[] keys)
		{
			if (keys != null)
			{
				for (int i = 0, l = keys.Length; i < l; i++)
				{
					if (Input.GetKeyDown(keys[i])) { return true; }
				}
			}
			return false;
		}

		// 
		static public int GetKey(KeyCode[] keysPositive, KeyCode[] keysNegative)
		{
			int result = 0;

			if (GetKey(keysPositive)) { result++; }
			if (GetKey(keysNegative)) { result--; }

			return result;
		}

		// 
		static public int GetKeyDown(KeyCode[] keysPositive, KeyCode[] keysNegative)
		{
			int result = 0;

			if (GetKeyDown(keysPositive)) { result++; }
			if (GetKeyDown(keysNegative)) { result--; }

			return result;
		}

		// 
		static public float GetAxis(string axisName)
		{
			if (HasAxis(axisName)) { return Input.GetAxisRaw(axisName); }
			else { return 0f; }
		}

		// There is currently (Unity 5.5.0f3) no other way in Unity to check if a specific axis is defined in Input Manager settings or not
		static private Dictionary<string, bool> cachedHasAxis = new Dictionary<string, bool>();
		static public bool HasAxis(string axisName)
		{
			bool value;
			if (cachedHasAxis.TryGetValue(axisName, out value))
			{
				return value;
			}

			try { Input.GetAxisRaw(axisName); }
			catch
			{
				cachedHasAxis.Add(axisName, false);
				return false;
			}

			// No exception occured - axis defined in Input settings
			cachedHasAxis.Add(axisName, true);
			return true;
		}

		// 
		static public float Remap(float x, float xMin, float xMax, float yMin, float yMax)
		{
			float sign;
			float abs;
			if (x >= 0f)
			{
				sign = 1f;
				abs = x;
			}
			else
			{
				sign = -1f;
				abs = -x;
			}

			if (abs < xMin) { return 0f; }
			if (abs > xMax) { return xMax; }

			float t = (abs - xMin) / (xMax - xMin);
			return sign * Mathf.Lerp(yMin, yMax, t);
		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值