NodeLink.cs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. using UnityEngine;
  2. #if UNITY_EDITOR
  3. using UnityEditor;
  4. #endif
  5. namespace Pathfinding {
  6. using Pathfinding.Util;
  7. /// <summary>
  8. /// Connects two nodes with a direct connection.
  9. /// It is not possible to detect this link when following a path (which may be good or bad), for that you can use NodeLink2.
  10. ///
  11. /// [Open online documentation to see images]
  12. ///
  13. /// See: editing-graphs (view in online documentation for working links)
  14. /// </summary>
  15. [AddComponentMenu("Pathfinding/Link")]
  16. [HelpURL("http://arongranberg.com/astar/documentation/stable/class_pathfinding_1_1_node_link.php")]
  17. public class NodeLink : GraphModifier {
  18. /// <summary>End position of the link</summary>
  19. public Transform end;
  20. /// <summary>
  21. /// The connection will be this times harder/slower to traverse.
  22. /// Note that values lower than one will not always make the pathfinder choose this path instead of another path even though this one should
  23. /// lead to a lower total cost unless you also adjust the Heuristic Scale in A* Inspector -> Settings -> Pathfinding or disable the heuristic altogether.
  24. /// </summary>
  25. public float costFactor = 1.0f;
  26. /// <summary>Make a one-way connection</summary>
  27. public bool oneWay = false;
  28. /// <summary>Delete existing connection instead of adding one</summary>
  29. public bool deleteConnection = false;
  30. public Transform Start {
  31. get { return transform; }
  32. }
  33. public Transform End {
  34. get { return end; }
  35. }
  36. public override void OnPostScan () {
  37. if (AstarPath.active.isScanning) {
  38. InternalOnPostScan();
  39. } else {
  40. AstarPath.active.AddWorkItem(new AstarWorkItem(force => {
  41. InternalOnPostScan();
  42. return true;
  43. }));
  44. }
  45. }
  46. public void InternalOnPostScan () {
  47. Apply();
  48. }
  49. public override void OnGraphsPostUpdate () {
  50. if (!AstarPath.active.isScanning) {
  51. AstarPath.active.AddWorkItem(new AstarWorkItem(force => {
  52. InternalOnPostScan();
  53. return true;
  54. }));
  55. }
  56. }
  57. public virtual void Apply () {
  58. if (Start == null || End == null || AstarPath.active == null) return;
  59. GraphNode startNode = AstarPath.active.GetNearest(Start.position).node;
  60. GraphNode endNode = AstarPath.active.GetNearest(End.position).node;
  61. if (startNode == null || endNode == null) return;
  62. if (deleteConnection) {
  63. startNode.RemoveConnection(endNode);
  64. if (!oneWay)
  65. endNode.RemoveConnection(startNode);
  66. } else {
  67. uint cost = (uint)System.Math.Round((startNode.position-endNode.position).costMagnitude*costFactor);
  68. startNode.AddConnection(endNode, cost);
  69. if (!oneWay)
  70. endNode.AddConnection(startNode, cost);
  71. }
  72. }
  73. public void OnDrawGizmos () {
  74. if (Start == null || End == null) return;
  75. Draw.Gizmos.Bezier(Start.position, End.position, deleteConnection ? Color.red : Color.green);
  76. }
  77. #if UNITY_EDITOR
  78. [UnityEditor.MenuItem("Edit/Pathfinding/Link Pair %&l")]
  79. public static void LinkObjects () {
  80. Transform[] tfs = Selection.transforms;
  81. if (tfs.Length == 2) {
  82. LinkObjects(tfs[0], tfs[1], false);
  83. }
  84. SceneView.RepaintAll();
  85. }
  86. [UnityEditor.MenuItem("Edit/Pathfinding/Unlink Pair %&u")]
  87. public static void UnlinkObjects () {
  88. Transform[] tfs = Selection.transforms;
  89. if (tfs.Length == 2) {
  90. LinkObjects(tfs[0], tfs[1], true);
  91. }
  92. SceneView.RepaintAll();
  93. }
  94. [UnityEditor.MenuItem("Edit/Pathfinding/Delete Links on Selected %&b")]
  95. public static void DeleteLinks () {
  96. Transform[] tfs = Selection.transforms;
  97. for (int i = 0; i < tfs.Length; i++) {
  98. NodeLink[] conns = tfs[i].GetComponents<NodeLink>();
  99. for (int j = 0; j < conns.Length; j++) DestroyImmediate(conns[j]);
  100. }
  101. SceneView.RepaintAll();
  102. }
  103. public static void LinkObjects (Transform a, Transform b, bool removeConnection) {
  104. NodeLink connecting = null;
  105. NodeLink[] conns = a.GetComponents<NodeLink>();
  106. for (int i = 0; i < conns.Length; i++) {
  107. if (conns[i].end == b) {
  108. connecting = conns[i];
  109. break;
  110. }
  111. }
  112. conns = b.GetComponents<NodeLink>();
  113. for (int i = 0; i < conns.Length; i++) {
  114. if (conns[i].end == a) {
  115. connecting = conns[i];
  116. break;
  117. }
  118. }
  119. if (removeConnection) {
  120. if (connecting != null) DestroyImmediate(connecting);
  121. } else {
  122. if (connecting == null) {
  123. connecting = a.gameObject.AddComponent<NodeLink>();
  124. connecting.end = b;
  125. } else {
  126. connecting.deleteConnection = !connecting.deleteConnection;
  127. }
  128. }
  129. }
  130. #endif
  131. }
  132. }