102 lines
3.5 KiB
C#
102 lines
3.5 KiB
C#
using Core;
|
||
using UnityEngine;
|
||
using Input;
|
||
|
||
namespace Gameplay.Player
|
||
{
|
||
/// <summary>
|
||
/// 玩家第一人称相机控制器
|
||
/// 挂到相机或相机父物体,playerBody 指向角色的根 Transform(用于左右旋转)
|
||
/// </summary>
|
||
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;
|
||
}
|
||
}
|
||
}
|