NavGraph.cs 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. using UnityEngine;
  2. namespace PF {
  3. /** Exposes internal methods for graphs.
  4. * This is used to hide methods that should not be used by any user code
  5. * but still have to be 'public' or 'internal' (which is pretty much the same as 'public'
  6. * as this library is distributed with source code).
  7. *
  8. * Hiding the internal methods cleans up the documentation and IntelliSense suggestions.
  9. */
  10. public interface IGraphInternals {
  11. string SerializedEditorSettings { get; set; }
  12. void OnDestroy ();
  13. void DestroyAllNodes ();
  14. void SerializeExtraInfo (GraphSerializationContext ctx);
  15. void DeserializeExtraInfo (GraphSerializationContext ctx);
  16. void PostDeserialization (GraphSerializationContext ctx);
  17. void DeserializeSettingsCompatibility (GraphSerializationContext ctx);
  18. }
  19. /** Base class for all graphs */
  20. public abstract class NavGraph : IGraphInternals {
  21. /** Used as an ID of the graph, considered to be unique.
  22. * \note This is Pathfinding.Util.Guid not System.Guid. A replacement for System.Guid was coded for better compatibility with iOS
  23. */
  24. [JsonMember]
  25. public Guid guid;
  26. /** Default penalty to apply to all nodes */
  27. [JsonMember]
  28. public uint initialPenalty;
  29. /** Is the graph open in the editor */
  30. [JsonMember]
  31. public bool open;
  32. /** Index of the graph, used for identification purposes */
  33. public uint graphIndex;
  34. /** Name of the graph.
  35. * Can be set in the unity editor
  36. */
  37. [JsonMember]
  38. public string name;
  39. /** Enable to draw gizmos in the Unity scene view.
  40. * In the inspector this value corresponds to the state of
  41. * the 'eye' icon in the top left corner of every graph inspector.
  42. */
  43. [JsonMember]
  44. public bool drawGizmos = true;
  45. /** Used in the editor to check if the info screen is open.
  46. * Should be inside UNITY_EDITOR only \#ifs but just in case anyone tries to serialize a NavGraph instance using Unity, I have left it like this as it would otherwise cause a crash when building.
  47. * Version 3.0.8.1 was released because of this bug only
  48. */
  49. [JsonMember]
  50. public bool infoScreenOpen;
  51. /** Used in the Unity editor to store serialized settings for graph inspectors */
  52. [JsonMember]
  53. string serializedEditorSettings;
  54. /** Number of nodes in the graph.
  55. * Note that this is, unless the graph type has overriden it, an O(n) operation.
  56. *
  57. * This is an O(1) operation for grid graphs and point graphs.
  58. * For layered grid graphs it is an O(n) operation.
  59. */
  60. public virtual int CountNodes () {
  61. int count = 0;
  62. GetNodes(node => count++);
  63. return count;
  64. }
  65. /** Calls a delegate with all nodes in the graph until the delegate returns false */
  66. public void GetNodes (System.Func<GraphNode, bool> action) {
  67. bool cont = true;
  68. GetNodes(node => {
  69. if (cont) cont &= action(node);
  70. });
  71. }
  72. /** Calls a delegate with all nodes in the graph.
  73. * This is the primary way of iterating through all nodes in a graph.
  74. *
  75. * Do not change the graph structure inside the delegate.
  76. *
  77. * \snippet MiscSnippets.cs NavGraph.GetNodes1
  78. *
  79. * If you want to store all nodes in a list you can do this
  80. *
  81. * \snippet MiscSnippets.cs NavGraph.GetNodes2
  82. */
  83. public abstract void GetNodes (System.Action<GraphNode> action);
  84. /** Returns the nearest node to a position using the specified NNConstraint.
  85. * \param position The position to try to find a close node to
  86. * \param constraint Can for example tell the function to try to return a walkable node. If you do not get a good node back, consider calling GetNearestForce. */
  87. public NNInfoInternal GetNearest (Vector3 position, NNConstraint constraint) {
  88. return GetNearest(position, constraint, null);
  89. }
  90. /** Returns the nearest node to a position using the specified NNConstraint.
  91. * \param position The position to try to find a close node to
  92. * \param hint Can be passed to enable some graph generators to find the nearest node faster.
  93. * \param constraint Can for example tell the function to try to return a walkable node. If you do not get a good node back, consider calling GetNearestForce.
  94. */
  95. public virtual NNInfoInternal GetNearest (Vector3 position, NNConstraint constraint, GraphNode hint) {
  96. // This is a default implementation and it is pretty slow
  97. // Graphs usually override this to provide faster and more specialised implementations
  98. float maxDistSqr = constraint == null || constraint.constrainDistance ? PathFindHelper.GetConfig().maxNearestNodeDistanceSqr : float.PositiveInfinity;
  99. float minDist = float.PositiveInfinity;
  100. GraphNode minNode = null;
  101. float minConstDist = float.PositiveInfinity;
  102. GraphNode minConstNode = null;
  103. // Loop through all nodes and find the closest suitable node
  104. GetNodes(node => {
  105. float dist = (position-(Vector3)node.position).sqrMagnitude;
  106. if (dist < minDist) {
  107. minDist = dist;
  108. minNode = node;
  109. }
  110. if (dist < minConstDist && dist < maxDistSqr && (constraint == null || constraint.Suitable(node))) {
  111. minConstDist = dist;
  112. minConstNode = node;
  113. }
  114. });
  115. var nnInfo = new NNInfoInternal(minNode);
  116. nnInfo.constrainedNode = minConstNode;
  117. if (minConstNode != null) {
  118. nnInfo.constClampedPosition = (Vector3)minConstNode.position;
  119. } else if (minNode != null) {
  120. nnInfo.constrainedNode = minNode;
  121. nnInfo.constClampedPosition = (Vector3)minNode.position;
  122. }
  123. return nnInfo;
  124. }
  125. /**
  126. * Returns the nearest node to a position using the specified \link Pathfinding.NNConstraint constraint \endlink.
  127. * \returns an NNInfo. This method will only return an empty NNInfo if there are no nodes which comply with the specified constraint.
  128. */
  129. public virtual NNInfoInternal GetNearestForce (Vector3 position, NNConstraint constraint) {
  130. return GetNearest(position, constraint);
  131. }
  132. /** Function for cleaning up references.
  133. * This will be called on the same time as OnDisable on the gameObject which the AstarPath script is attached to (remember, not in the editor).
  134. * Use for any cleanup code such as cleaning up static variables which otherwise might prevent resources from being collected.
  135. * Use by creating a function overriding this one in a graph class, but always call base.OnDestroy () in that function.
  136. * All nodes should be destroyed in this function otherwise a memory leak will arise.
  137. */
  138. protected virtual void OnDestroy () {
  139. DestroyAllNodes();
  140. }
  141. /** Destroys all nodes in the graph.
  142. * \warning This is an internal method. Unless you have a very good reason, you should probably not call it.
  143. */
  144. protected virtual void DestroyAllNodes () {
  145. GetNodes(node => node.Destroy());
  146. }
  147. /** Serializes graph type specific node data.
  148. * This function can be overriden to serialize extra node information (or graph information for that matter)
  149. * which cannot be serialized using the standard serialization.
  150. * Serialize the data in any way you want and return a byte array.
  151. * When loading, the exact same byte array will be passed to the DeserializeExtraInfo function.\n
  152. * These functions will only be called if node serialization is enabled.\n
  153. */
  154. protected virtual void SerializeExtraInfo (GraphSerializationContext ctx) {
  155. }
  156. /** Deserializes graph type specific node data.
  157. * \see SerializeExtraInfo
  158. */
  159. protected virtual void DeserializeExtraInfo (GraphSerializationContext ctx) {
  160. }
  161. /** Called after all deserialization has been done for all graphs.
  162. * Can be used to set up more graph data which is not serialized
  163. */
  164. protected virtual void PostDeserialization (GraphSerializationContext ctx) {
  165. }
  166. /** An old format for serializing settings.
  167. * \deprecated This is deprecated now, but the deserialization code is kept to
  168. * avoid loosing data when upgrading from older versions.
  169. */
  170. protected virtual void DeserializeSettingsCompatibility (GraphSerializationContext ctx) {
  171. guid = new Guid(ctx.reader.ReadBytes(16));
  172. initialPenalty = ctx.reader.ReadUInt32();
  173. open = ctx.reader.ReadBoolean();
  174. name = ctx.reader.ReadString();
  175. drawGizmos = ctx.reader.ReadBoolean();
  176. infoScreenOpen = ctx.reader.ReadBoolean();
  177. }
  178. #region IGraphInternals implementation
  179. string IGraphInternals.SerializedEditorSettings { get { return serializedEditorSettings; } set { serializedEditorSettings = value; } }
  180. void IGraphInternals.OnDestroy () { OnDestroy(); }
  181. void IGraphInternals.DestroyAllNodes () { DestroyAllNodes(); }
  182. void IGraphInternals.SerializeExtraInfo (GraphSerializationContext ctx) { SerializeExtraInfo(ctx); }
  183. void IGraphInternals.DeserializeExtraInfo (GraphSerializationContext ctx) { DeserializeExtraInfo(ctx); }
  184. void IGraphInternals.PostDeserialization (GraphSerializationContext ctx) { PostDeserialization(ctx); }
  185. void IGraphInternals.DeserializeSettingsCompatibility (GraphSerializationContext ctx) { DeserializeSettingsCompatibility(ctx); }
  186. #endregion
  187. }
  188. }