Below is my actual source code (RVOGridGraph.cs) if somebody want to try it (need A* Pro). If you own A* PRO, feel free to use and enhance it
It can be used the same way as RVONavmesh (see Example11_RVO) but for a GridGraph. I have personally tested it on the terrain demo (Example2_Terrain) with success and without a big drop of the FPS.
@ Aron Granberg : if posting here some code derived from the A* Pro is a problem, just tell me and I’ll remove it.
`
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Pathfinding;
using Pathfinding.RVO;
/** Adds a GridGraph as RVO obstacles.
-
Add this to a scene in which has a GridGrah based graph, when scanning (or loading from cache) the graph
-
it will be added as RVO obstacles to the RVOSimulator (which must exist in the scene).
-
\astarpro
/
[AddComponentMenu(“Local Avoidance/RVOGridGraph”)]
public class RVOGridGraph : GraphModifier
{
/* Height of the walls added for each obstacle edge.- If a graph contains overlapping you should set this low enough so
- that edges on different levels do not interfere, but high enough so that
- agents cannot move over them by mistake.
*/
public float wallHeight = 5;
/** Obstacles currently added to the simulator */
private List obstacles = new List();/** Last simulator used */
private Simulator lastSim = null;public override void OnPostCacheLoad()
{
OnLatePostScan();
}public override void OnLatePostScan()
{
if (!Application.isPlaying)
return;RemoveObstacles(); NavGraph[] graphs = AstarPath.active.graphs; RVOSimulator rvosim = FindObjectOfType(typeof(RVOSimulator)) as RVOSimulator; if (rvosim == null) throw new System.NullReferenceException("No RVOSimulator could be found in the scene. Please add one to any GameObject"); Pathfinding.RVO.Simulator sim = rvosim.GetSimulator(); for (int i = 0; i < graphs.Length; i++) { AddGraphObstacles(sim, graphs[i]); } sim.UpdateObstacles();
}
/** Removes obstacles which were added with AddGraphObstacles */
public void RemoveObstacles()
{
if (lastSim == null)
return;Pathfinding.RVO.Simulator sim = lastSim; lastSim = null; for (int i = 0; i < obstacles.Count; i++) sim.RemoveObstacle(obstacles[i]); obstacles.Clear();
}
/** Adds RVO obstacles for a Grid Graph */
public void AddGraphObstacles(Pathfinding.RVO.Simulator sim, NavGraph graph)
{
if (obstacles.Count > 0 && lastSim != null && lastSim != sim)
{
Debug.LogError(“Simulator has changed but some old obstacles are still added for the previous simulator. Deleting previous obstacles.”);
RemoveObstacles();
}//Remember which simulator these obstacles were added to lastSim = sim; GridGraph gg = graph as GridGraph; if (gg == null) { return; } Node[] nodes = graph.nodes; for (int w = 0; w < gg.width; w++) { for (int d = 0; d < gg.depth; d++) { int iA = d * gg.width + w; if (nodes[iA].walkable == false) { /* * Quarters order ("A" is the tested node) : * 3 | 4 * --A--B * 2 | 1 * C D */ // Quarter 1 if ((w < (gg.width - 1)) && (d > 0)) { ComputeQuarter(sim, gg, w, d, 1, 0, 0, -1, 1, -1); } // Quarter 2 if ((w > 0) && (d > 0)) { ComputeQuarter(sim, gg, w, d, 0, -1, -1, 0, -1, -1); } // Quarter 3 if ((w > 0) && (d < (gg.depth - 1))) { ComputeQuarter(sim, gg, w, d, -1, 0, 0, 1, -1, 1); } // Quarter 4 if ((w < (gg.width - 1)) && (d < (gg.depth - 1))) { ComputeQuarter(sim, gg, w, d, 0, 1, 1, 0, 1, 1); } } } } Debug.Log(string.Format("RVOGridGraph.AddGraphObstacles() : {0} obstacles", obstacles.Count));
}
/** Compute a quarter of 4 nodes (A, B, C, D) where A is unwalkable and add AB or AD ObstacleVertex if needed */
private void ComputeQuarter(Pathfinding.RVO.Simulator sim, GridGraph gg, int w, int d, int wB, int dB, int wC, int dC, int wD, int dD)
{
Node[] nodes = gg.nodes;int iA = (d + 0) * gg.width + w + 0; int iB = (d + dB) * gg.width + w + wB; int iC = (d + dC) * gg.width + w + wC; int iD = (d + dD) * gg.width + w + wD; bool nodeB = nodes[iB].walkable; bool nodeC = nodes[iC].walkable; bool nodeD = nodes[iD].walkable; if ((nodeB == false) && (nodeC == true) && (nodeD == true)) { obstacles.Add(sim.AddObstacle((Vector3)nodes[iA].position, (Vector3)nodes[iB].position, wallHeight)); } if ((nodeB == false) && (nodeC == true) && (nodeD == false)) { obstacles.Add(sim.AddObstacle((Vector3)nodes[iA].position, (Vector3)nodes[iD].position, wallHeight)); }
}
/** Draws Gizmos */
public void OnDrawGizmos()
{
OnDrawGizmos(false);
}/** Draws Gizmos */
public void OnDrawGizmosSelected()
{
OnDrawGizmos(true);
}/** Draws Gizmos */
public void OnDrawGizmos(bool selected)
{
Gizmos.color = new Color(0.615f, 1, 0.06f, selected ? 1.0f : 0.7f);foreach (ObstacleVertex ov in obstacles) { if (ov.next == null) throw new System.InvalidOperationException("RVOGridGraph.OnDrawGizmos() : obstacles[...].next == null"); Vector3 a = ov.position; Vector3 b = ov.next.position; Gizmos.DrawLine(a, b); if (selected) { // Draw the little arrow to show the direction of the obstacle Vector3 avg = (a + b) * 0.5f; Vector3 tang = (b - a).normalized; if (tang != Vector3.zero) { Vector3 normal = Vector3.Cross(Vector3.up, tang); Gizmos.DrawLine(avg, avg + normal); Gizmos.DrawLine(avg + normal, avg + normal * 0.5f + tang * 0.5f); Gizmos.DrawLine(avg + normal, avg + normal * 0.5f - tang * 0.5f); } } }
}
}
`