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