191 lines
7.5 KiB
C#
191 lines
7.5 KiB
C#
using UnityEngine;
|
|
using MoreMountains.Feedbacks;
|
|
using MoreMountains.Tools;
|
|
#if MM_CINEMACHINE
|
|
using Cinemachine;
|
|
#elif MM_CINEMACHINE3
|
|
using Unity.Cinemachine;
|
|
#endif
|
|
|
|
namespace MoreMountains.FeedbacksForThirdParty
|
|
{
|
|
// 定义事件结构
|
|
public struct MMCameraRotationShakeEvent
|
|
{
|
|
static private event Delegate OnEvent;
|
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] private static void RuntimeInitialization() { OnEvent = null; }
|
|
public static void Register(Delegate callback) { OnEvent += callback; }
|
|
public static void Unregister(Delegate callback) { OnEvent -= callback; }
|
|
|
|
public delegate void Delegate(AnimationCurve shakeCurve, float duration, Vector3 rotationAmplitude, float remapMin, float remapMax, bool relative,
|
|
float feedbacksIntensity = 1.0f, MMChannelData channelData = null, bool resetShakerValuesAfterShake = true, bool resetTargetValuesAfterShake = true, bool forwardDirection = true, TimescaleModes timescaleMode = TimescaleModes.Scaled, bool stop = false, bool restore = false);
|
|
|
|
public static void Trigger(AnimationCurve shakeCurve, float duration, Vector3 rotationAmplitude, float remapMin, float remapMax, bool relative,
|
|
float feedbacksIntensity = 1.0f, MMChannelData channelData = null, bool resetShakerValuesAfterShake = true, bool resetTargetValuesAfterShake = true, bool forwardDirection = true, TimescaleModes timescaleMode = TimescaleModes.Scaled, bool stop = false, bool restore = false)
|
|
{
|
|
OnEvent?.Invoke(shakeCurve, duration, rotationAmplitude, remapMin, remapMax, relative, feedbacksIntensity, channelData, resetShakerValuesAfterShake, resetTargetValuesAfterShake, forwardDirection, timescaleMode, stop, restore);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Cinemachine Rotation Shaker
|
|
/// X/Y applied to FollowTarget, Z applied to Camera Dutch.
|
|
/// </summary>
|
|
[AddComponentMenu("More Mountains/Feedbacks/Shakers/Cinemachine/MM Cinemachine Rotation Shaker")]
|
|
#if MM_CINEMACHINE
|
|
[RequireComponent(typeof(CinemachineVirtualCamera))]
|
|
#elif MM_CINEMACHINE3
|
|
[RequireComponent(typeof(CinemachineCamera))]
|
|
#endif
|
|
public class MMCinemachineRotationShaker : MMShaker
|
|
{
|
|
public Transform FollowTarget => _targetCamera.Follow;
|
|
|
|
[MMInspectorGroup("Shake Settings", true, 42)]
|
|
public Vector3 ShakeRotationAmplitude = new Vector3(2f, 2f, 5f);
|
|
public AnimationCurve ShakeCurve = new AnimationCurve(new Keyframe(0, 0), new Keyframe(0.5f, 1), new Keyframe(1, 0));
|
|
|
|
[MMFInspectorButton("StartShaking")]
|
|
public bool TestShakeButton;
|
|
|
|
#if MM_CINEMACHINE
|
|
protected CinemachineVirtualCamera _targetCamera;
|
|
#elif MM_CINEMACHINE3
|
|
protected CinemachineCamera _targetCamera;
|
|
#endif
|
|
|
|
protected float _initialDutch;
|
|
protected Quaternion _initialTargetRotation;
|
|
|
|
// --- 修复点 1: 显式声明这些备份变量 ---
|
|
protected float _originalShakeDuration;
|
|
protected Vector3 _originalShakeRotationAmplitude;
|
|
protected AnimationCurve _originalShakeCurve;
|
|
|
|
protected override void Initialization()
|
|
{
|
|
base.Initialization();
|
|
#if MM_CINEMACHINE
|
|
_targetCamera = GetComponent<CinemachineVirtualCamera>();
|
|
#elif MM_CINEMACHINE3
|
|
_targetCamera = GetComponent<CinemachineCamera>();
|
|
#endif
|
|
}
|
|
|
|
protected override void GrabInitialValues()
|
|
{
|
|
if (_targetCamera != null)
|
|
{
|
|
#if MM_CINEMACHINE
|
|
_initialDutch = _targetCamera.m_Lens.Dutch;
|
|
#elif MM_CINEMACHINE3
|
|
_initialDutch = _targetCamera.Lens.Dutch;
|
|
#endif
|
|
}
|
|
|
|
if (FollowTarget != null)
|
|
{
|
|
_initialTargetRotation = FollowTarget.localRotation;
|
|
}
|
|
}
|
|
|
|
protected override void Shake()
|
|
{
|
|
// --- 修复点 2: 使用 ShakeFloat 代替手动 ShakeTime 计算 ---
|
|
// ShakeFloat 会自动处理时间、重映射和曲线计算
|
|
// 我们请求一个 0 到 1 之间的浮点数作为当前的“强度”
|
|
float intensity = ShakeFloat(ShakeCurve, 0f, 1f, false, 0f);
|
|
|
|
// 根据强度应用 XYZ
|
|
float xOffset = ShakeRotationAmplitude.x * intensity;
|
|
float yOffset = ShakeRotationAmplitude.y * intensity;
|
|
float zOffset = ShakeRotationAmplitude.z * intensity;
|
|
|
|
ApplyRotation(xOffset, yOffset, zOffset);
|
|
}
|
|
|
|
protected virtual void ApplyRotation(float x, float y, float z)
|
|
{
|
|
// Z -> Dutch
|
|
if (_targetCamera != null)
|
|
{
|
|
#if MM_CINEMACHINE
|
|
_targetCamera.m_Lens.Dutch = _initialDutch + z;
|
|
#elif MM_CINEMACHINE3
|
|
_targetCamera.Lens.Dutch = _initialDutch + z;
|
|
#endif
|
|
}
|
|
|
|
// X/Y -> FollowTarget
|
|
if (FollowTarget != null)
|
|
{
|
|
FollowTarget.localRotation = _initialTargetRotation * Quaternion.Euler(x, y, 0f);
|
|
}
|
|
}
|
|
|
|
protected override void ResetTargetValues()
|
|
{
|
|
base.ResetTargetValues();
|
|
ApplyRotation(0f, 0f, 0f);
|
|
}
|
|
|
|
protected override void ResetShakerValues()
|
|
{
|
|
base.ResetShakerValues();
|
|
// 恢复备份的值
|
|
ShakeDuration = _originalShakeDuration;
|
|
ShakeRotationAmplitude = _originalShakeRotationAmplitude;
|
|
ShakeCurve = _originalShakeCurve;
|
|
}
|
|
|
|
public virtual void OnMMCameraRotationShakeEvent(AnimationCurve shakeCurve, float duration, Vector3 rotationAmplitude, float remapMin, float remapMax, bool relative, float feedbacksIntensity = 1.0f, MMChannelData channelData = null, bool resetShakerValuesAfterShake = true, bool resetTargetValuesAfterShake = true, bool forwardDirection = true, TimescaleModes timescaleMode = TimescaleModes.Scaled, bool stop = false, bool restore = false)
|
|
{
|
|
if (!CheckEventAllowed(channelData)) return;
|
|
|
|
if (stop)
|
|
{
|
|
Stop();
|
|
return;
|
|
}
|
|
if (restore)
|
|
{
|
|
ResetTargetValues();
|
|
return;
|
|
}
|
|
|
|
if (!Interruptible && Shaking) return;
|
|
|
|
_resetShakerValuesAfterShake = resetShakerValuesAfterShake;
|
|
_resetTargetValuesAfterShake = resetTargetValuesAfterShake;
|
|
|
|
if (resetShakerValuesAfterShake)
|
|
{
|
|
// 备份当前值
|
|
_originalShakeDuration = ShakeDuration;
|
|
_originalShakeRotationAmplitude = ShakeRotationAmplitude;
|
|
_originalShakeCurve = ShakeCurve;
|
|
}
|
|
|
|
TimescaleMode = timescaleMode;
|
|
ShakeDuration = duration;
|
|
// 应用 Intensity
|
|
ShakeRotationAmplitude = rotationAmplitude * feedbacksIntensity;
|
|
ShakeCurve = shakeCurve;
|
|
ForwardDirection = forwardDirection;
|
|
|
|
Play();
|
|
}
|
|
|
|
public override void StartListening()
|
|
{
|
|
base.StartListening();
|
|
MMCameraRotationShakeEvent.Register(OnMMCameraRotationShakeEvent);
|
|
}
|
|
|
|
public override void StopListening()
|
|
{
|
|
base.StopListening();
|
|
MMCameraRotationShakeEvent.Unregister(OnMMCameraRotationShakeEvent);
|
|
}
|
|
}
|
|
} |