using UnityEngine; using System; using UnityEngine.Serialization; namespace Cinemachine { /// /// This is an asset that defines a noise profile. A noise profile is the /// shape of the noise signal as a function of time. You can build arbitrarily complex shapes by /// combining different base perlin noise frequencies at different amplitudes. /// /// The frequencies and amplitudes should be chosen with care, to ensure an interesting /// noise quality that is not obviously repetitive. /// /// As a mathematical side-note, any arbitrary periodic curve can be broken down into a /// series of fixed-amplitude sine-waves added together. This is called fourier decomposition, /// and is the basis of much signal processing. It doesn't really have much to do with this /// asset, but it's super interesting! /// [DocumentationSorting(DocumentationSortingAttribute.Level.UserRef)] [HelpURL(Documentation.BaseURL + "manual/CinemachineNoiseProfiles.html")] public sealed class NoiseSettings : SignalSourceAsset { /// Describes the behaviour for a channel of noise [DocumentationSorting(DocumentationSortingAttribute.Level.UserRef)] [Serializable] public struct NoiseParams { /// The frequency of noise for this channel. Higher magnitudes vibrate faster [Tooltip("The frequency of noise for this channel. Higher magnitudes vibrate faster.")] public float Frequency; /// The amplitude of the noise for this channel. Larger numbers vibrate higher [Tooltip("The amplitude of the noise for this channel. Larger numbers vibrate higher.")] public float Amplitude; /// If checked, then the amplitude and frequency will not be randomized [Tooltip("If checked, then the amplitude and frequency will not be randomized.")] public bool Constant; /// Get the signal value at a given time, offset by a given amount /// The current time /// The (unscaled) offset to add to the current time /// Value of the signal at desired time public float GetValueAt(float time, float timeOffset) { float t = (Frequency * time) + timeOffset; if (Constant) return Mathf.Cos(t * 2 * Mathf.PI) * Amplitude * 0.5f; return (Mathf.PerlinNoise(t, 0f) - 0.5f) * Amplitude; } } /// /// Contains the behaviour of noise for the noise module for all 3 cardinal axes of the camera /// [DocumentationSorting(DocumentationSortingAttribute.Level.UserRef)] [Serializable] public struct TransformNoiseParams { /// Noise definition for X-axis [Tooltip("Noise definition for X-axis")] public NoiseParams X; /// Noise definition for Y-axis [Tooltip("Noise definition for Y-axis")] public NoiseParams Y; /// Noise definition for Z-axis [Tooltip("Noise definition for Z-axis")] public NoiseParams Z; /// Get the signal value at a given time, offset by a given amount /// The current time /// The (unscaled) offsets (per-channel) to add to the current time /// Value of the signal at desired time public Vector3 GetValueAt(float time, Vector3 timeOffsets) { return new Vector3( X.GetValueAt(time, timeOffsets.x), Y.GetValueAt(time, timeOffsets.y), Z.GetValueAt(time, timeOffsets.z)); } } /// The array of positional noise channels for this NoiseSettings [Tooltip("These are the noise channels for the virtual camera's position. Convincing noise setups " + "typically mix low, medium and high frequencies together, so start with a size of 3")] [FormerlySerializedAs("m_Position")] public TransformNoiseParams[] PositionNoise = Array.Empty(); /// The array of orientation noise channels for this NoiseSettings [Tooltip("These are the noise channels for the virtual camera's orientation. Convincing noise " + "setups typically mix low, medium and high frequencies together, so start with a size of 3")] [FormerlySerializedAs("m_Orientation")] public TransformNoiseParams[] OrientationNoise = Array.Empty(); /// Get the noise signal value at a specific time /// The parameters that define the noise function /// The time at which to sample the noise function /// Start time offset for each channel /// The 3-channel noise signal value at the specified time public static Vector3 GetCombinedFilterResults( TransformNoiseParams[] noiseParams, float time, Vector3 timeOffsets) { Vector3 pos = Vector3.zero; if (noiseParams != null) { for (int i = 0; i < noiseParams.Length; ++i) pos += noiseParams[i].GetValueAt(time, timeOffsets); } return pos; } /// /// Returns the total length in seconds of the signal. /// Returns 0 for signals of indeterminate length. /// public override float SignalDuration { get { return 0; } } /// Interface for raw signal provider /// Time at which to get signal value /// The position impulse signal /// The rotation impulse signal public override void GetSignal(float timeSinceSignalStart, out Vector3 pos, out Quaternion rot) { pos = GetCombinedFilterResults(PositionNoise, timeSinceSignalStart, Vector3.zero); rot = Quaternion.Euler(GetCombinedFilterResults(OrientationNoise, timeSinceSignalStart, Vector3.zero)); } } }