You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
301 lines
10 KiB
301 lines
10 KiB
#if ENABLE_INPUT_SYSTEM |
|
using UnityEngine.InputSystem; |
|
#endif |
|
|
|
using UnityEngine; |
|
|
|
namespace UnityTemplateProjects |
|
{ |
|
public class SimpleCameraController : MonoBehaviour |
|
{ |
|
class CameraState |
|
{ |
|
public float yaw; |
|
public float pitch; |
|
public float roll; |
|
public float x; |
|
public float y; |
|
public float z; |
|
|
|
public void SetFromTransform(Transform t) |
|
{ |
|
pitch = t.eulerAngles.x; |
|
yaw = t.eulerAngles.y; |
|
roll = t.eulerAngles.z; |
|
x = t.position.x; |
|
y = t.position.y; |
|
z = t.position.z; |
|
} |
|
|
|
public void Translate(Vector3 translation) |
|
{ |
|
Vector3 rotatedTranslation = Quaternion.Euler(pitch, yaw, roll) * translation; |
|
|
|
x += rotatedTranslation.x; |
|
y += rotatedTranslation.y; |
|
z += rotatedTranslation.z; |
|
} |
|
|
|
public void LerpTowards(CameraState target, float positionLerpPct, float rotationLerpPct) |
|
{ |
|
yaw = Mathf.Lerp(yaw, target.yaw, rotationLerpPct); |
|
pitch = Mathf.Lerp(pitch, target.pitch, rotationLerpPct); |
|
roll = Mathf.Lerp(roll, target.roll, rotationLerpPct); |
|
|
|
x = Mathf.Lerp(x, target.x, positionLerpPct); |
|
y = Mathf.Lerp(y, target.y, positionLerpPct); |
|
z = Mathf.Lerp(z, target.z, positionLerpPct); |
|
} |
|
|
|
public void UpdateTransform(Transform t) |
|
{ |
|
t.eulerAngles = new Vector3(pitch, yaw, roll); |
|
t.position = new Vector3(x, y, z); |
|
} |
|
} |
|
|
|
const float k_MouseSensitivityMultiplier = 0.01f; |
|
|
|
CameraState m_TargetCameraState = new CameraState(); |
|
CameraState m_InterpolatingCameraState = new CameraState(); |
|
|
|
[Header("Movement Settings")] |
|
[Tooltip("Exponential boost factor on translation, controllable by mouse wheel.")] |
|
public float boost = 3.5f; |
|
|
|
[Tooltip("Time it takes to interpolate camera position 99% of the way to the target."), Range(0.001f, 1f)] |
|
public float positionLerpTime = 0.2f; |
|
|
|
[Header("Rotation Settings")] |
|
[Tooltip("Multiplier for the sensitivity of the rotation.")] |
|
public float mouseSensitivity = 60.0f; |
|
|
|
[Tooltip("X = Change in mouse position.\nY = Multiplicative factor for camera rotation.")] |
|
public AnimationCurve mouseSensitivityCurve = new AnimationCurve(new Keyframe(0f, 0.5f, 0f, 5f), new Keyframe(1f, 2.5f, 0f, 0f)); |
|
|
|
[Tooltip("Time it takes to interpolate camera rotation 99% of the way to the target."), Range(0.001f, 1f)] |
|
public float rotationLerpTime = 0.01f; |
|
|
|
[Tooltip("Whether or not to invert our Y axis for mouse input to rotation.")] |
|
public bool invertY = false; |
|
|
|
#if ENABLE_INPUT_SYSTEM |
|
InputAction movementAction; |
|
InputAction verticalMovementAction; |
|
InputAction lookAction; |
|
InputAction boostFactorAction; |
|
bool mouseRightButtonPressed; |
|
|
|
void Start() |
|
{ |
|
var map = new InputActionMap("Simple Camera Controller"); |
|
|
|
lookAction = map.AddAction("look", binding: "<Mouse>/delta"); |
|
movementAction = map.AddAction("move", binding: "<Gamepad>/leftStick"); |
|
verticalMovementAction = map.AddAction("Vertical Movement"); |
|
boostFactorAction = map.AddAction("Boost Factor", binding: "<Mouse>/scroll"); |
|
|
|
lookAction.AddBinding("<Gamepad>/rightStick").WithProcessor("scaleVector2(x=15, y=15)"); |
|
movementAction.AddCompositeBinding("Dpad") |
|
.With("Up", "<Keyboard>/w") |
|
.With("Up", "<Keyboard>/upArrow") |
|
.With("Down", "<Keyboard>/s") |
|
.With("Down", "<Keyboard>/downArrow") |
|
.With("Left", "<Keyboard>/a") |
|
.With("Left", "<Keyboard>/leftArrow") |
|
.With("Right", "<Keyboard>/d") |
|
.With("Right", "<Keyboard>/rightArrow"); |
|
verticalMovementAction.AddCompositeBinding("Dpad") |
|
.With("Up", "<Keyboard>/pageUp") |
|
.With("Down", "<Keyboard>/pageDown") |
|
.With("Up", "<Keyboard>/e") |
|
.With("Down", "<Keyboard>/q") |
|
.With("Up", "<Gamepad>/rightshoulder") |
|
.With("Down", "<Gamepad>/leftshoulder"); |
|
boostFactorAction.AddBinding("<Gamepad>/Dpad").WithProcessor("scaleVector2(x=1, y=4)"); |
|
|
|
movementAction.Enable(); |
|
lookAction.Enable(); |
|
verticalMovementAction.Enable(); |
|
boostFactorAction.Enable(); |
|
} |
|
|
|
#endif |
|
|
|
void OnEnable() |
|
{ |
|
m_TargetCameraState.SetFromTransform(transform); |
|
m_InterpolatingCameraState.SetFromTransform(transform); |
|
} |
|
|
|
Vector3 GetInputTranslationDirection() |
|
{ |
|
Vector3 direction = Vector3.zero; |
|
#if ENABLE_INPUT_SYSTEM |
|
var moveDelta = movementAction.ReadValue<Vector2>(); |
|
direction.x = moveDelta.x; |
|
direction.z = moveDelta.y; |
|
direction.y = verticalMovementAction.ReadValue<Vector2>().y; |
|
#else |
|
if (Input.GetKey(KeyCode.W)) |
|
{ |
|
direction += Vector3.forward; |
|
} |
|
if (Input.GetKey(KeyCode.S)) |
|
{ |
|
direction += Vector3.back; |
|
} |
|
if (Input.GetKey(KeyCode.A)) |
|
{ |
|
direction += Vector3.left; |
|
} |
|
if (Input.GetKey(KeyCode.D)) |
|
{ |
|
direction += Vector3.right; |
|
} |
|
if (Input.GetKey(KeyCode.Q)) |
|
{ |
|
direction += Vector3.down; |
|
} |
|
if (Input.GetKey(KeyCode.E)) |
|
{ |
|
direction += Vector3.up; |
|
} |
|
#endif |
|
return direction; |
|
} |
|
|
|
void Update() |
|
{ |
|
// Exit Sample |
|
|
|
if (IsEscapePressed()) |
|
{ |
|
Application.Quit(); |
|
#if UNITY_EDITOR |
|
UnityEditor.EditorApplication.isPlaying = false; |
|
#endif |
|
} |
|
|
|
// Hide and lock cursor when right mouse button pressed |
|
if (IsRightMouseButtonDown()) |
|
{ |
|
Cursor.lockState = CursorLockMode.Locked; |
|
} |
|
|
|
// Unlock and show cursor when right mouse button released |
|
if (IsRightMouseButtonUp()) |
|
{ |
|
Cursor.visible = true; |
|
Cursor.lockState = CursorLockMode.None; |
|
} |
|
|
|
// Rotation |
|
if (IsCameraRotationAllowed()) |
|
{ |
|
var mouseMovement = GetInputLookRotation() * k_MouseSensitivityMultiplier * mouseSensitivity; |
|
if (invertY) |
|
mouseMovement.y = -mouseMovement.y; |
|
|
|
var mouseSensitivityFactor = mouseSensitivityCurve.Evaluate(mouseMovement.magnitude); |
|
|
|
m_TargetCameraState.yaw += mouseMovement.x * mouseSensitivityFactor; |
|
m_TargetCameraState.pitch += mouseMovement.y * mouseSensitivityFactor; |
|
} |
|
|
|
// Translation |
|
var translation = GetInputTranslationDirection() * Time.deltaTime; |
|
|
|
// Speed up movement when shift key held |
|
if (IsBoostPressed()) |
|
{ |
|
translation *= 10.0f; |
|
} |
|
|
|
// Modify movement by a boost factor (defined in Inspector and modified in play mode through the mouse scroll wheel) |
|
boost += GetBoostFactor(); |
|
translation *= Mathf.Pow(2.0f, boost); |
|
|
|
m_TargetCameraState.Translate(translation); |
|
|
|
// Framerate-independent interpolation |
|
// Calculate the lerp amount, such that we get 99% of the way to our target in the specified time |
|
var positionLerpPct = 1f - Mathf.Exp((Mathf.Log(1f - 0.99f) / positionLerpTime) * Time.deltaTime); |
|
var rotationLerpPct = 1f - Mathf.Exp((Mathf.Log(1f - 0.99f) / rotationLerpTime) * Time.deltaTime); |
|
m_InterpolatingCameraState.LerpTowards(m_TargetCameraState, positionLerpPct, rotationLerpPct); |
|
|
|
m_InterpolatingCameraState.UpdateTransform(transform); |
|
} |
|
|
|
float GetBoostFactor() |
|
{ |
|
#if ENABLE_INPUT_SYSTEM |
|
return boostFactorAction.ReadValue<Vector2>().y * 0.01f; |
|
#else |
|
return Input.mouseScrollDelta.y * 0.01f; |
|
#endif |
|
} |
|
|
|
Vector2 GetInputLookRotation() |
|
{ |
|
// try to compensate the diff between the two input systems by multiplying with empirical values |
|
#if ENABLE_INPUT_SYSTEM |
|
var delta = lookAction.ReadValue<Vector2>(); |
|
delta *= 0.5f; // Account for scaling applied directly in Windows code by old input system. |
|
delta *= 0.1f; // Account for sensitivity setting on old Mouse X and Y axes. |
|
return delta; |
|
#else |
|
return new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y")); |
|
#endif |
|
} |
|
|
|
bool IsBoostPressed() |
|
{ |
|
#if ENABLE_INPUT_SYSTEM |
|
bool boost = Keyboard.current != null ? Keyboard.current.leftShiftKey.isPressed : false; |
|
boost |= Gamepad.current != null ? Gamepad.current.xButton.isPressed : false; |
|
return boost; |
|
#else |
|
return Input.GetKey(KeyCode.LeftShift); |
|
#endif |
|
} |
|
|
|
bool IsEscapePressed() |
|
{ |
|
#if ENABLE_INPUT_SYSTEM |
|
return Keyboard.current != null ? Keyboard.current.escapeKey.isPressed : false; |
|
#else |
|
return Input.GetKey(KeyCode.Escape); |
|
#endif |
|
} |
|
|
|
bool IsCameraRotationAllowed() |
|
{ |
|
#if ENABLE_INPUT_SYSTEM |
|
bool canRotate = Mouse.current != null ? Mouse.current.rightButton.isPressed : false; |
|
canRotate |= Gamepad.current != null ? Gamepad.current.rightStick.ReadValue().magnitude > 0 : false; |
|
return canRotate; |
|
#else |
|
return Input.GetMouseButton(1); |
|
#endif |
|
} |
|
|
|
bool IsRightMouseButtonDown() |
|
{ |
|
#if ENABLE_INPUT_SYSTEM |
|
return Mouse.current != null ? Mouse.current.rightButton.isPressed : false; |
|
#else |
|
return Input.GetMouseButtonDown(1); |
|
#endif |
|
} |
|
|
|
bool IsRightMouseButtonUp() |
|
{ |
|
#if ENABLE_INPUT_SYSTEM |
|
return Mouse.current != null ? !Mouse.current.rightButton.isPressed : false; |
|
#else |
|
return Input.GetMouseButtonUp(1); |
|
#endif |
|
} |
|
} |
|
}
|
|
|