using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace SK.Framework
{
///
/// 自由相机控制器
/// WASD 移动,鼠标旋转,Q/E 上升下降,Shift 加速
///
[DisallowMultipleComponent]
public class FreeCameraController : MonoBehaviour
{
#region Inspector 参数
[Header("控制总开关")]
[Tooltip("是否启用相机控制")]
public bool enableControl = true;
[Tooltip("按住该鼠标键时才能旋转视角(0=左键,1=右键)")]
public int lookMouseButton = 1;
[Tooltip("旋转时是否锁定鼠标")]
public bool lockCursor = true;
[Header("移动参数(WASD)")]
public float moveSpeed = 5f;
public float moveDamping = 10f;
[Header("Shift 加速")]
[Tooltip("按住 Shift 时速度倍率")]
public float shiftMultiplier = 2f;
[Header("垂直移动(Q / E)")]
[Tooltip("是否允许 Q/E 垂直移动")]
public bool enableVerticalMove = true;
public float verticalSpeed = 3f;
public float minHeight = -10f;
public float maxHeight = 50f;
[Header("视角旋转")]
public float mouseSensitivityX = 120f;
public float mouseSensitivityY = 80f;
[Tooltip("俯仰角最小值")]
public float minPitch = -80f;
[Tooltip("俯仰角最大值")]
public float maxPitch = 80f;
public float rotationDamping = 12f;
#endregion
#region 运行时状态
// 目标旋转角
private float yaw;
private float pitch;
// 平滑旋转角
private float smoothYaw;
private float smoothPitch;
// 目标移动速度
private Vector3 targetVelocity;
private Vector3 smoothVelocity;
#endregion
#region Unity 生命周期
void Start()
{
// 初始化角度
Vector3 angles = transform.eulerAngles;
yaw = angles.y;
pitch = angles.x;
smoothYaw = yaw;
smoothPitch = pitch;
}
void Update()
{
if (!enableControl)
return;
HandleRotation();
HandleMovement();
}
#endregion
#region 视角旋转
///
/// 鼠标控制相机旋转
///
void HandleRotation()
{
if (!Input.GetMouseButton(lookMouseButton))
{
// 松开鼠标时恢复光标
Cursor.lockState = CursorLockMode.None;
Cursor.visible = true;
return;
}
if (lockCursor)
{
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
yaw += Input.GetAxis("Mouse X") * mouseSensitivityX * Time.deltaTime;
pitch -= Input.GetAxis("Mouse Y") * mouseSensitivityY * Time.deltaTime;
pitch = Mathf.Clamp(pitch, minPitch, maxPitch);
// 阻尼平滑
smoothYaw = Mathf.LerpAngle(smoothYaw, yaw, Time.deltaTime * rotationDamping);
smoothPitch = Mathf.Lerp(smoothPitch, pitch, Time.deltaTime * rotationDamping);
transform.rotation = Quaternion.Euler(smoothPitch, smoothYaw, 0f);
}
#endregion
#region 移动控制
///
/// WASD + Q/E + Shift 移动
///
void HandleMovement()
{
Vector3 inputDir = Vector3.zero;
// WASD 平移
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
inputDir += transform.forward * v;
inputDir += transform.right * h;
// Q / E 垂直移动(可开关)
if (enableVerticalMove)
{
if (Input.GetKey(KeyCode.E))
inputDir += Vector3.up;
if (Input.GetKey(KeyCode.Q))
inputDir += Vector3.down;
}
inputDir = inputDir.normalized;
// 基础速度
float currentSpeed = moveSpeed;
// Shift 加速
if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))
{
currentSpeed *= shiftMultiplier;
}
// 目标速度
targetVelocity = inputDir * currentSpeed;
// 阻尼平滑
smoothVelocity = Vector3.Lerp(
smoothVelocity,
targetVelocity,
Time.deltaTime * moveDamping
);
Vector3 nextPos = transform.position + smoothVelocity * Time.deltaTime;
// 高度限制
nextPos.y = Mathf.Clamp(nextPos.y, minHeight, maxHeight);
transform.position = nextPos;
}
#endregion
}
}