using Cielonos.MainGame.Effects.Feedback; using DG.Tweening; using Unity.Cinemachine; using UnityEngine; namespace Cielonos.MainGame.Characters { public class CameraFovSubmodule : SubmoduleBase { private Player player => owner.player; private PlayerViewSubcontroller viewSc => owner; [Header("基础FOV配置")] [Tooltip("静止时的基础FOV")] public float baseFov = 45f; [Tooltip("FOV最小值")] public float minFov = 40f; [Tooltip("FOV最大值(疾奔时)")] public float maxFov = 55f; [Header("速度阈值")] [Tooltip("开始FOV变化的最小速度")] public float speedThreshold = 3f; [Tooltip("达到最大FOV的速度")] public float maxSpeedThreshold = 15f; [Header("过渡设置")] [Tooltip("FOV变化的速度")] public float fovChangeSpeed = 5f; [Tooltip("是否平滑过渡FOV")] public bool useSmoothTransition = true; private float currentFov; private float targetFov; private CinemachineCamera currentCamera => viewSc.currentCamera; public CameraFovSubmodule(PlayerViewSubcontroller owner, float baseFov, float minFov, float maxFov, float speedThreshold, float maxSpeedThreshold, float fovChangeSpeed, bool useSmoothTransition) : base(owner) { this.baseFov = baseFov; this.minFov = minFov; this.maxFov = maxFov; this.speedThreshold = speedThreshold; this.maxSpeedThreshold = maxSpeedThreshold; this.fovChangeSpeed = fovChangeSpeed; this.useSmoothTransition = useSmoothTransition; this.currentFov = baseFov; this.targetFov = baseFov; } /// /// 根据水平速度更新FOV /// /// 水平速度(单位/秒) /// 帧时间 public void UpdateFovBySpeed(float horizontalSpeed, float deltaTime) { // 计算目标FOV targetFov = CalculateTargetFov(horizontalSpeed); // 平滑过渡 if (useSmoothTransition) { currentFov = Mathf.Lerp(currentFov, targetFov, deltaTime * fovChangeSpeed); } else { currentFov = targetFov; } // 应用FOV ApplyFov(currentFov); } /// /// 根据速度计算目标FOV /// private float CalculateTargetFov(float speed) { if (speed < speedThreshold) { return baseFov; } // 使用InverseLerp将速度映射到0-1范围 float t = Mathf.InverseLerp(speedThreshold, maxSpeedThreshold, speed); // 使用SmoothStep使过渡更平滑 t = Mathf.SmoothStep(0f, 1f, t); return Mathf.Lerp(baseFov, maxFov, t); } /// /// 应用FOV到相机 /// private void ApplyFov(float fov) { fov = Mathf.Clamp(fov, minFov, maxFov); LensSettings lens = currentCamera.Lens; lens.FieldOfView = fov; currentCamera.Lens = lens; } /// /// 立即设置FOV(不使用平滑过渡) /// public void SetFovImmediate(float fov) { currentFov = fov; targetFov = fov; ApplyFov(fov); } /// /// 平滑过渡到指定FOV /// public void SetFovSmooth(float targetFovValue, float duration) { DOTween.To(() => currentFov, x => { currentFov = x; ApplyFov(x); }, targetFovValue, duration) .SetEase(Ease.OutQuad); targetFov = targetFovValue; } /// /// 重置为默认FOV /// public void ResetToBaseFov() { targetFov = baseFov; } } }