using System; using MoreMountains.FeedbacksForThirdParty; using Sirenix.OdinInspector; using SLSUtilities.Feedback; using UnityEngine; namespace Cielonos.MainGame.Effects.Feedback { /// /// 摄像机旋转震动反馈,通过 MMCinemachineRotationShakeEvent 触发现有的 Shaker。 /// X/Y 作用于 FollowTarget 旋转,Z 作用于 Dutch 倾斜。 /// [Serializable] public class CameraRotationShakeAction : FeedbackActionBase { public override string DisplayName => "Camera Rotation Shake"; /// /// 震动曲线,定义震动强度随时间的变化。 /// [Title("Rotation Shake")] [LabelText("Shake Curve")] public AnimationCurve shakeCurve = new AnimationCurve( new Keyframe(0f, 0f), new Keyframe(0.2f, 1f), new Keyframe(1f, 0f) ); /// /// 最大旋转角度振幅(度)。X/Y -> FollowTarget, Z -> Dutch。 /// [LabelText("Rotation Amplitude")] public Vector3 rotationAmplitude = new Vector3(2f, 2f, 5f); /// /// 方向影响设置。 /// [Title("Direction")] public CameraDirectionSettings directionSettings = new CameraDirectionSettings(); /// /// 距离衰减。 /// [Title("Distance Attenuation")] [LabelText("Use Attenuation")] public bool useAttenuation; [ShowIf("useAttenuation")] [LabelText("Attenuation Range")] public float attenuationRange = 50f; [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(rotationAmplitude, context.owner); float intensityMultiplier = ComputeAttenuation(context); MMCinemachineRotationShakeEvent.Trigger( null, shakeCurve, context.duration, finalAmplitude, 0f, 1f, false, intensityMultiplier ); } public override void OnInterrupt(FeedbackContext context) { MMCinemachineRotationShakeEvent.Trigger( null, shakeCurve, 0f, Vector3.zero, 0f, 1f, false, 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); } } }