103 lines
3.3 KiB
C#
103 lines
3.3 KiB
C#
using System;
|
||
using MoreMountains.Feedbacks;
|
||
using Sirenix.OdinInspector;
|
||
using SLSUtilities.Feedback;
|
||
using UnityEngine;
|
||
|
||
namespace Cielonos.MainGame.Effects.Feedback
|
||
{
|
||
/// <summary>
|
||
/// 摄像机位移震动反馈,通过 MMCinemachinePositionShakeEvent 触发现有的 Shaker。
|
||
/// Shaker 负责处理多个震动的叠加混合。
|
||
/// </summary>
|
||
[Serializable]
|
||
public class CameraPositionShakeAction : FeedbackActionBase
|
||
{
|
||
public override string DisplayName => "Camera Position Shake";
|
||
|
||
/// <summary>
|
||
/// 震动曲线,定义震动强度随时间的变化。
|
||
/// </summary>
|
||
[Title("Position Shake")]
|
||
[LabelText("Shake Curve")]
|
||
public AnimationCurve shakeCurve = new AnimationCurve(
|
||
new Keyframe(0f, 0f),
|
||
new Keyframe(0.2f, 1f),
|
||
new Keyframe(1f, 0f)
|
||
);
|
||
|
||
/// <summary>
|
||
/// 最大位移振幅(本地空间)。
|
||
/// </summary>
|
||
[LabelText("Amplitude")]
|
||
public Vector3 positionAmplitude = new Vector3(0.5f, 0.5f, 0f);
|
||
|
||
/// <summary>
|
||
/// 方向影响设置。
|
||
/// </summary>
|
||
[Title("Direction")]
|
||
public CameraDirectionSettings directionSettings = new CameraDirectionSettings();
|
||
|
||
/// <summary>
|
||
/// 距离衰减:根据摄像机与 owner 的距离衰减震动强度。
|
||
/// </summary>
|
||
[Title("Distance Attenuation")]
|
||
[LabelText("Use Attenuation")]
|
||
public bool useAttenuation;
|
||
|
||
/// <summary>
|
||
/// 全强度的最大距离。
|
||
/// </summary>
|
||
[ShowIf("useAttenuation")]
|
||
[LabelText("Attenuation Range")]
|
||
public float attenuationRange = 50f;
|
||
|
||
/// <summary>
|
||
/// 距离-强度衰减曲线(0=近处/全强度,1=远处/无强度)。
|
||
/// </summary>
|
||
[ShowIf("useAttenuation")]
|
||
[LabelText("Attenuation Curve")]
|
||
public AnimationCurve attenuationCurve = new AnimationCurve(
|
||
new Keyframe(0f, 1f),
|
||
new Keyframe(1f, 0f)
|
||
);
|
||
|
||
public override void OnStart(FeedbackContext context)
|
||
{
|
||
Vector3 finalAmplitude = directionSettings.TransformAmplitude(positionAmplitude, context.owner);
|
||
float intensityMultiplier = ComputeAttenuation(context);
|
||
|
||
MMCinemachinePositionShakeEvent.Trigger(
|
||
null,
|
||
shakeCurve,
|
||
context.duration,
|
||
finalAmplitude,
|
||
intensityMultiplier
|
||
);
|
||
}
|
||
|
||
public override void OnInterrupt(FeedbackContext context)
|
||
{
|
||
MMCinemachinePositionShakeEvent.Trigger(
|
||
null, shakeCurve, 0f, Vector3.zero, 0f,
|
||
stop: true
|
||
);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 计算距离衰减系数。
|
||
/// </summary>
|
||
private float ComputeAttenuation(FeedbackContext context)
|
||
{
|
||
if (!useAttenuation || context.owner == null) return 1f;
|
||
|
||
Camera mainCamera = Camera.main;
|
||
if (mainCamera == null) return 1f;
|
||
|
||
float distance = Vector3.Distance(context.owner.position, mainCamera.transform.position);
|
||
float normalizedDistance = Mathf.Clamp01(distance / attenuationRange);
|
||
return attenuationCurve.Evaluate(normalizedDistance);
|
||
}
|
||
}
|
||
}
|