2026-04-18 13:57:19 -04:00
|
|
|
|
using System;
|
|
|
|
|
|
using Sirenix.OdinInspector;
|
|
|
|
|
|
using SLSUtilities.Feedback;
|
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
|
|
|
|
|
|
namespace Cielonos.MainGame.Effects.Feedback
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 摄像机旋转震动反馈,通过 CameraRotationShakeEvent 触发 CinemachineRotationShaker。
|
|
|
|
|
|
/// X/Y 作用于 FollowTarget 旋转,Z 作用于 Dutch 倾斜。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[Serializable]
|
|
|
|
|
|
[FeedbackActionColor(0.3f, 0.7f, 0.3f)]
|
|
|
|
|
|
public class CameraRotationShakeAction : CinemachineActionBase
|
|
|
|
|
|
{
|
|
|
|
|
|
public override string DisplayName => "Camera Rotation Shake";
|
|
|
|
|
|
|
|
|
|
|
|
public Vector3 amplitude;
|
|
|
|
|
|
|
2026-04-28 15:46:32 -04:00
|
|
|
|
public FloatCurveChannel intensityCurve = FloatCurveChannel.CreateDefault();
|
2026-04-18 13:57:19 -04:00
|
|
|
|
|
|
|
|
|
|
public CameraDirectionSettings directionSettings = new CameraDirectionSettings();
|
|
|
|
|
|
|
|
|
|
|
|
[TitleGroup("距离衰减")]
|
|
|
|
|
|
[LabelText("启用衰减")]
|
|
|
|
|
|
public bool useAttenuation;
|
|
|
|
|
|
|
|
|
|
|
|
[ShowIf("useAttenuation")]
|
|
|
|
|
|
[LabelText("衰减范围")]
|
|
|
|
|
|
public float attenuationRange = 50f;
|
|
|
|
|
|
|
|
|
|
|
|
[ShowIf("useAttenuation")]
|
|
|
|
|
|
[LabelText("衰减曲线")]
|
|
|
|
|
|
public AnimationCurve attenuationCurve = new AnimationCurve(
|
|
|
|
|
|
new Keyframe(0f, 1f),
|
|
|
|
|
|
new Keyframe(1f, 0f)
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
protected override void TriggerEvent(FeedbackContext context)
|
|
|
|
|
|
{
|
|
|
|
|
|
Vector3 finalAmplitude = directionSettings.TransformAmplitude(amplitude, context.owner);
|
2026-04-28 15:46:32 -04:00
|
|
|
|
float attenuation = ComputeAttenuation(context);
|
|
|
|
|
|
CameraRotationShakeEvent.Trigger(context, intensityCurve, finalAmplitude * attenuation);
|
2026-04-18 13:57:19 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override void StopEvent(FeedbackContext context)
|
|
|
|
|
|
{
|
|
|
|
|
|
CameraRotationShakeEvent.Trigger(context, intensityCurve, Vector3.zero, 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);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public override bool Validate(out string error)
|
|
|
|
|
|
{
|
|
|
|
|
|
error = null;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|