RVONavmesh.cs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. using UnityEngine;
  2. using System.Collections.Generic;
  3. using UnityEngine.Profiling;
  4. namespace Pathfinding.RVO {
  5. using Pathfinding.Util;
  6. /// <summary>
  7. /// Adds a navmesh as RVO obstacles.
  8. /// Add this to a scene in which has a navmesh or grid based graph, when scanning (or loading from cache) the graph
  9. /// it will be added as RVO obstacles to the RVOSimulator (which must exist in the scene).
  10. ///
  11. /// Warning: You should only have a single instance of this script in the scene, otherwise it will add duplicate
  12. /// obstacles and thereby increasing the CPU usage.
  13. ///
  14. /// If you update a graph during runtime the obstacles need to be recalculated which has a performance penalty.
  15. /// This can be quite significant for larger graphs.
  16. ///
  17. /// In the screenshot the generated obstacles are visible in red.
  18. /// [Open online documentation to see images]
  19. /// </summary>
  20. [AddComponentMenu("Pathfinding/Local Avoidance/RVO Navmesh")]
  21. [HelpURL("http://arongranberg.com/astar/documentation/stable/class_pathfinding_1_1_r_v_o_1_1_r_v_o_navmesh.php")]
  22. public class RVONavmesh : GraphModifier {
  23. /// <summary>
  24. /// Height of the walls added for each obstacle edge.
  25. /// If a graph contains overlapping regions (e.g multiple floor in a building)
  26. /// you should set this low enough so that edges on different levels do not interfere,
  27. /// but high enough so that agents cannot move over them by mistake.
  28. /// </summary>
  29. public float wallHeight = 5;
  30. /// <summary>Obstacles currently added to the simulator</summary>
  31. readonly List<ObstacleVertex> obstacles = new List<ObstacleVertex>();
  32. /// <summary>Last simulator used</summary>
  33. Simulator lastSim;
  34. public override void OnPostCacheLoad () {
  35. OnLatePostScan();
  36. }
  37. public override void OnGraphsPostUpdate () {
  38. OnLatePostScan();
  39. }
  40. public override void OnLatePostScan () {
  41. if (!Application.isPlaying) return;
  42. Profiler.BeginSample("Update RVO Obstacles From Graphs");
  43. RemoveObstacles();
  44. NavGraph[] graphs = AstarPath.active.graphs;
  45. RVOSimulator rvosim = RVOSimulator.active;
  46. if (rvosim == null) throw new System.NullReferenceException("No RVOSimulator could be found in the scene. Please add one to any GameObject");
  47. // Remember which simulator these obstacles were added to
  48. lastSim = rvosim.GetSimulator();
  49. for (int i = 0; i < graphs.Length; i++) {
  50. RecastGraph recast = graphs[i] as RecastGraph;
  51. INavmesh navmesh = graphs[i] as INavmesh;
  52. GridGraph grid = graphs[i] as GridGraph;
  53. if (recast != null) {
  54. foreach (var tile in recast.GetTiles()) {
  55. AddGraphObstacles(lastSim, tile);
  56. }
  57. } else if (navmesh != null) {
  58. AddGraphObstacles(lastSim, navmesh);
  59. } else if (grid != null) {
  60. AddGraphObstacles(lastSim, grid);
  61. }
  62. }
  63. Profiler.EndSample();
  64. }
  65. protected override void OnDisable () {
  66. base.OnDisable();
  67. RemoveObstacles();
  68. }
  69. /// <summary>Removes all obstacles which have been added by this component</summary>
  70. public void RemoveObstacles () {
  71. if (lastSim != null) {
  72. for (int i = 0; i < obstacles.Count; i++) lastSim.RemoveObstacle(obstacles[i]);
  73. lastSim = null;
  74. }
  75. obstacles.Clear();
  76. }
  77. /// <summary>Adds obstacles for a grid graph</summary>
  78. void AddGraphObstacles (Pathfinding.RVO.Simulator sim, GridGraph grid) {
  79. bool reverse = Vector3.Dot(grid.transform.TransformVector(Vector3.up), sim.movementPlane == MovementPlane.XY ? Vector3.back : Vector3.up) > 0;
  80. GraphUtilities.GetContours(grid, vertices => {
  81. // Check if the contour is traced in the wrong direction from the one we want it in.
  82. // If we did not do this then instead of the obstacles keeping the agents OUT of the walls
  83. // they would keep them INSIDE the walls.
  84. if (reverse) System.Array.Reverse(vertices);
  85. obstacles.Add(sim.AddObstacle(vertices, wallHeight, true));
  86. }, wallHeight*0.4f);
  87. }
  88. /// <summary>Adds obstacles for a navmesh/recast graph</summary>
  89. void AddGraphObstacles (Pathfinding.RVO.Simulator simulator, INavmesh navmesh) {
  90. GraphUtilities.GetContours(navmesh, (vertices, cycle) => {
  91. var verticesV3 = new Vector3[vertices.Count];
  92. for (int i = 0; i < verticesV3.Length; i++) verticesV3[i] = (Vector3)vertices[i];
  93. // Pool the 'vertices' list to reduce allocations
  94. ListPool<Int3>.Release(vertices);
  95. obstacles.Add(simulator.AddObstacle(verticesV3, wallHeight, cycle));
  96. });
  97. }
  98. }
  99. }