Files
ichni_Creator_Studio/Assets/Feel/MMFeedbacks/MMFeedbacks/Shakers/MMCameraShaker.cs
SoulliesOfficial 8d0abec75f 基础内容
必要插件安装
缓动曲线和动画基础
ElementFolder,Track与其次级模块,PathNode重构
2025-01-26 21:10:16 -05:00

183 lines
8.4 KiB
C#

using UnityEngine;
using System;
using MoreMountains.Tools;
namespace MoreMountains.Feedbacks
{
[Serializable]
/// <summary>
/// Camera shake properties
/// </summary>
public struct MMCameraShakeProperties
{
public float Duration;
public float Amplitude;
public float Frequency;
public float AmplitudeX;
public float AmplitudeY;
public float AmplitudeZ;
public MMCameraShakeProperties(float duration, float amplitude, float frequency, float amplitudeX = 0f, float amplitudeY = 0f, float amplitudeZ = 0f)
{
Duration = duration;
Amplitude = amplitude;
Frequency = frequency;
AmplitudeX = amplitudeX;
AmplitudeY = amplitudeY;
AmplitudeZ = amplitudeZ;
}
}
public enum MMCameraZoomModes { For, Set, Reset }
public struct MMCameraZoomEvent
{
static private event Delegate OnEvent;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] private static void RuntimeInitialization() { OnEvent = null; }
static public void Register(Delegate callback) { OnEvent += callback; }
static public void Unregister(Delegate callback) { OnEvent -= callback; }
public delegate void Delegate(MMCameraZoomModes mode, float newFieldOfView, float transitionDuration, float duration, MMChannelData channelData, bool useUnscaledTime = false, bool stop = false, bool relative = false, bool restore = false, MMTweenType tweenType = null);
static public void Trigger(MMCameraZoomModes mode, float newFieldOfView, float transitionDuration, float duration, MMChannelData channelData, bool useUnscaledTime = false, bool stop = false, bool relative = false, bool restore = false, MMTweenType tweenType = null)
{
OnEvent?.Invoke(mode, newFieldOfView, transitionDuration, duration, channelData, useUnscaledTime, stop, relative, restore, tweenType);
}
}
public struct MMCameraShakeEvent
{
static private event Delegate OnEvent;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] private static void RuntimeInitialization() { OnEvent = null; }
static public void Register(Delegate callback) { OnEvent += callback; }
static public void Unregister(Delegate callback) { OnEvent -= callback; }
public delegate void Delegate(float duration, float amplitude, float frequency, float amplitudeX, float amplitudeY, float amplitudeZ, bool infinite = false, MMChannelData channelData = null, bool useUnscaledTime = false);
static public void Trigger(float duration, float amplitude, float frequency, float amplitudeX, float amplitudeY, float amplitudeZ, bool infinite = false, MMChannelData channelData = null, bool useUnscaledTime = false)
{
OnEvent?.Invoke(duration, amplitude, frequency, amplitudeX, amplitudeY, amplitudeZ, infinite, channelData, useUnscaledTime);
}
}
public struct MMCameraShakeStopEvent
{
static private event Delegate OnEvent;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] private static void RuntimeInitialization() { OnEvent = null; }
static public void Register(Delegate callback) { OnEvent += callback; }
static public void Unregister(Delegate callback) { OnEvent -= callback; }
public delegate void Delegate(MMChannelData channelData);
static public void Trigger(MMChannelData channelData)
{
OnEvent?.Invoke(channelData);
}
}
[RequireComponent(typeof(MMWiggle))]
[AddComponentMenu("More Mountains/Feedbacks/Shakers/Camera/MMCameraShaker")]
/// <summary>
/// A class to add to your camera. It'll listen to MMCameraShakeEvents and will shake your camera accordingly
/// </summary>
public class MMCameraShaker : MonoBehaviour
{
/// whether to listen on a channel defined by an int or by a MMChannel scriptable object. Ints are simple to setup but can get messy and make it harder to remember what int corresponds to what.
/// MMChannel scriptable objects require you to create them in advance, but come with a readable name and are more scalable
[Tooltip("whether to listen on a channel defined by an int or by a MMChannel scriptable object. Ints are simple to setup but can get messy and make it harder to remember what int corresponds to what. " +
"MMChannel scriptable objects require you to create them in advance, but come with a readable name and are more scalable")]
public MMChannelModes ChannelMode = MMChannelModes.Int;
/// the channel to listen to - has to match the one on the feedback
[Tooltip("the channel to listen to - has to match the one on the feedback")]
[MMEnumCondition("ChannelMode", (int)MMChannelModes.Int)]
public int Channel = 0;
/// the MMChannel definition asset to use to listen for events. The feedbacks targeting this shaker will have to reference that same MMChannel definition to receive events - to create a MMChannel,
/// right click anywhere in your project (usually in a Data folder) and go MoreMountains > MMChannel, then name it with some unique name
[Tooltip("the MMChannel definition asset to use to listen for events. The feedbacks targeting this shaker will have to reference that same MMChannel definition to receive events - to create a MMChannel, " +
"right click anywhere in your project (usually in a Data folder) and go MoreMountains > MMChannel, then name it with some unique name")]
[MMEnumCondition("ChannelMode", (int)MMChannelModes.MMChannel)]
public MMChannel MMChannelDefinition = null;
/// a cooldown, in seconds, after a shake, during which no other shake can start
[Tooltip("a cooldown, in seconds, after a shake, during which no other shake can start")]
public float CooldownBetweenShakes = 0f;
protected MMWiggle _wiggle;
protected float _shakeStartedTimestamp = -Single.MaxValue;
/// <summary>
/// On Awake, grabs the MMShaker component
/// </summary>
protected virtual void Awake()
{
_wiggle = GetComponent<MMWiggle>();
}
/// <summary>
/// Shakes the camera for Duration seconds, by the desired amplitude and frequency
/// </summary>
/// <param name="duration">Duration.</param>
/// <param name="amplitude">Amplitude.</param>
/// <param name="frequency">Frequency.</param>
public virtual void ShakeCamera(float duration, float amplitude, float frequency, float amplitudeX, float amplitudeY, float amplitudeZ, bool useUnscaledTime)
{
if (Time.unscaledTime - _shakeStartedTimestamp < CooldownBetweenShakes)
{
return;
}
if ((amplitudeX != 0f) || (amplitudeY != 0f) || (amplitudeZ != 0f))
{
_wiggle.PositionWiggleProperties.AmplitudeMin.x = -amplitudeX;
_wiggle.PositionWiggleProperties.AmplitudeMin.y = -amplitudeY;
_wiggle.PositionWiggleProperties.AmplitudeMin.z = -amplitudeZ;
_wiggle.PositionWiggleProperties.AmplitudeMax.x = amplitudeX;
_wiggle.PositionWiggleProperties.AmplitudeMax.y = amplitudeY;
_wiggle.PositionWiggleProperties.AmplitudeMax.z = amplitudeZ;
}
else
{
_wiggle.PositionWiggleProperties.AmplitudeMin = Vector3.one * -amplitude;
_wiggle.PositionWiggleProperties.AmplitudeMax = Vector3.one * amplitude;
}
_shakeStartedTimestamp = Time.unscaledTime;
_wiggle.PositionWiggleProperties.UseUnscaledTime = useUnscaledTime;
_wiggle.PositionWiggleProperties.FrequencyMin = frequency;
_wiggle.PositionWiggleProperties.FrequencyMax = frequency;
_wiggle.PositionWiggleProperties.NoiseFrequencyMin = frequency * Vector3.one;
_wiggle.PositionWiggleProperties.NoiseFrequencyMax = frequency * Vector3.one;
_wiggle.WigglePosition(duration);
}
/// <summary>
/// When a MMCameraShakeEvent is caught, shakes the camera
/// </summary>
/// <param name="shakeEvent">Shake event.</param>
public virtual void OnCameraShakeEvent(float duration, float amplitude, float frequency, float amplitudeX, float amplitudeY, float amplitudeZ, bool infinite, MMChannelData channelData, bool useUnscaledTime)
{
if (!MMChannel.Match(channelData, ChannelMode, Channel, MMChannelDefinition))
{
return;
}
this.ShakeCamera (duration, amplitude, frequency, amplitudeX, amplitudeY, amplitudeZ, useUnscaledTime);
}
/// <summary>
/// On enable, starts listening for events
/// </summary>
protected virtual void OnEnable()
{
MMCameraShakeEvent.Register(OnCameraShakeEvent);
}
/// <summary>
/// On disable, stops listening to events
/// </summary>
protected virtual void OnDisable()
{
MMCameraShakeEvent.Unregister(OnCameraShakeEvent);
}
}
}