187 lines
4.7 KiB
C#
187 lines
4.7 KiB
C#
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
|
||
namespace SK.Framework
|
||
{
|
||
/// <summary>
|
||
/// 自由相机控制器
|
||
/// WASD 移动,鼠标旋转,Q/E 上升下降,Shift 加速
|
||
/// </summary>
|
||
[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 视角旋转
|
||
|
||
/// <summary>
|
||
/// 鼠标控制相机旋转
|
||
/// </summary>
|
||
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 移动控制
|
||
|
||
/// <summary>
|
||
/// WASD + Q/E + Shift 移动
|
||
/// </summary>
|
||
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
|
||
}
|
||
}
|