Files
XericLibrary-Publish/Runtime/Player/CameraController.cs
2025-04-10 15:32:00 +08:00

294 lines
9.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#if CREST_UNITY_INPUT && ENABLE_INPUT_SYSTEM
#define INPUT_SYSTEM_ENABLED
#endif
using System;
using UnityEngine;
#if INPUT_SYSTEM_ENABLED
using UnityEngine.InputSystem;
#endif
#if ENABLE_VR && ENABLE_VR_MODULE
using UnityEngine.XR;
#endif
namespace Deconstruction.Runtime.Player
{
/// <summary>
/// 一个简单且功能有限的摄像机脚本,可通过 WASD 键和鼠标进行控制。
/// </summary>
public class CameraController : MonoBehaviour
{
/// <summary>
/// 此资产的版本。可用于不同版本之间的迁移。只有在编辑器升级版本时才应更改此值。
/// </summary>
[SerializeField, HideInInspector]
#pragma warning disable 414
int _version = 0;
#pragma warning restore 414
public float linSpeed = 10f;
public float rotSpeed = 70f;
public bool simForwardInput = false;
public bool _requireLMBToMove = false;
public bool enableWalkMode = false;
Vector2 _lastMousePos = -Vector2.one;
bool _dragging = false;
public float _fixedDt = 1 / 60f;
Transform _targetTransform;
public CharacterController _moveComponent;
[Space(10)]
[SerializeField]
DebugFields _debug = new DebugFields();
#pragma warning disable CS0108
// 在编辑器中我们需要使用“new”来屏蔽警告但在构建时会再次给出警告所以应该使用“pragma”来替代。
private Camera camera;
#pragma warning restore CS0108
[System.Serializable]
class DebugFields
{
[Tooltip("Allows the camera to roll (rotating on the z axis).")]
public bool _enableCameraRoll = false;
[Tooltip("Disables the XR occlusion mesh for debugging purposes. Only works with legacy XR.")]
public bool _disableOcclusionMesh = false;
[Tooltip("Sets the XR occlusion mesh scale. Useful for debugging refractions. Only works with legacy XR."), UnityEngine.Range(1f, 2f)]
public float _occlusionMeshScale = 1f;
}
private void OnValidate()
{
if (_moveComponent == null)
{
_moveComponent = GetComponent<CharacterController>();
}
else if (Application.isEditor)
{
_moveComponent.enabled = enableWalkMode;
}
}
void Awake()
{
_targetTransform = transform;
if (!TryGetComponent(out camera))
{
enabled = false;
return;
}
if (_moveComponent != null)
{
_moveComponent.enabled = enableWalkMode;
}
#if ENABLE_VR && ENABLE_VR_MODULE
if (XRSettings.enabled)
{
// Seems like the best place to put this for now. Most XR debugging happens using this component.
// @FixMe: useOcclusionMesh doesn't work anymore. Might be a Unity bug.
XRSettings.useOcclusionMesh = !_debug._disableOcclusionMesh;
XRSettings.occlusionMaskScale = _debug._occlusionMeshScale;
}
#endif
}
void Update()
{
float dt = Time.deltaTime;
if (_fixedDt > 0f)
dt = _fixedDt;
UpdateMovement(dt);
#if ENABLE_VR && ENABLE_VR_MODULE
// These aren't useful and can break for XR hardware.
if (!XRSettings.enabled || XRSettings.loadedDeviceName.Contains("MockHMD"))
#endif
{
UpdateDragging(dt);
UpdateKillRoll();
}
#if ENABLE_VR && ENABLE_VR_MODULE
if (XRSettings.enabled)
{
// Check if property has changed.
if (XRSettings.useOcclusionMesh == _debug._disableOcclusionMesh)
{
// @FixMe: useOcclusionMesh doesn't work anymore. Might be a Unity bug.
XRSettings.useOcclusionMesh = !_debug._disableOcclusionMesh;
}
XRSettings.occlusionMaskScale = _debug._occlusionMeshScale;
}
#endif
}
void UpdateMovement(float dt)
{
// New input system works even when game view is not focused.
if (!Application.isFocused)
{
return;
}
#if INPUT_SYSTEM_ENABLED
if (!Mouse.current.leftButton.isPressed && _requireLMBToMove) return;
float forward = (Keyboard.current.wKey.isPressed ? 1 : 0) - (Keyboard.current.sKey.isPressed ? 1 : 0);
#else
if (!Input.GetMouseButton(1) && _requireLMBToMove) return;
float forward = (Input.GetKey(KeyCode.W) ? 1 : 0) - (Input.GetKey(KeyCode.S) ? 1 : 0);
#endif
if (simForwardInput)
{
forward = 1f;
}
_targetTransform.position += linSpeed * _targetTransform.forward * forward * dt;
var speed = linSpeed;
#if INPUT_SYSTEM_ENABLED
if (Keyboard.current.leftShiftKey.isPressed)
#else
if (Input.GetKey(KeyCode.LeftShift))
#endif
{
speed *= 3f;
}
var offset = _targetTransform.forward * forward;
// _targetTransform.position += speed * _targetTransform.forward * forward * dt;
//_transform.position += linSpeed * _transform.right * Input.GetAxis( "Horizontal" ) * dt;
#if INPUT_SYSTEM_ENABLED
offset += _targetTransform.up * (Keyboard.current.eKey.isPressed ? 1 : 0);
offset -= _targetTransform.up * (Keyboard.current.qKey.isPressed ? 1 : 0);
offset -= _targetTransform.right * (Keyboard.current.aKey.isPressed ? 1 : 0);
offset += _targetTransform.right * (Keyboard.current.dKey.isPressed ? 1 : 0);
#else
offset += _targetTransform.up * (Input.GetKey(KeyCode.E) ? 1 : 0);
offset -= _targetTransform.up * (Input.GetKey(KeyCode.Q) ? 1 : 0);
offset -= _targetTransform.right * (Input.GetKey(KeyCode.A) ? 1 : 0);
offset += _targetTransform.right * (Input.GetKey(KeyCode.D) ? 1 : 0);
#endif
offset *= speed * dt;
// 使用控制器移动
if (enableWalkMode)
{
UpdateWalk(offset);
}
// 直接设置坐标移动
else
{
_targetTransform.position += offset;
}
{
float rotate = 0f;
#if INPUT_SYSTEM_ENABLED
rotate += (Keyboard.current.rightArrowKey.isPressed ? 1 : 0);
rotate -= (Keyboard.current.leftArrowKey.isPressed ? 1 : 0);
#else
rotate += (Input.GetKey(KeyCode.RightArrow) ? 1 : 0);
rotate -= (Input.GetKey(KeyCode.LeftArrow) ? 1 : 0);
#endif
rotate *= 5f;
Vector3 ea = _targetTransform.eulerAngles;
ea.y += 0.1f * rotSpeed * rotate * dt;
_targetTransform.eulerAngles = ea;
}
}
void UpdateDragging(float dt)
{
// New input system works even when game view is not focused.
if (!Application.isFocused)
{
return;
}
Vector2 mousePos =
#if INPUT_SYSTEM_ENABLED
Mouse.current.position.ReadValue();
#else
Input.mousePosition;
#endif
var wasLeftMouseButtonPressed =
#if INPUT_SYSTEM_ENABLED
Mouse.current.leftButton.wasPressedThisFrame;
#else
Input.GetMouseButtonDown(1);
#endif
if (!_dragging && wasLeftMouseButtonPressed && camera.rect.Contains(camera.ScreenToViewportPoint(mousePos)) )
//!Crest.OceanDebugGUI.OverGUI(mousePos))
{
_dragging = true;
_lastMousePos = mousePos;
}
#if INPUT_SYSTEM_ENABLED
if (_dragging && Mouse.current.leftButton.wasReleasedThisFrame)
#else
if (_dragging && Input.GetMouseButtonUp(1))
#endif
{
_dragging = false;
_lastMousePos = -Vector2.one;
}
if (_dragging)
{
Vector2 delta = mousePos - _lastMousePos;
Vector3 ea = _targetTransform.eulerAngles;
ea.x += -0.1f * rotSpeed * delta.y * dt;
ea.y += 0.1f * rotSpeed * delta.x * dt;
_targetTransform.eulerAngles = ea;
_lastMousePos = mousePos;
}
}
void UpdateKillRoll()
{
if (_debug._enableCameraRoll) return;
Vector3 ea = _targetTransform.eulerAngles;
ea.z = 0f;
transform.eulerAngles = ea;
}
private float gravity = 0;
void UpdateWalk(Vector3 offset)
{
if (_moveComponent != null)
{
_moveComponent.enabled = enableWalkMode;
if (enableWalkMode)
{
if (offset.y > 0)
gravity = 0;
else
{
gravity -= 0.01f;
gravity = Mathf.Max(gravity, -0.98f);
}
offset.y = offset.y <= 0 ? gravity : offset.y;
_moveComponent.Move(offset);
}
}
}
}
}