AlternativePath.cs 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. using UnityEngine;
  2. using System.Collections.Generic;
  3. namespace Pathfinding {
  4. [AddComponentMenu("Pathfinding/Modifiers/Alternative Path")]
  5. [System.Serializable]
  6. /// <summary>
  7. /// Applies penalty to the paths it processes telling other units to avoid choosing the same path.
  8. ///
  9. /// Note that this might not work properly if penalties are modified by other actions as well (e.g graph update objects which reset the penalty to zero).
  10. /// It will only work when all penalty modifications are relative, i.e adding or subtracting penalties, but not when setting penalties
  11. /// to specific values.
  12. ///
  13. /// When destroyed, it will correctly remove any added penalty.
  14. /// </summary>
  15. [HelpURL("http://arongranberg.com/astar/documentation/stable/class_pathfinding_1_1_alternative_path.php")]
  16. public class AlternativePath : MonoModifier {
  17. #if UNITY_EDITOR
  18. [UnityEditor.MenuItem("CONTEXT/Seeker/Add Alternative Path Modifier")]
  19. public static void AddComp (UnityEditor.MenuCommand command) {
  20. (command.context as Component).gameObject.AddComponent(typeof(AlternativePath));
  21. }
  22. #endif
  23. public override int Order { get { return 10; } }
  24. /// <summary>How much penalty (weight) to apply to nodes</summary>
  25. public int penalty = 1000;
  26. /// <summary>Max number of nodes to skip in a row</summary>
  27. public int randomStep = 10;
  28. /// <summary>The previous path</summary>
  29. List<GraphNode> prevNodes = new List<GraphNode>();
  30. /// <summary>The previous penalty used. Stored just in case it changes during operation</summary>
  31. int prevPenalty;
  32. /// <summary>A random object</summary>
  33. readonly System.Random rnd = new System.Random();
  34. bool destroyed;
  35. public override void Apply (Path p) {
  36. if (this == null) return;
  37. ApplyNow(p.path);
  38. }
  39. protected void OnDestroy () {
  40. destroyed = true;
  41. ClearOnDestroy();
  42. }
  43. void ClearOnDestroy () {
  44. InversePrevious();
  45. }
  46. void InversePrevious () {
  47. // Remove previous penalty
  48. if (prevNodes != null) {
  49. bool warnPenalties = false;
  50. for (int i = 0; i < prevNodes.Count; i++) {
  51. if (prevNodes[i].Penalty < prevPenalty) {
  52. warnPenalties = true;
  53. prevNodes[i].Penalty = 0;
  54. } else {
  55. prevNodes[i].Penalty = (uint)(prevNodes[i].Penalty-prevPenalty);
  56. }
  57. }
  58. if (warnPenalties) {
  59. Debug.LogWarning("Penalty for some nodes has been reset while the AlternativePath modifier was active (possibly because of a graph update). Some penalties might be incorrect (they may be lower than expected for the affected nodes)");
  60. }
  61. }
  62. }
  63. void ApplyNow (List<GraphNode> nodes) {
  64. InversePrevious();
  65. prevNodes.Clear();
  66. if (destroyed) return;
  67. if (nodes != null) {
  68. int rndStart = rnd.Next(randomStep);
  69. for (int i = rndStart; i < nodes.Count; i += rnd.Next(1, randomStep)) {
  70. nodes[i].Penalty = (uint)(nodes[i].Penalty+penalty);
  71. prevNodes.Add(nodes[i]);
  72. }
  73. }
  74. prevPenalty = penalty;
  75. }
  76. }
  77. }