Files
Cielonos/Assets/Scripts/MainGame/Characters/Player/View/CameraFovSubmodule.cs
SoulliesOfficial 0902ca8a9e Bezi回来了
2026-04-28 15:46:32 -04:00

134 lines
4.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Cielonos.MainGame.Effects.Feedback;
using DG.Tweening;
using Unity.Cinemachine;
using UnityEngine;
namespace Cielonos.MainGame.Characters
{
public class CameraFovSubmodule : SubmoduleBase<PlayerViewSubcontroller>
{
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;
}
/// <summary>
/// 根据水平速度更新FOV
/// </summary>
/// <param name="horizontalSpeed">水平速度(单位/秒)</param>
/// <param name="deltaTime">帧时间</param>
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);
}
/// <summary>
/// 根据速度计算目标FOV
/// </summary>
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);
}
/// <summary>
/// 应用FOV到相机
/// </summary>
private void ApplyFov(float fov)
{
fov = Mathf.Clamp(fov, minFov, maxFov);
LensSettings lens = currentCamera.Lens;
lens.FieldOfView = fov;
currentCamera.Lens = lens;
}
/// <summary>
/// 立即设置FOV不使用平滑过渡
/// </summary>
public void SetFovImmediate(float fov)
{
currentFov = fov;
targetFov = fov;
ApplyFov(fov);
}
/// <summary>
/// 平滑过渡到指定FOV
/// </summary>
public void SetFovSmooth(float targetFovValue, float duration)
{
DOTween.To(() => currentFov, x =>
{
currentFov = x;
ApplyFov(x);
}, targetFovValue, duration)
.SetEase(Ease.OutQuad);
targetFov = targetFovValue;
}
/// <summary>
/// 重置为默认FOV
/// </summary>
public void ResetToBaseFov()
{
targetFov = baseFov;
}
}
}