175 lines
6.2 KiB
C#
175 lines
6.2 KiB
C#
using UnityEngine;
|
|
using MoreMountains.Feedbacks;
|
|
using MoreMountains.Tools;
|
|
using Unity.Cinemachine;
|
|
using System.Collections.Generic;
|
|
|
|
namespace MoreMountains.FeedbacksForThirdParty
|
|
{
|
|
// 定义一个类来保存单个震动实例的状态
|
|
public class MMCinemachinePositionShakeInstance
|
|
{
|
|
public float Duration;
|
|
public float Timer;
|
|
public Vector3 Amplitude;
|
|
public AnimationCurve Curve;
|
|
public float Intensity;
|
|
public TimescaleModes TimescaleMode;
|
|
|
|
public MMCinemachinePositionShakeInstance(float duration, Vector3 amplitude, AnimationCurve curve, float intensity, TimescaleModes timescaleMode)
|
|
{
|
|
Duration = duration;
|
|
Timer = 0f;
|
|
Amplitude = amplitude;
|
|
Curve = curve;
|
|
Intensity = intensity;
|
|
TimescaleMode = timescaleMode;
|
|
}
|
|
}
|
|
|
|
[AddComponentMenu("More Mountains/Feedbacks/Shakers/Cinemachine/MM Cinemachine Position Shaker (Additive)")]
|
|
[RequireComponent(typeof(CinemachineCamera))]
|
|
[RequireComponent(typeof(CinemachineCameraOffset))] // 确保有 Offset 组件
|
|
public class MMCinemachinePositionShaker : MMShaker
|
|
{
|
|
[MMInspectorGroup("Debug Info", true, 43)]
|
|
[MMReadOnly]
|
|
public int ActiveShakesCount = 0; // 仅用于监视当前有多少个震动在叠加
|
|
|
|
protected CinemachineCamera _cmCamera;
|
|
protected CinemachineCameraOffset _positionOffset;
|
|
protected Vector3 _initialOffset;
|
|
|
|
// 维护一个活跃震动的列表
|
|
protected List<MMCinemachinePositionShakeInstance> _activeShakes = new List<MMCinemachinePositionShakeInstance>();
|
|
|
|
protected override void Initialization()
|
|
{
|
|
// 注意:我们不调用 base.Initialization(),因为我们不想使用 MMShaker 默认的 Event 监听逻辑,
|
|
// 我们需要完全接管 Shake 的逻辑来实现叠加。
|
|
// 但为了兼容性,如果 Feel 内部有依赖,可以保留,但这里主要逻辑是自定义的。
|
|
_cmCamera = GetComponent<CinemachineCamera>();
|
|
_positionOffset = GetComponent<CinemachineCameraOffset>();
|
|
GrabInitialValues();
|
|
}
|
|
|
|
protected override void GrabInitialValues()
|
|
{
|
|
if (_positionOffset != null)
|
|
{
|
|
_initialOffset = _positionOffset.Offset;
|
|
}
|
|
}
|
|
|
|
// 我们重写 Update 来处理叠加逻辑
|
|
protected override void Update()
|
|
{
|
|
if (_positionOffset == null) return;
|
|
|
|
// 如果没有活跃的震动,且当前不是初始位置,则复位(可选,作为保险)
|
|
if (_activeShakes.Count == 0)
|
|
{
|
|
Stop();
|
|
return;
|
|
}
|
|
|
|
Vector3 totalShakeOffset = Vector3.zero;
|
|
|
|
// 倒序遍历以便安全移除
|
|
for (int i = _activeShakes.Count - 1; i >= 0; i--)
|
|
{
|
|
var shake = _activeShakes[i];
|
|
|
|
// 更新时间
|
|
float deltaTime = (shake.TimescaleMode == TimescaleModes.Scaled) ? Time.deltaTime : Time.unscaledDeltaTime;
|
|
shake.Timer += deltaTime;
|
|
|
|
// 计算进度 (0 到 1)
|
|
float percent = Mathf.Clamp01(shake.Timer / shake.Duration);
|
|
|
|
// 采样曲线并计算位移
|
|
float curveValue = shake.Curve.Evaluate(percent);
|
|
Vector3 currentOffset = shake.Amplitude * curveValue * shake.Intensity;
|
|
|
|
// 叠加
|
|
totalShakeOffset += currentOffset;
|
|
|
|
// 如果结束,移除
|
|
if (shake.Timer >= shake.Duration)
|
|
{
|
|
_activeShakes.RemoveAt(i);
|
|
}
|
|
}
|
|
|
|
// 应用叠加后的总偏移量 + 初始偏移量
|
|
_positionOffset.Offset = _initialOffset + totalShakeOffset;
|
|
//Debug.Log($"Total Shake Offset Applied: {totalShakeOffset}");
|
|
|
|
// 更新 Debug 计数
|
|
ActiveShakesCount = _activeShakes.Count;
|
|
|
|
// 如果所有震动都结束了,强制归位以消除浮点误差
|
|
if (_activeShakes.Count == 0)
|
|
{
|
|
_positionOffset.Offset = _initialOffset;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 接收事件
|
|
/// </summary>
|
|
public virtual void OnPositionShakeEvent(MMF_Feedback source, AnimationCurve shakeCurve, float duration, Vector3 positionAmplitude,
|
|
float feedbacksIntensity = 1.0f, MMChannelData channelData = null, bool resetShakerValuesAfterShake = true,
|
|
bool resetTargetValuesAfterShake = true, bool forwardDirection = true, TimescaleModes timescaleMode = TimescaleModes.Scaled, bool stop = false)
|
|
{
|
|
if (!CheckEventAllowed(channelData)) return;
|
|
|
|
if (stop)
|
|
{
|
|
Stop();
|
|
return;
|
|
}
|
|
|
|
// 创建新的震动实例并添加到列表
|
|
MMCinemachinePositionShakeInstance newShake = new MMCinemachinePositionShakeInstance(
|
|
duration,
|
|
positionAmplitude,
|
|
shakeCurve,
|
|
feedbacksIntensity,
|
|
timescaleMode
|
|
);
|
|
|
|
_activeShakes.Add(newShake);
|
|
Play(source);
|
|
}
|
|
|
|
// 强制停止所有震动
|
|
public override void Stop()
|
|
{
|
|
_activeShakes.Clear();
|
|
if (_positionOffset != null)
|
|
{
|
|
_positionOffset.Offset = _initialOffset;
|
|
}
|
|
}
|
|
|
|
protected override void ResetTargetValues()
|
|
{
|
|
base.ResetTargetValues();
|
|
Stop();
|
|
}
|
|
|
|
public override void StartListening()
|
|
{
|
|
// 注意:这里我们依然使用基类的注册机制,或者直接在这里注册
|
|
base.StartListening();
|
|
MMCinemachinePositionShakeEvent.Register(OnPositionShakeEvent);
|
|
}
|
|
|
|
public override void StopListening()
|
|
{
|
|
base.StopListening();
|
|
MMCinemachinePositionShakeEvent.Unregister(OnPositionShakeEvent);
|
|
}
|
|
}
|
|
} |