NoiseSettings.cs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. using UnityEngine;
  2. using System;
  3. using UnityEngine.Serialization;
  4. namespace Cinemachine
  5. {
  6. /// <summary>
  7. /// This is an asset that defines a noise profile. A noise profile is the
  8. /// shape of the noise signal as a function of time. You can build arbitrarily complex shapes by
  9. /// combining different base perlin noise frequencies at different amplitudes.
  10. ///
  11. /// The frequencies and amplitudes should be chosen with care, to ensure an interesting
  12. /// noise quality that is not obviously repetitive.
  13. ///
  14. /// As a mathematical side-note, any arbitrary periodic curve can be broken down into a
  15. /// series of fixed-amplitude sine-waves added together. This is called fourier decomposition,
  16. /// and is the basis of much signal processing. It doesn't really have much to do with this
  17. /// asset, but it's super interesting!
  18. /// </summary>
  19. [DocumentationSorting(DocumentationSortingAttribute.Level.UserRef)]
  20. [HelpURL(Documentation.BaseURL + "manual/CinemachineNoiseProfiles.html")]
  21. public sealed class NoiseSettings : SignalSourceAsset
  22. {
  23. /// <summary>Describes the behaviour for a channel of noise</summary>
  24. [DocumentationSorting(DocumentationSortingAttribute.Level.UserRef)]
  25. [Serializable]
  26. public struct NoiseParams
  27. {
  28. /// <summary>The frequency of noise for this channel. Higher magnitudes vibrate faster</summary>
  29. [Tooltip("The frequency of noise for this channel. Higher magnitudes vibrate faster.")]
  30. public float Frequency;
  31. /// <summary>The amplitude of the noise for this channel. Larger numbers vibrate higher</summary>
  32. [Tooltip("The amplitude of the noise for this channel. Larger numbers vibrate higher.")]
  33. public float Amplitude;
  34. /// <summary>If checked, then the amplitude and frequency will not be randomized</summary>
  35. [Tooltip("If checked, then the amplitude and frequency will not be randomized.")]
  36. public bool Constant;
  37. /// <summary>Get the signal value at a given time, offset by a given amount</summary>
  38. /// <param name="time">The current time</param>
  39. /// <param name="timeOffset">The (unscaled) offset to add to the current time</param>
  40. /// <returns>Value of the signal at desired time</returns>
  41. public float GetValueAt(float time, float timeOffset)
  42. {
  43. float t = (Frequency * time) + timeOffset;
  44. if (Constant)
  45. return Mathf.Cos(t * 2 * Mathf.PI) * Amplitude * 0.5f;
  46. return (Mathf.PerlinNoise(t, 0f) - 0.5f) * Amplitude;
  47. }
  48. }
  49. /// <summary>
  50. /// Contains the behaviour of noise for the noise module for all 3 cardinal axes of the camera
  51. /// </summary>
  52. [DocumentationSorting(DocumentationSortingAttribute.Level.UserRef)]
  53. [Serializable]
  54. public struct TransformNoiseParams
  55. {
  56. /// <summary>Noise definition for X-axis</summary>
  57. [Tooltip("Noise definition for X-axis")]
  58. public NoiseParams X;
  59. /// <summary>Noise definition for Y-axis</summary>
  60. [Tooltip("Noise definition for Y-axis")]
  61. public NoiseParams Y;
  62. /// <summary>Noise definition for Z-axis</summary>
  63. [Tooltip("Noise definition for Z-axis")]
  64. public NoiseParams Z;
  65. /// <summary>Get the signal value at a given time, offset by a given amount</summary>
  66. /// <param name="time">The current time</param>
  67. /// <param name="timeOffsets">The (unscaled) offsets (per-channel) to add to the current time</param>
  68. /// <returns>Value of the signal at desired time</returns>
  69. public Vector3 GetValueAt(float time, Vector3 timeOffsets)
  70. {
  71. return new Vector3(
  72. X.GetValueAt(time, timeOffsets.x),
  73. Y.GetValueAt(time, timeOffsets.y),
  74. Z.GetValueAt(time, timeOffsets.z));
  75. }
  76. }
  77. /// <summary>The array of positional noise channels for this <c>NoiseSettings</c></summary>
  78. [Tooltip("These are the noise channels for the virtual camera's position. Convincing noise setups "
  79. + "typically mix low, medium and high frequencies together, so start with a size of 3")]
  80. [FormerlySerializedAs("m_Position")]
  81. public TransformNoiseParams[] PositionNoise = Array.Empty<TransformNoiseParams>();
  82. /// <summary>The array of orientation noise channels for this <c>NoiseSettings</c></summary>
  83. [Tooltip("These are the noise channels for the virtual camera's orientation. Convincing noise "
  84. + "setups typically mix low, medium and high frequencies together, so start with a size of 3")]
  85. [FormerlySerializedAs("m_Orientation")]
  86. public TransformNoiseParams[] OrientationNoise = Array.Empty<TransformNoiseParams>();
  87. /// <summary>Get the noise signal value at a specific time</summary>
  88. /// <param name="noiseParams">The parameters that define the noise function</param>
  89. /// <param name="time">The time at which to sample the noise function</param>
  90. /// <param name="timeOffsets">Start time offset for each channel</param>
  91. /// <returns>The 3-channel noise signal value at the specified time</returns>
  92. public static Vector3 GetCombinedFilterResults(
  93. TransformNoiseParams[] noiseParams, float time, Vector3 timeOffsets)
  94. {
  95. Vector3 pos = Vector3.zero;
  96. if (noiseParams != null)
  97. {
  98. for (int i = 0; i < noiseParams.Length; ++i)
  99. pos += noiseParams[i].GetValueAt(time, timeOffsets);
  100. }
  101. return pos;
  102. }
  103. /// <summary>
  104. /// Returns the total length in seconds of the signal.
  105. /// Returns 0 for signals of indeterminate length.
  106. /// </summary>
  107. public override float SignalDuration { get { return 0; } }
  108. /// <summary>Interface for raw signal provider</summary>
  109. /// <param name="timeSinceSignalStart">Time at which to get signal value</param>
  110. /// <param name="pos">The position impulse signal</param>
  111. /// <param name="rot">The rotation impulse signal</param>
  112. public override void GetSignal(float timeSinceSignalStart, out Vector3 pos, out Quaternion rot)
  113. {
  114. pos = GetCombinedFilterResults(PositionNoise, timeSinceSignalStart, Vector3.zero);
  115. rot = Quaternion.Euler(GetCombinedFilterResults(OrientationNoise, timeSinceSignalStart, Vector3.zero));
  116. }
  117. }
  118. }