102 lines
3.5 KiB
C#
102 lines
3.5 KiB
C#
|
using Core;
|
|||
|
using UnityEngine;
|
|||
|
|
|||
|
namespace Player
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// 玩家第一人称相机控制器
|
|||
|
/// 挂到相机或相机父物体,playerBody 指向角色的根 Transform(用于左右旋转)
|
|||
|
/// </summary>
|
|||
|
/// TODO:使用InputManager替换掉Input.GetAxis
|
|||
|
public class PlayerCameraController : MonoBehaviour
|
|||
|
{
|
|||
|
[Header("References")]
|
|||
|
[Tooltip("角色根 Transform,用于水平旋转(yaw)")]
|
|||
|
public Transform playerBody;
|
|||
|
[Tooltip("如果相机不是挂载在同一物体上,可以指定相机 Transform(可选)")]
|
|||
|
public Transform cameraTransform;
|
|||
|
|
|||
|
[Header("Sensitivity & Invert")]
|
|||
|
[Tooltip("鼠标灵敏度")]
|
|||
|
[Range(0.01f, 1f)]
|
|||
|
public float mouseSensitivity = 0.2f;
|
|||
|
|
|||
|
[Tooltip("反转垂直轴")]
|
|||
|
public bool invertY = false;
|
|||
|
|
|||
|
[Header("Vertical Limits")]
|
|||
|
[Tooltip("向上最大仰角(度)")]
|
|||
|
public float maxUpAngle = 60f;
|
|||
|
[Tooltip("向下最大俯角(度)")]
|
|||
|
public float maxDownAngle = 60f;
|
|||
|
|
|||
|
[Header("Smoothing")]
|
|||
|
public bool enableSmoothing = false;
|
|||
|
[Tooltip("旋转平滑时间(秒)")]
|
|||
|
public float smoothTime = 0.05f;
|
|||
|
|
|||
|
// internal state
|
|||
|
private float xRotation = 0f; // 垂直角(pitch)
|
|||
|
private float yaw = 0f; // 水平角(yaw)
|
|||
|
private float smoothVelocityPitch = 0f;
|
|||
|
private float smoothVelocityYaw = 0f;
|
|||
|
|
|||
|
void Start()
|
|||
|
{
|
|||
|
if (cameraTransform == null)
|
|||
|
cameraTransform = transform;
|
|||
|
|
|||
|
// 初始化当前角度以避免跳变
|
|||
|
Vector3 euler = cameraTransform.localEulerAngles;
|
|||
|
xRotation = NormalizeAngle(euler.x);
|
|||
|
yaw = NormalizeAngle(playerBody ? playerBody.eulerAngles.y : transform.eulerAngles.y);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
void Update()
|
|||
|
{
|
|||
|
Vector2 mouse = InputManager.Instance.Look;
|
|||
|
|
|||
|
// ✅ 不要乘 Time.deltaTime,因为 Look 已经是每帧的增量
|
|||
|
float mouseX = mouse.x * mouseSensitivity;
|
|||
|
float mouseY = mouse.y * mouseSensitivity;
|
|||
|
|
|||
|
float invert = invertY ? 1f : -1f;
|
|||
|
|
|||
|
yaw += mouseX;
|
|||
|
xRotation += mouseY * invert;
|
|||
|
|
|||
|
// 限制垂直角度
|
|||
|
xRotation = Mathf.Clamp(xRotation, -maxDownAngle, maxUpAngle);
|
|||
|
|
|||
|
if (enableSmoothing)
|
|||
|
{
|
|||
|
float smoothPitch = Mathf.SmoothDampAngle(cameraTransform.localEulerAngles.x, xRotation, ref smoothVelocityPitch, smoothTime);
|
|||
|
float smoothYaw = Mathf.SmoothDampAngle(playerBody ? playerBody.eulerAngles.y : transform.eulerAngles.y, yaw, ref smoothVelocityYaw, smoothTime);
|
|||
|
|
|||
|
cameraTransform.localRotation = Quaternion.Euler(smoothPitch, 0f, 0f);
|
|||
|
if (playerBody)
|
|||
|
playerBody.rotation = Quaternion.Euler(0f, smoothYaw, 0f);
|
|||
|
else
|
|||
|
transform.rotation = Quaternion.Euler(0f, smoothYaw, 0f);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
cameraTransform.localRotation = Quaternion.Euler(xRotation, 0f, 0f);
|
|||
|
if (playerBody)
|
|||
|
playerBody.rotation = Quaternion.Euler(0f, yaw, 0f);
|
|||
|
else
|
|||
|
transform.rotation = Quaternion.Euler(0f, yaw, 0f);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
// 将角度规范到 [-180,180] 范围,避免插值跳变
|
|||
|
private float NormalizeAngle(float angle)
|
|||
|
{
|
|||
|
angle = (angle + 180f) % 360f - 180f;
|
|||
|
return angle;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|