using System; using MoreMountains.Feedbacks; using Sirenix.OdinInspector; using SLSUtilities.Feedback; using UnityEngine; namespace Cielonos.MainGame.Effects.Feedback { /// /// 摄像机位移震动反馈,通过 MMCinemachinePositionShakeEvent 触发现有的 Shaker。 /// Shaker 负责处理多个震动的叠加混合。 /// [Serializable] public class CameraPositionShakeAction : FeedbackActionBase { public override string DisplayName => "Camera Position Shake"; /// /// 震动曲线,定义震动强度随时间的变化。 /// [Title("Position Shake")] [LabelText("Shake Curve")] public AnimationCurve shakeCurve = new AnimationCurve( new Keyframe(0f, 0f), new Keyframe(0.2f, 1f), new Keyframe(1f, 0f) ); /// /// 最大位移振幅(本地空间)。 /// [LabelText("Amplitude")] public Vector3 positionAmplitude = new Vector3(0.5f, 0.5f, 0f); /// /// 方向影响设置。 /// [Title("Direction")] public CameraDirectionSettings directionSettings = new CameraDirectionSettings(); /// /// 距离衰减:根据摄像机与 owner 的距离衰减震动强度。 /// [Title("Distance Attenuation")] [LabelText("Use Attenuation")] public bool useAttenuation; /// /// 全强度的最大距离。 /// [ShowIf("useAttenuation")] [LabelText("Attenuation Range")] public float attenuationRange = 50f; /// /// 距离-强度衰减曲线(0=近处/全强度,1=远处/无强度)。 /// [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 ); } /// /// 计算距离衰减系数。 /// 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); } } }