Upload from upload_mods.ps1

This commit is contained in:
Nathaniel Cosford
2025-06-04 16:13:32 +09:30
commit 7345f42201
470 changed files with 51966 additions and 0 deletions

View File

@@ -0,0 +1,66 @@
using UnityEngine;
namespace CameraShake
{
/// <summary>
/// Contains methods for changing strength and direction of shakes depending on their position.
/// </summary>
public static class Attenuator
{
/// <summary>
/// Returns multiplier for the strength of a shake, based on source and camera positions.
/// </summary>
public static float Strength(StrengthAttenuationParams pars, Vector3 sourcePosition, Vector3 cameraPosition)
{
Vector3 vec = cameraPosition - sourcePosition;
float distance = Vector3.Scale(pars.axesMultiplier, vec).magnitude;
float strength = Mathf.Clamp01(1 - (distance - pars.clippingDistance) / pars.falloffScale);
return Power.Evaluate(strength, pars.falloffDegree);
}
/// <summary>
/// Returns displacement, opposite to the direction to the source in camera's local space.
/// </summary>
public static Displacement Direction(Vector3 sourcePosition, Vector3 cameraPosition, Quaternion cameraRotation)
{
Displacement direction = Displacement.Zero;
direction.position = (cameraPosition - sourcePosition).normalized;
direction.position = Quaternion.Inverse(cameraRotation) * direction.position;
direction.eulerAngles.x = direction.position.z;
direction.eulerAngles.y = direction.position.x;
direction.eulerAngles.z = -direction.position.x;
return direction;
}
[System.Serializable]
public class StrengthAttenuationParams
{
/// <summary>
/// Radius in which shake doesn't lose strength.
/// </summary>
[Tooltip("Radius in which shake doesn't lose strength.")]
public float clippingDistance = 10;
/// <summary>
/// Defines how fast strength falls with distance.
/// </summary>
[Tooltip("How fast strength falls with distance.")]
public float falloffScale = 50;
/// <summary>
/// Power of the falloff function.
/// </summary>
[Tooltip("Power of the falloff function.")]
public Degree falloffDegree = Degree.Quadratic;
/// <summary>
/// Contribution of each axis to distance. E. g. (1, 1, 0) for a 2D game in XY plane.
/// </summary>
[Tooltip("Contribution of each axis to distance. E. g. (1, 1, 0) for a 2D game in XY plane.")]
public Vector3 axesMultiplier = Vector3.one;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 07aa6a8400d46274f9cbc5f3714e6a9b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,133 @@
using UnityEngine;
namespace CameraShake
{
public class BounceShake : ICameraShake
{
readonly Params pars;
readonly AnimationCurve moveCurve = AnimationCurve.EaseInOut(0, 0, 1, 1);
readonly Vector3? sourcePosition = null;
float attenuation = 1;
Displacement direction;
Displacement previousWaypoint;
Displacement currentWaypoint;
int bounceIndex;
float t;
/// <summary>
/// Creates an instance of BounceShake.
/// </summary>
/// <param name="parameters">Parameters of the shake.</param>
/// <param name="sourcePosition">World position of the source of the shake.</param>
public BounceShake(Params parameters, Vector3? sourcePosition = null)
{
this.sourcePosition = sourcePosition;
pars = parameters;
Displacement rnd = Displacement.InsideUnitSpheres();
direction = Displacement.Scale(rnd, pars.axesMultiplier).Normalized;
}
/// <summary>
/// Creates an instance of BounceShake.
/// </summary>
/// <param name="parameters">Parameters of the shake.</param>
/// <param name="initialDirection">Initial direction of the shake motion.</param>
/// <param name="sourcePosition">World position of the source of the shake.</param>
public BounceShake(Params parameters, Displacement initialDirection, Vector3? sourcePosition = null)
{
this.sourcePosition = sourcePosition;
pars = parameters;
direction = Displacement.Scale(initialDirection, pars.axesMultiplier).Normalized;
}
public Displacement CurrentDisplacement { get; private set; }
public bool IsFinished { get; private set; }
public void Initialize(Vector3 cameraPosition, Quaternion cameraRotation)
{
attenuation = sourcePosition == null ?
1 : Attenuator.Strength(pars.attenuation, sourcePosition.Value, cameraPosition);
currentWaypoint = attenuation * direction.ScaledBy(pars.positionStrength, pars.rotationStrength);
}
public void Update(float deltaTime, Vector3 cameraPosition, Quaternion cameraRotation)
{
if (t < 1)
{
t += deltaTime * pars.freq;
if (pars.freq == 0) t = 1;
CurrentDisplacement = Displacement.Lerp(previousWaypoint, currentWaypoint,
moveCurve.Evaluate(t));
}
else
{
t = 0;
CurrentDisplacement = currentWaypoint;
previousWaypoint = currentWaypoint;
bounceIndex++;
if (bounceIndex > pars.numBounces)
{
IsFinished = true;
return;
}
Displacement rnd = Displacement.InsideUnitSpheres();
direction = -direction
+ pars.randomness * Displacement.Scale(rnd, pars.axesMultiplier).Normalized;
direction = direction.Normalized;
float decayValue = 1 - (float)bounceIndex / pars.numBounces;
currentWaypoint = decayValue * decayValue * attenuation
* direction.ScaledBy(pars.positionStrength, pars.rotationStrength);
}
}
[System.Serializable]
public class Params
{
/// <summary>
/// Strength of the shake for positional axes.
/// </summary>
[Tooltip("Strength of the shake for positional axes.")]
public float positionStrength = 0.05f;
/// <summary>
/// Strength of the shake for rotational axes.
/// </summary>
[Tooltip("Strength of the shake for rotational axes.")]
public float rotationStrength = 0.1f;
/// <summary>
/// Preferred direction of shaking.
/// </summary>
[Tooltip("Preferred direction of shaking.")]
public Displacement axesMultiplier = new Displacement(Vector2.one, Vector3.forward);
/// <summary>
/// Frequency of shaking.
/// </summary>
[Tooltip("Frequency of shaking.")]
public float freq = 25;
/// <summary>
/// Number of vibrations before stop.
/// </summary>
[Tooltip("Number of vibrations before stop.")]
public int numBounces = 5;
/// <summary>
/// Randomness of motion.
/// </summary>
[Range(0, 1)]
[Tooltip("Randomness of motion.")]
public float randomness = 0.5f;
/// <summary>
/// How strength falls with distance from the shake source.
/// </summary>
[Tooltip("How strength falls with distance from the shake source.")]
public Attenuator.StrengthAttenuationParams attenuation;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1a8a4f5340889954aa6de7013b117066
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,113 @@
using UnityEngine;
namespace CameraShake
{
/// <summary>
/// Contains shorthands for creating common shake types.
/// </summary>
public class CameraShakePresets
{
readonly CameraShaker shaker;
public CameraShakePresets(CameraShaker shaker)
{
this.shaker = shaker;
}
/// <summary>
/// Suitable for short and snappy shakes in 2D. Moves camera in X and Y axes and rotates it in Z axis.
/// </summary>
/// <param name="positionStrength">Strength of motion in X and Y axes.</param>
/// <param name="rotationStrength">Strength of rotation in Z axis.</param>
/// <param name="freq">Frequency of shaking.</param>
/// <param name="numBounces">Number of vibrations before stop.</param>
public void ShortShake2D(
float positionStrength = 0.08f,
float rotationStrength = 0.1f,
float freq = 25,
int numBounces = 5)
{
BounceShake.Params pars = new BounceShake.Params
{
positionStrength = positionStrength,
rotationStrength = rotationStrength,
freq = freq,
numBounces = numBounces
};
shaker.RegisterShake(new BounceShake(pars));
}
/// <summary>
/// Suitable for longer and stronger shakes in 3D. Rotates camera in all three axes.
/// </summary>
/// <param name="strength">Strength of the shake.</param>
/// <param name="freq">Frequency of shaking.</param>
/// <param name="numBounces">Number of vibrations before stop.</param>
public void ShortShake3D(
float strength = 0.3f,
float freq = 25,
int numBounces = 5)
{
BounceShake.Params pars = new BounceShake.Params
{
axesMultiplier = new Displacement(Vector3.zero, new Vector3(1, 1, 0.4f)),
rotationStrength = strength,
freq = freq,
numBounces = numBounces
};
shaker.RegisterShake(new BounceShake(pars));
}
/// <summary>
/// Suitable for longer and stronger shakes in 2D. Moves camera in X and Y axes and rotates it in Z axis.
/// </summary>
/// <param name="positionStrength">Strength of motion in X and Y axes.</param>
/// <param name="rotationStrength">Strength of rotation in Z axis.</param>
/// <param name="duration">Duration of the shake.</param>
public void Explosion2D(
float positionStrength = 1f,
float rotationStrength = 3,
float duration = 0.5f)
{
PerlinShake.NoiseMode[] modes =
{
new PerlinShake.NoiseMode(8, 1),
new PerlinShake.NoiseMode(20, 0.3f)
};
Envelope.EnvelopeParams envelopePars = new Envelope.EnvelopeParams();
envelopePars.decay = duration <= 0 ? 1 : 1 / duration;
PerlinShake.Params pars = new PerlinShake.Params
{
strength = new Displacement(new Vector3(1, 1) * positionStrength, Vector3.forward * rotationStrength),
noiseModes = modes,
envelope = envelopePars,
};
shaker.RegisterShake(new PerlinShake(pars));
}
/// <summary>
/// Suitable for longer and stronger shakes in 3D. Rotates camera in all three axes.
/// </summary>
/// <param name="strength">Strength of the shake.</param>
/// <param name="duration">Duration of the shake.</param>
public void Explosion3D(
float strength = 8f,
float duration = 0.7f)
{
PerlinShake.NoiseMode[] modes =
{
new PerlinShake.NoiseMode(6, 1),
new PerlinShake.NoiseMode(20, 0.2f)
};
Envelope.EnvelopeParams envelopePars = new Envelope.EnvelopeParams();
envelopePars.decay = duration <= 0 ? 1 : 1 / duration;
PerlinShake.Params pars = new PerlinShake.Params
{
strength = new Displacement(Vector3.zero, new Vector3(1, 1, 0.5f) * strength),
noiseModes = modes,
envelope = envelopePars,
};
shaker.RegisterShake(new PerlinShake(pars));
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 27cd455dd46fc6a47b7cc4f29f710304
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,98 @@
using System.Collections.Generic;
using UnityEngine;
namespace CameraShake
{
/// <summary>
/// Camera shaker component registeres new shakes, holds a list of active shakes, and applies them to the camera additively.
/// </summary>
public class CameraShaker : MonoBehaviour
{
public static CameraShaker Instance;
public static CameraShakePresets Presets;
readonly List<ICameraShake> activeShakes = new List<ICameraShake>();
[Tooltip("Transform which will be affected by the shakes.\n\nCameraShaker will set this transform's local position and rotation.")]
[SerializeField]
Transform cameraTransform;
[Tooltip("Scales the strength of all shakes.")]
[Range(0, 1)]
[SerializeField]
public float StrengthMultiplier = 1;
public CameraShakePresets ShakePresets;
/// <summary>
/// Adds a shake to the list of active shakes.
/// </summary>
public static void Shake(ICameraShake shake)
{
if (IsInstanceNull()) return;
Instance.RegisterShake(shake);
}
/// <summary>
/// Adds a shake to the list of active shakes.
/// </summary>
public void RegisterShake(ICameraShake shake)
{
shake.Initialize(cameraTransform.position,
cameraTransform.rotation);
activeShakes.Add(shake);
}
/// <summary>
/// Sets the transform which will be affected by the shakes.
/// </summary>
public void SetCameraTransform(Transform cameraTransform)
{
cameraTransform.localPosition = Vector3.zero;
cameraTransform.localEulerAngles = Vector3.zero;
this.cameraTransform = cameraTransform;
}
private void Awake()
{
Instance = this;
ShakePresets = new CameraShakePresets(this);
Presets = ShakePresets;
if (cameraTransform == null)
cameraTransform = transform;
}
public void UpdateShake()
{
if (cameraTransform == null) return;
Displacement cameraDisplacement = Displacement.Zero;
for (int i = activeShakes.Count - 1; i >= 0; i--)
{
if (activeShakes[i].IsFinished)
{
activeShakes.RemoveAt(i);
}
else
{
activeShakes[i].Update(Time.deltaTime, cameraTransform.position, cameraTransform.rotation);
cameraDisplacement += activeShakes[i].CurrentDisplacement;
}
}
cameraTransform.localPosition = transform.localPosition + StrengthMultiplier * cameraDisplacement.position;
cameraTransform.localRotation *= Quaternion.Euler(StrengthMultiplier * cameraDisplacement.eulerAngles);
}
private static bool IsInstanceNull()
{
if (Instance == null)
{
Debug.LogError("CameraShaker Instance is missing!");
return true;
}
return false;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2a257897ce04dc64eb5ae266c62846be
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,98 @@
using UnityEngine;
namespace CameraShake
{
/// <summary>
/// Representation of translation and rotation.
/// </summary>
[System.Serializable]
public struct Displacement
{
public Vector3 position;
public Vector3 eulerAngles;
public Displacement(Vector3 position, Vector3 eulerAngles)
{
this.position = position;
this.eulerAngles = eulerAngles;
}
public Displacement(Vector3 position)
{
this.position = position;
this.eulerAngles = Vector3.zero;
}
public static Displacement Zero
{
get
{
return new Displacement(Vector3.zero, Vector3.zero);
}
}
public static Displacement operator +(Displacement a, Displacement b)
{
return new Displacement(a.position + b.position,
b.eulerAngles + a.eulerAngles);
}
public static Displacement operator -(Displacement a, Displacement b)
{
return new Displacement(a.position - b.position,
b.eulerAngles - a.eulerAngles);
}
public static Displacement operator -(Displacement disp)
{
return new Displacement(-disp.position, -disp.eulerAngles);
}
public static Displacement operator *(Displacement coords, float number)
{
return new Displacement(coords.position * number,
coords.eulerAngles * number);
}
public static Displacement operator *(float number, Displacement coords)
{
return coords * number;
}
public static Displacement operator /(Displacement coords, float number)
{
return new Displacement(coords.position / number,
coords.eulerAngles / number);
}
public static Displacement Scale(Displacement a, Displacement b)
{
return new Displacement(Vector3.Scale(a.position, b.position),
Vector3.Scale(b.eulerAngles, a.eulerAngles));
}
public static Displacement Lerp(Displacement a, Displacement b, float t)
{
return new Displacement(Vector3.Lerp(a.position, b.position, t),
Vector3.Lerp(a.eulerAngles, b.eulerAngles, t));
}
public Displacement ScaledBy(float posScale, float rotScale)
{
return new Displacement(position * posScale, eulerAngles * rotScale);
}
public Displacement Normalized
{
get
{
return new Displacement(position.normalized, eulerAngles.normalized);
}
}
public static Displacement InsideUnitSpheres()
{
return new Displacement(Random.insideUnitSphere, Random.insideUnitSphere);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 22dc566280f4a704d958e931abdb9fc4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,168 @@
using UnityEngine;
namespace CameraShake
{
/// <summary>
/// Controls strength of the shake over time.
/// </summary>
public class Envelope : IAmplitudeController
{
readonly EnvelopeParams pars;
readonly EnvelopeControlMode controlMode;
float amplitude;
float targetAmplitude;
float sustainEndTime;
bool finishWhenAmplitudeZero;
bool finishImmediately;
EnvelopeState state;
/// <summary>
/// Creates an Envelope instance.
/// </summary>
/// <param name="pars">Envelope parameters.</param>
/// <param name="controlMode">Pass Auto for a single shake, or Manual for controlling strength manually.</param>
public Envelope(EnvelopeParams pars, float initialTargetAmplitude, EnvelopeControlMode controlMode)
{
this.pars = pars;
this.controlMode = controlMode;
SetTarget(initialTargetAmplitude);
}
/// <summary>
/// The value by which you want to multiply shake displacement.
/// </summary>
public float Intensity { get; private set; }
public bool IsFinished
{
get
{
if (finishImmediately) return true;
return (finishWhenAmplitudeZero || controlMode == EnvelopeControlMode.Auto)
&& amplitude <= 0 && targetAmplitude <= 0;
}
}
public void Finish()
{
finishWhenAmplitudeZero = true;
SetTarget(0);
}
public void FinishImmediately()
{
finishImmediately = true;
}
/// <summary>
/// Update is called every frame by the shake.
/// </summary>
public void Update(float deltaTime)
{
if (IsFinished) return;
if (state == EnvelopeState.Increase)
{
if (pars.attack > 0)
amplitude += deltaTime * pars.attack;
if (amplitude > targetAmplitude || pars.attack <= 0)
{
amplitude = targetAmplitude;
state = EnvelopeState.Sustain;
if (controlMode == EnvelopeControlMode.Auto)
sustainEndTime = Time.time + pars.sustain;
}
}
else
{
if (state == EnvelopeState.Decrease)
{
if (pars.decay > 0)
amplitude -= deltaTime * pars.decay;
if (amplitude < targetAmplitude || pars.decay <= 0)
{
amplitude = targetAmplitude;
state = EnvelopeState.Sustain;
}
}
else
{
if (controlMode == EnvelopeControlMode.Auto && Time.time > sustainEndTime)
{
SetTarget(0);
}
}
}
amplitude = Mathf.Clamp01(amplitude);
Intensity = Power.Evaluate(amplitude, pars.degree);
}
public void SetTargetAmplitude(float value)
{
if (controlMode == EnvelopeControlMode.Manual && !finishWhenAmplitudeZero)
{
SetTarget(value);
}
}
private void SetTarget(float value)
{
targetAmplitude = Mathf.Clamp01(value);
state = targetAmplitude > amplitude ? EnvelopeState.Increase : EnvelopeState.Decrease;
}
[System.Serializable]
public class EnvelopeParams
{
/// <summary>
/// How fast the amplitude rises.
/// </summary>
[Tooltip("How fast the amplitude increases.")]
public float attack = 10;
/// <summary>
/// How long in seconds the amplitude holds a maximum value.
/// </summary>
[Tooltip("How long in seconds the amplitude holds maximum value.")]
public float sustain = 0;
/// <summary>
/// How fast the amplitude falls.
/// </summary>
[Tooltip("How fast the amplitude decreases.")]
public float decay = 1f;
/// <summary>
/// Power in which the amplitude is raised to get intensity.
/// </summary>
[Tooltip("Power in which the amplitude is raised to get intensity.")]
public Degree degree = Degree.Cubic;
}
public enum EnvelopeControlMode { Auto, Manual }
public enum EnvelopeState { Sustain, Increase, Decrease }
}
public interface IAmplitudeController
{
/// <summary>
/// Sets value to which amplitude will move over time.
/// </summary>
void SetTargetAmplitude(float value);
/// <summary>
/// Sets amplitude to zero and finishes the shake when zero is reached.
/// </summary>
void Finish();
/// <summary>
/// Immediately finishes the shake.
/// </summary>
void FinishImmediately();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 13084b7de651ead408d3f5ef8c6837b8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,27 @@
using UnityEngine;
namespace CameraShake
{
public interface ICameraShake
{
/// <summary>
/// Represents current position and rotation of the camera according to the shake.
/// </summary>
Displacement CurrentDisplacement { get; }
/// <summary>
/// Shake system will dispose the shake on the first frame when this is true.
/// </summary>
bool IsFinished { get; }
/// <summary>
/// CameraShaker calls this when the shake is added to the list of active shakes.
/// </summary>
void Initialize(Vector3 cameraPosition, Quaternion cameraRotation);
/// <summary>
/// CameraShaker calls this every frame on active shakes.
/// </summary>
void Update(float deltaTime, Vector3 cameraPosition, Quaternion cameraRotation);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a062a4046bad80b469554a84b9b30cab
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,121 @@
using UnityEngine;
namespace CameraShake
{
public class KickShake : ICameraShake
{
readonly Params pars;
readonly Vector3? sourcePosition;
readonly bool attenuateStrength;
Displacement direction;
Displacement prevWaypoint;
Displacement currentWaypoint;
bool release;
float t;
/// <summary>
/// Creates an instance of KickShake in the direction from the source to the camera.
/// </summary>
/// <param name="parameters">Parameters of the shake.</param>
/// <param name="sourcePosition">World position of the source of the shake.</param>
/// <param name="attenuateStrength">Change strength depending on distance from the camera?</param>
public KickShake(Params parameters, Vector3 sourcePosition, bool attenuateStrength)
{
pars = parameters;
this.sourcePosition = sourcePosition;
this.attenuateStrength = attenuateStrength;
}
/// <summary>
/// Creates an instance of KickShake.
/// </summary>
/// <param name="parameters">Parameters of the shake.</param>
/// <param name="direction">Direction of the kick.</param>
public KickShake(Params parameters, Displacement direction)
{
pars = parameters;
this.direction = direction.Normalized;
}
public Displacement CurrentDisplacement { get; private set; }
public bool IsFinished { get; private set; }
public void Initialize(Vector3 cameraPosition, Quaternion cameraRotation)
{
if (sourcePosition != null)
{
direction = Attenuator.Direction(sourcePosition.Value, cameraPosition, cameraRotation);
if (attenuateStrength)
direction *= Attenuator.Strength(pars.attenuation, sourcePosition.Value, cameraPosition);
}
currentWaypoint = Displacement.Scale(direction, pars.strength);
}
public void Update(float deltaTime, Vector3 cameraPosition, Quaternion cameraRotation)
{
if (t < 1)
{
Move(deltaTime,
release ? pars.releaseTime : pars.attackTime,
release ? pars.releaseCurve : pars.attackCurve);
}
else
{
CurrentDisplacement = currentWaypoint;
prevWaypoint = currentWaypoint;
if (release)
{
IsFinished = true;
return;
}
else
{
release = true;
t = 0;
currentWaypoint = Displacement.Zero;
}
}
}
private void Move(float deltaTime, float duration, AnimationCurve curve)
{
if (duration > 0)
t += deltaTime / duration;
else
t = 1;
CurrentDisplacement = Displacement.Lerp(prevWaypoint, currentWaypoint, curve.Evaluate(t));
}
[System.Serializable]
public class Params
{
/// <summary>
/// Strength of the shake for each axis.
/// </summary>
[Tooltip("Strength of the shake for each axis.")]
public Displacement strength = new Displacement(Vector3.zero, Vector3.one);
/// <summary>
/// How long it takes to move forward.
/// </summary>
[Tooltip("How long it takes to move forward.")]
public float attackTime = 0.05f;
public AnimationCurve attackCurve = AnimationCurve.EaseInOut(0, 0, 1, 1);
/// <summary>
/// How long it takes to move back.
/// </summary>
[Tooltip("How long it takes to move back.")]
public float releaseTime = 0.2f;
public AnimationCurve releaseCurve = AnimationCurve.EaseInOut(0, 0, 1, 1);
/// <summary>
/// How strength falls with distance from the shake source.
/// </summary>
[Tooltip("How strength falls with distance from the shake source.")]
public Attenuator.StrengthAttenuationParams attenuation;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: aacae9308ca14a04a8174bd35d85a1be
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,144 @@
using UnityEngine;
namespace CameraShake
{
public class PerlinShake : ICameraShake
{
readonly Params pars;
readonly Envelope envelope;
public IAmplitudeController AmplitudeController;
Vector2[] seeds;
float time;
Vector3? sourcePosition;
float norm;
/// <summary>
/// Creates an instance of PerlinShake.
/// </summary>
/// <param name="parameters">Parameters of the shake.</param>
/// <param name="maxAmplitude">Maximum amplitude of the shake.</param>
/// <param name="sourcePosition">World position of the source of the shake.</param>
/// <param name="manualStrengthControl">Pass true if you want to control amplitude manually.</param>
public PerlinShake(
Params parameters,
float maxAmplitude = 1,
Vector3? sourcePosition = null,
bool manualStrengthControl = false)
{
pars = parameters;
envelope = new Envelope(pars.envelope, maxAmplitude,
manualStrengthControl ?
Envelope.EnvelopeControlMode.Manual : Envelope.EnvelopeControlMode.Auto);
AmplitudeController = envelope;
this.sourcePosition = sourcePosition;
}
public Displacement CurrentDisplacement { get; private set; }
public bool IsFinished { get; private set; }
public void Initialize(Vector3 cameraPosition, Quaternion cameraRotation)
{
seeds = new Vector2[pars.noiseModes.Length];
norm = 0;
for (int i = 0; i < seeds.Length; i++)
{
seeds[i] = Random.insideUnitCircle * 20;
norm += pars.noiseModes[i].amplitude;
}
}
public void Update(float deltaTime, Vector3 cameraPosition, Quaternion cameraRotation)
{
if (envelope.IsFinished)
{
IsFinished = true;
return;
}
time += deltaTime;
envelope.Update(deltaTime);
Displacement disp = Displacement.Zero;
for (int i = 0; i < pars.noiseModes.Length; i++)
{
disp += pars.noiseModes[i].amplitude / norm *
SampleNoise(seeds[i], pars.noiseModes[i].freq);
}
CurrentDisplacement = envelope.Intensity * Displacement.Scale(disp, pars.strength);
if (sourcePosition != null)
CurrentDisplacement *= Attenuator.Strength(pars.attenuation, sourcePosition.Value, cameraPosition);
}
private Displacement SampleNoise(Vector2 seed, float freq)
{
Vector3 position = new Vector3(
Mathf.PerlinNoise(seed.x + time * freq, seed.y),
Mathf.PerlinNoise(seed.x, seed.y + time * freq),
Mathf.PerlinNoise(seed.x + time * freq, seed.y + time * freq));
position -= Vector3.one * 0.5f;
Vector3 rotation = new Vector3(
Mathf.PerlinNoise(-seed.x - time * freq, -seed.y),
Mathf.PerlinNoise(-seed.x, -seed.y - time * freq),
Mathf.PerlinNoise(-seed.x - time * freq, -seed.y - time * freq));
rotation -= Vector3.one * 0.5f;
return new Displacement(position, rotation);
}
[System.Serializable]
public class Params
{
/// <summary>
/// Strength of the shake for each axis.
/// </summary>
[Tooltip("Strength of the shake for each axis.")]
public Displacement strength = new Displacement(Vector3.zero, new Vector3(2, 2, 0.8f));
/// <summary>
/// Layers of perlin noise with different frequencies.
/// </summary>
[Tooltip("Layers of perlin noise with different frequencies.")]
public NoiseMode[] noiseModes = { new NoiseMode(12, 1) };
/// <summary>
/// Strength over time.
/// </summary>
[Tooltip("Strength of the shake over time.")]
public Envelope.EnvelopeParams envelope;
/// <summary>
/// How strength falls with distance from the shake source.
/// </summary>
[Tooltip("How strength falls with distance from the shake source.")]
public Attenuator.StrengthAttenuationParams attenuation;
}
[System.Serializable]
public struct NoiseMode
{
public NoiseMode(float freq, float amplitude)
{
this.freq = freq;
this.amplitude = amplitude;
}
/// <summary>
/// Frequency multiplier for the noise.
/// </summary>
[Tooltip("Frequency multiplier for the noise.")]
public float freq;
/// <summary>
/// Amplitude of the mode.
/// </summary>
[Tooltip("Amplitude of the mode.")]
[Range(0, 1)]
public float amplitude;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: de97a9ba28783f34cae2c44c1d4446d5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,24 @@
namespace CameraShake
{
public static class Power
{
public static float Evaluate(float value, Degree degree)
{
switch (degree)
{
case Degree.Linear:
return value;
case Degree.Quadratic:
return value * value;
case Degree.Cubic:
return value * value * value;
case Degree.Quadric:
return value * value * value * value;
default:
return value;
}
}
}
public enum Degree { Linear, Quadratic, Cubic, Quadric }
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ae1c138ac39e5704daa47650c0a286d0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: