狗屎Minimax坏我代码
This commit is contained in:
@@ -0,0 +1,151 @@
|
||||
using System.Collections.Generic;
|
||||
using SLSUtilities.Feedback;
|
||||
using Unity.Cinemachine;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Cielonos.MainGame.Effects.Feedback
|
||||
{
|
||||
/// <summary>
|
||||
/// 单个FOV震动实例的运行时状态。
|
||||
/// </summary>
|
||||
public class CameraFovShakeInstance : ShakeInstanceBase
|
||||
{
|
||||
public FloatCurveChannel fovCurve;
|
||||
|
||||
public CameraFovShakeInstance(FeedbackTimeSettings timeSettings, IFeedbackTimeProvider timeProvider,
|
||||
FloatCurveChannel fovCurve, float duration) : base(timeSettings, timeProvider, duration)
|
||||
{
|
||||
this.fovCurve = fovCurve;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 摄像机视野角(FOV)震动事件,用于解耦 Action 与 Shaker。
|
||||
/// </summary>
|
||||
public struct CameraFovShakeEvent
|
||||
{
|
||||
private static event ShakeDelegate OnEvent;
|
||||
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
|
||||
private static void RuntimeInitialization() { OnEvent = null; }
|
||||
|
||||
public delegate void ShakeDelegate(
|
||||
FeedbackContext feedbackContext,
|
||||
FloatCurveChannel fovCurve,
|
||||
bool stop
|
||||
);
|
||||
|
||||
public static void Register(ShakeDelegate callback) { OnEvent += callback; }
|
||||
public static void Unregister(ShakeDelegate callback) { OnEvent -= callback; }
|
||||
|
||||
public static void Trigger(
|
||||
FeedbackContext feedbackContext,
|
||||
FloatCurveChannel fovCurve,
|
||||
bool stop = false)
|
||||
{
|
||||
OnEvent?.Invoke(feedbackContext, fovCurve, stop);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// CinemachineCamera FOV 震动聚合器。挂载于 CinemachineCamera 上,
|
||||
/// 监听 CameraFovShakeEvent,叠加驱动 Lens.FieldOfView。
|
||||
/// </summary>
|
||||
[AddComponentMenu("Cielonos/Feedback Shakers/Camera FOV Shaker")]
|
||||
[RequireComponent(typeof(CinemachineCamera))]
|
||||
public class CameraFovShaker : MonoBehaviour
|
||||
{
|
||||
private CinemachineCamera _camera;
|
||||
private float _initialFov;
|
||||
private readonly List<CameraFovShakeInstance> _activeShakes = new List<CameraFovShakeInstance>();
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_camera = GetComponent<CinemachineCamera>();
|
||||
_initialFov = _camera.Lens.FieldOfView;
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
CameraFovShakeEvent.Register(OnShakeEvent);
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
CameraFovShakeEvent.Unregister(OnShakeEvent);
|
||||
StopAll();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (_camera == null) return;
|
||||
|
||||
if (_activeShakes.Count == 0)
|
||||
{
|
||||
SetFov(_initialFov);
|
||||
return;
|
||||
}
|
||||
|
||||
float additiveFov = 0f;
|
||||
float absoluteFov = 0f;
|
||||
bool hasAbsolute = false;
|
||||
|
||||
for (int i = _activeShakes.Count - 1; i >= 0; i--)
|
||||
{
|
||||
CameraFovShakeInstance shake = _activeShakes[i];
|
||||
shake.Tick();
|
||||
float normalizedTime = shake.timer / shake.duration;
|
||||
|
||||
if (shake.fovCurve.relativeToInitial)
|
||||
{
|
||||
additiveFov += shake.fovCurve.Evaluate(normalizedTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
absoluteFov = shake.fovCurve.Evaluate(normalizedTime);
|
||||
hasAbsolute = true;
|
||||
}
|
||||
|
||||
if (shake.IsFinished)
|
||||
{
|
||||
_activeShakes.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
float finalFov = hasAbsolute ? absoluteFov : _initialFov + additiveFov;
|
||||
SetFov(finalFov);
|
||||
}
|
||||
|
||||
private void OnShakeEvent(
|
||||
FeedbackContext feedbackContext,
|
||||
FloatCurveChannel fovCurve,
|
||||
bool stop)
|
||||
{
|
||||
if (stop) { StopAll(); return; }
|
||||
|
||||
var instance = new CameraFovShakeInstance(
|
||||
feedbackContext.timeSettings,
|
||||
feedbackContext.player.TimeProvider,
|
||||
fovCurve,
|
||||
feedbackContext.duration
|
||||
);
|
||||
_activeShakes.Add(instance);
|
||||
}
|
||||
|
||||
private void SetFov(float fov)
|
||||
{
|
||||
LensSettings lens = _camera.Lens;
|
||||
lens.FieldOfView = fov;
|
||||
_camera.Lens = lens;
|
||||
}
|
||||
|
||||
private void StopAll()
|
||||
{
|
||||
_activeShakes.Clear();
|
||||
if (_camera != null)
|
||||
{
|
||||
SetFov(_initialFov);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dbbfef1d7cc479c47837ff154e4a7c5e
|
||||
@@ -0,0 +1,153 @@
|
||||
using System.Collections.Generic;
|
||||
using SLSUtilities.Feedback;
|
||||
using Unity.Cinemachine;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Cielonos.MainGame.Effects.Feedback
|
||||
{
|
||||
/// <summary>
|
||||
/// 单个位移震动实例的运行时状态。
|
||||
/// </summary>
|
||||
public class CameraPositionShakeInstance : ShakeInstanceBase
|
||||
{
|
||||
public FloatCurveChannel intensityCurve;
|
||||
public Vector3 amplitude;
|
||||
|
||||
public CameraPositionShakeInstance(
|
||||
FeedbackTimeSettings timeSettings,
|
||||
IFeedbackTimeProvider timeProvider,
|
||||
FloatCurveChannel intensityCurve,
|
||||
Vector3 amplitude,
|
||||
float duration)
|
||||
: base(timeSettings, timeProvider, duration)
|
||||
{
|
||||
this.intensityCurve = intensityCurve;
|
||||
this.amplitude = amplitude;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算当前帧的偏移量。
|
||||
/// </summary>
|
||||
public Vector3 Evaluate()
|
||||
{
|
||||
float normalizedTime = duration > 0 ? timer / duration : 1f;
|
||||
float curveValue = intensityCurve.Evaluate(normalizedTime);
|
||||
return amplitude * curveValue;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 摄像机位移震动事件,用于解耦 Action 与 Shaker。
|
||||
/// </summary>
|
||||
public struct CameraPositionShakeEvent
|
||||
{
|
||||
private static event ShakeDelegate OnEvent;
|
||||
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
|
||||
private static void RuntimeInitialization() { OnEvent = null; }
|
||||
|
||||
public delegate void ShakeDelegate(
|
||||
FeedbackContext feedbackContext,
|
||||
FloatCurveChannel intensityCurve,
|
||||
Vector3 amplitude,
|
||||
bool stop
|
||||
);
|
||||
|
||||
public static void Register(ShakeDelegate callback) { OnEvent += callback; }
|
||||
public static void Unregister(ShakeDelegate callback) { OnEvent -= callback; }
|
||||
|
||||
public static void Trigger(
|
||||
FeedbackContext feedbackContext,
|
||||
FloatCurveChannel intensityCurve,
|
||||
Vector3 amplitude,
|
||||
bool stop = false)
|
||||
{
|
||||
OnEvent?.Invoke(feedbackContext, intensityCurve, amplitude, stop);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cinemachine 位移震动器。挂载于 CinemachineCamera 上,
|
||||
/// 监听 CameraPositionShakeEvent,驱动 CinemachineCameraOffset 实现叠加震动。
|
||||
/// </summary>
|
||||
[AddComponentMenu("Cielonos/Feedback Shakers/Camera Position Shaker")]
|
||||
[RequireComponent(typeof(CinemachineCamera))]
|
||||
[RequireComponent(typeof(CinemachineCameraOffset))]
|
||||
public class CinemachinePositionShaker : MonoBehaviour
|
||||
{
|
||||
private CinemachineCameraOffset _offsetComponent;
|
||||
private Vector3 _initialOffset;
|
||||
private readonly List<CameraPositionShakeInstance> _activeShakes = new List<CameraPositionShakeInstance>();
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_offsetComponent = GetComponent<CinemachineCameraOffset>();
|
||||
_initialOffset = _offsetComponent.Offset;
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
CameraPositionShakeEvent.Register(OnShakeEvent);
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
CameraPositionShakeEvent.Unregister(OnShakeEvent);
|
||||
StopAll();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (_offsetComponent == null) return;
|
||||
|
||||
if (_activeShakes.Count == 0)
|
||||
{
|
||||
_offsetComponent.Offset = _initialOffset;
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3 totalOffset = Vector3.zero;
|
||||
|
||||
for (int i = _activeShakes.Count - 1; i >= 0; i--)
|
||||
{
|
||||
CameraPositionShakeInstance shake = _activeShakes[i];
|
||||
shake.Tick();
|
||||
totalOffset += shake.Evaluate();
|
||||
|
||||
if (shake.IsFinished)
|
||||
{
|
||||
_activeShakes.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
_offsetComponent.Offset = _initialOffset + totalOffset;
|
||||
}
|
||||
|
||||
private void OnShakeEvent(
|
||||
FeedbackContext feedbackContext,
|
||||
FloatCurveChannel intensityCurve,
|
||||
Vector3 amplitude,
|
||||
bool stop)
|
||||
{
|
||||
if (stop) { StopAll(); return; }
|
||||
|
||||
var instance = new CameraPositionShakeInstance(
|
||||
feedbackContext.timeSettings,
|
||||
feedbackContext.player.TimeProvider,
|
||||
intensityCurve,
|
||||
amplitude,
|
||||
feedbackContext.duration
|
||||
);
|
||||
_activeShakes.Add(instance);
|
||||
}
|
||||
|
||||
private void StopAll()
|
||||
{
|
||||
_activeShakes.Clear();
|
||||
if (_offsetComponent != null)
|
||||
{
|
||||
_offsetComponent.Offset = _initialOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 08a7d10a0525af448902b60235ecf4fc
|
||||
@@ -0,0 +1,153 @@
|
||||
using System.Collections.Generic;
|
||||
using SLSUtilities.Cinemachine;
|
||||
using SLSUtilities.Feedback;
|
||||
using Unity.Cinemachine;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Cielonos.MainGame.Effects.Feedback
|
||||
{
|
||||
/// <summary>
|
||||
/// 单个旋转震动实例的运行时状态。
|
||||
/// </summary>
|
||||
public class CameraRotationShakeInstance : ShakeInstanceBase
|
||||
{
|
||||
public FloatCurveChannel intensityCurve;
|
||||
public Vector3 amplitude;
|
||||
|
||||
public CameraRotationShakeInstance(
|
||||
FeedbackTimeSettings timeSettings,
|
||||
IFeedbackTimeProvider timeProvider,
|
||||
FloatCurveChannel intensityCurve,
|
||||
Vector3 amplitude,
|
||||
float duration)
|
||||
: base(timeSettings, timeProvider, duration)
|
||||
{
|
||||
this.intensityCurve = intensityCurve;
|
||||
this.amplitude = amplitude;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算当前帧的偏移量。
|
||||
/// </summary>
|
||||
public Vector3 Evaluate()
|
||||
{
|
||||
float normalizedTime = duration > 0 ? timer / duration : 1f;
|
||||
float curveValue = intensityCurve.Evaluate(normalizedTime);
|
||||
return amplitude * curveValue;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 摄像机旋转震动事件,用于解耦 Action 与 Shaker。
|
||||
/// </summary>
|
||||
public struct CameraRotationShakeEvent
|
||||
{
|
||||
private static event ShakeDelegate OnEvent;
|
||||
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
|
||||
private static void RuntimeInitialization() { OnEvent = null; }
|
||||
|
||||
public delegate void ShakeDelegate(
|
||||
FeedbackContext feedbackContext,
|
||||
FloatCurveChannel intensityCurve,
|
||||
Vector3 amplitude,
|
||||
bool stop
|
||||
);
|
||||
|
||||
public static void Register(ShakeDelegate callback) { OnEvent += callback; }
|
||||
public static void Unregister(ShakeDelegate callback) { OnEvent -= callback; }
|
||||
|
||||
public static void Trigger(
|
||||
FeedbackContext feedbackContext,
|
||||
FloatCurveChannel intensityCurve,
|
||||
Vector3 amplitude,
|
||||
bool stop = false)
|
||||
{
|
||||
OnEvent?.Invoke(feedbackContext, intensityCurve, amplitude, stop);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cinemachine 旋转震动器。挂载于 CinemachineCamera 上,
|
||||
/// 监听 CameraRotationShakeEvent,驱动 CinemachineRotationOffset 实现叠加震动。
|
||||
/// X/Y 作用于 FollowTarget 旋转,Z 作用于 Dutch 倾斜。
|
||||
/// </summary>
|
||||
[AddComponentMenu("Cielonos/Feedback Shakers/Camera Rotation Shaker")]
|
||||
[RequireComponent(typeof(CinemachineCamera))]
|
||||
[RequireComponent(typeof(CinemachineRotationOffset))]
|
||||
public class CinemachineRotationShaker : MonoBehaviour
|
||||
{
|
||||
private CinemachineRotationOffset _rotationOffset;
|
||||
private Vector3 _initialRotation;
|
||||
private readonly List<CameraRotationShakeInstance> _activeShakes = new List<CameraRotationShakeInstance>();
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_rotationOffset = GetComponent<CinemachineRotationOffset>();
|
||||
_initialRotation = _rotationOffset.rotationOffset;
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
CameraRotationShakeEvent.Register(OnShakeEvent);
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
CameraRotationShakeEvent.Unregister(OnShakeEvent);
|
||||
StopAll();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (_rotationOffset == null) return;
|
||||
|
||||
if (_activeShakes.Count == 0)
|
||||
{
|
||||
_rotationOffset.rotationOffset = _initialRotation;
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3 totalOffset = Vector3.zero;
|
||||
|
||||
for (int i = _activeShakes.Count - 1; i >= 0; i--)
|
||||
{
|
||||
CameraRotationShakeInstance shake = _activeShakes[i];
|
||||
shake.Tick();
|
||||
totalOffset += shake.Evaluate();
|
||||
|
||||
if (shake.IsFinished)
|
||||
{
|
||||
_activeShakes.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
_rotationOffset.rotationOffset = _initialRotation + totalOffset;
|
||||
}
|
||||
|
||||
private void OnShakeEvent(
|
||||
FeedbackContext feedbackContext,
|
||||
FloatCurveChannel intensityCurve,
|
||||
Vector3 amplitude,
|
||||
bool stop)
|
||||
{
|
||||
if (stop) { StopAll(); return; }
|
||||
_activeShakes.Add(new CameraRotationShakeInstance(
|
||||
feedbackContext.timeSettings,
|
||||
feedbackContext.player.TimeProvider,
|
||||
intensityCurve,
|
||||
amplitude,
|
||||
feedbackContext.duration
|
||||
));
|
||||
}
|
||||
|
||||
private void StopAll()
|
||||
{
|
||||
_activeShakes.Clear();
|
||||
if (_rotationOffset != null)
|
||||
{
|
||||
_rotationOffset.rotationOffset = _initialRotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5c54de88d6cf4304180fbd641401b1b6
|
||||
Reference in New Issue
Block a user