暫無描述
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Volume.cs 6.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. using System.Collections.Generic;
  2. using UnityEngine.Serialization;
  3. namespace UnityEngine.Rendering
  4. {
  5. /// <summary>
  6. /// A generic Volume component holding a <see cref="VolumeProfile"/>.
  7. /// </summary>
  8. [CurrentPipelineHelpURL("Volumes")]
  9. [ExecuteAlways]
  10. [AddComponentMenu("Miscellaneous/Volume")]
  11. public class Volume : MonoBehaviour, IVolume
  12. {
  13. [SerializeField, FormerlySerializedAs("isGlobal")]
  14. bool m_IsGlobal = true;
  15. /// <summary>
  16. /// Specifies whether to apply the Volume to the entire Scene or not.
  17. /// </summary>
  18. public bool isGlobal
  19. {
  20. get => m_IsGlobal;
  21. set => m_IsGlobal = value;
  22. }
  23. /// <summary>
  24. /// A value which determines which Volume is being used when Volumes have an equal amount of influence on the Scene. Volumes with a higher priority will override lower ones.
  25. /// </summary>
  26. [Delayed]
  27. public float priority = 0f;
  28. /// <summary>
  29. /// The outer distance to start blending from. A value of 0 means no blending and Unity applies
  30. /// the Volume overrides immediately upon entry.
  31. /// </summary>
  32. public float blendDistance = 0f;
  33. /// <summary>
  34. /// The total weight of this volume in the Scene. 0 means no effect and 1 means full effect.
  35. /// </summary>
  36. [Range(0f, 1f)]
  37. public float weight = 1f;
  38. /// <summary>
  39. /// The shared Profile that this Volume uses.
  40. /// Modifying <c>sharedProfile</c> changes every Volumes that uses this Profile and also changes
  41. /// the Profile settings stored in the Project.
  42. /// </summary>
  43. /// <remarks>
  44. /// You should not modify Profiles that <c>sharedProfile</c> returns. If you want
  45. /// to modify the Profile of a Volume, use <see cref="profile"/> instead.
  46. /// </remarks>
  47. /// <seealso cref="profile"/>
  48. public VolumeProfile sharedProfile = null;
  49. /// <summary>
  50. /// Gets the first instantiated <see cref="VolumeProfile"/> assigned to the Volume.
  51. /// Modifying <c>profile</c> changes the Profile for this Volume only. If another Volume
  52. /// uses the same Profile, this clones the shared Profile and starts using it from now on.
  53. /// </summary>
  54. /// <remarks>
  55. /// This property automatically instantiates the Profile and make it unique to this Volume
  56. /// so you can safely edit it via scripting at runtime without changing the original Asset
  57. /// in the Project.
  58. /// Note that if you pass your own Profile, you must destroy it when you finish using it.
  59. /// </remarks>
  60. /// <seealso cref="sharedProfile"/>
  61. public VolumeProfile profile
  62. {
  63. get
  64. {
  65. if (m_InternalProfile == null)
  66. {
  67. m_InternalProfile = ScriptableObject.CreateInstance<VolumeProfile>();
  68. if (sharedProfile != null)
  69. {
  70. m_InternalProfile.name = sharedProfile.name;
  71. foreach (var item in sharedProfile.components)
  72. {
  73. var itemCopy = Instantiate(item);
  74. m_InternalProfile.components.Add(itemCopy);
  75. }
  76. }
  77. }
  78. return m_InternalProfile;
  79. }
  80. set => m_InternalProfile = value;
  81. }
  82. internal List<Collider> m_Colliders = new List<Collider>();
  83. /// <summary>
  84. /// The colliders of the volume if <see cref="isGlobal"/> is false
  85. /// </summary>
  86. public List<Collider> colliders => m_Colliders;
  87. internal VolumeProfile profileRef => m_InternalProfile == null ? sharedProfile : m_InternalProfile;
  88. /// <summary>
  89. /// Checks if the Volume has an instantiated Profile or if it uses a shared Profile.
  90. /// </summary>
  91. /// <returns><c>true</c> if the profile has been instantiated.</returns>
  92. /// <seealso cref="profile"/>
  93. /// <seealso cref="sharedProfile"/>
  94. public bool HasInstantiatedProfile() => m_InternalProfile != null;
  95. // Needed for state tracking (see the comments in Update)
  96. int m_PreviousLayer;
  97. float m_PreviousPriority;
  98. VolumeProfile m_InternalProfile;
  99. void OnEnable()
  100. {
  101. m_PreviousLayer = gameObject.layer;
  102. VolumeManager.instance.Register(this, m_PreviousLayer);
  103. GetComponents(m_Colliders);
  104. }
  105. void OnDisable()
  106. {
  107. VolumeManager.instance.Unregister(this, gameObject.layer);
  108. }
  109. void Update()
  110. {
  111. // Unfortunately we need to track the current layer to update the volume manager in
  112. // real-time as the user could change it at any time in the editor or at runtime.
  113. // Because no event is raised when the layer changes, we have to track it on every
  114. // frame :/
  115. UpdateLayer();
  116. // Same for priority. We could use a property instead, but it doesn't play nice with the
  117. // serialization system. Using a custom Attribute/PropertyDrawer for a property is
  118. // possible but it doesn't work with Undo/Redo in the editor, which makes it useless for
  119. // our case.
  120. if (priority != m_PreviousPriority)
  121. {
  122. VolumeManager.instance.SetLayerDirty(gameObject.layer);
  123. m_PreviousPriority = priority;
  124. }
  125. #if UNITY_EDITOR
  126. // In the editor, we refresh the list of colliders at every frame because it's frequent to add/remove them
  127. GetComponents(m_Colliders);
  128. #endif
  129. }
  130. internal void UpdateLayer()
  131. {
  132. int layer = gameObject.layer;
  133. if (layer != m_PreviousLayer)
  134. {
  135. VolumeManager.instance.UpdateVolumeLayer(this, m_PreviousLayer, layer);
  136. m_PreviousLayer = layer;
  137. }
  138. }
  139. void OnValidate()
  140. {
  141. blendDistance = Mathf.Max(blendDistance, 0f);
  142. }
  143. }
  144. }