110 lines
4.8 KiB
C#
110 lines
4.8 KiB
C#
using System.Collections.Generic;
|
|
using Pathfinding.Util;
|
|
|
|
namespace Pathfinding {
|
|
/// <summary>
|
|
/// Contains useful functions for updating graphs.
|
|
/// This class works a lot with the GraphNode class, a useful function to get nodes is <see cref="AstarPath.GetNearest"/>.
|
|
///
|
|
/// See: <see cref="AstarPath.GetNearest"/>
|
|
/// See: <see cref="Pathfinding.PathUtilities"/>
|
|
///
|
|
/// \since Added in 3.1
|
|
///
|
|
/// \ingroup utils
|
|
/// </summary>
|
|
public static class GraphUpdateUtilities {
|
|
/// <summary>
|
|
/// Updates graphs and checks if all nodes are still reachable from each other.
|
|
/// Graphs are updated, then a check is made to see if the nodes are still reachable from each other.
|
|
/// If they are not, the graphs are reverted to before the update and false is returned.\n
|
|
/// This is slower than a normal graph update.
|
|
/// All queued graph updates and thread safe callbacks will be flushed during this function.
|
|
///
|
|
/// Returns: True if the given nodes are still reachable from each other after the guo has been applied. False otherwise.
|
|
///
|
|
/// <code>
|
|
/// var guo = new GraphUpdateObject(tower.GetComponent<Collider>().bounds);
|
|
/// var spawnPointNode = AstarPath.active.GetNearest(spawnPoint.position).node;
|
|
/// var goalNode = AstarPath.active.GetNearest(goalPoint.position).node;
|
|
///
|
|
/// if (GraphUpdateUtilities.UpdateGraphsNoBlock(guo, spawnPointNode, goalNode, false)) {
|
|
/// // Valid tower position
|
|
/// // Since the last parameter (which is called "alwaysRevert") in the method call was false
|
|
/// // The graph is now updated and the game can just continue
|
|
/// } else {
|
|
/// // Invalid tower position. It blocks the path between the spawn point and the goal
|
|
/// // The effect on the graph has been reverted
|
|
/// Destroy(tower);
|
|
/// }
|
|
/// </code>
|
|
/// </summary>
|
|
/// <param name="guo">The GraphUpdateObject to update the graphs with</param>
|
|
/// <param name="node1">Node which should have a valid path to node2. All nodes should be walkable or false will be returned.</param>
|
|
/// <param name="node2">Node which should have a valid path to node1. All nodes should be walkable or false will be returned.</param>
|
|
/// <param name="alwaysRevert">If true, reverts the graphs to the old state even if no blocking occurred</param>
|
|
public static bool UpdateGraphsNoBlock (GraphUpdateObject guo, GraphNode node1, GraphNode node2, bool alwaysRevert = false) {
|
|
List<GraphNode> buffer = ListPool<GraphNode>.Claim();
|
|
|
|
buffer.Add(node1);
|
|
buffer.Add(node2);
|
|
|
|
bool worked = UpdateGraphsNoBlock(guo, buffer, alwaysRevert);
|
|
ListPool<GraphNode>.Release(ref buffer);
|
|
return worked;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Updates graphs and checks if all nodes are still reachable from each other.
|
|
/// Graphs are updated, then a check is made to see if the nodes are still reachable from each other.
|
|
/// If they are not, the graphs are reverted to before the update and false is returned.
|
|
/// This is slower than a normal graph update.
|
|
/// All queued graph updates will be flushed during this function.
|
|
///
|
|
/// Returns: True if the given nodes are still reachable from each other after the guo has been applied. False otherwise.
|
|
/// </summary>
|
|
/// <param name="guo">The GraphUpdateObject to update the graphs with</param>
|
|
/// <param name="nodes">Nodes which should have valid paths between them. All nodes should be walkable or false will be returned.</param>
|
|
/// <param name="alwaysRevert">If true, reverts the graphs to the old state even if no blocking occurred</param>
|
|
public static bool UpdateGraphsNoBlock (GraphUpdateObject guo, List<GraphNode> nodes, bool alwaysRevert = false) {
|
|
bool worked;
|
|
|
|
// Pause pathfinding while modifying the graphs
|
|
var graphLock = AstarPath.active.PausePathfinding();
|
|
|
|
try {
|
|
// Make sure any pending graph updates have been done before we start
|
|
AstarPath.active.FlushGraphUpdates();
|
|
|
|
// Make sure all nodes are walkable
|
|
for (int i = 0; i < nodes.Count; i++) if (!nodes[i].Walkable) return false;
|
|
|
|
// Track changed nodes to enable reversion of the guo
|
|
guo.trackChangedNodes = true;
|
|
|
|
AstarPath.active.UpdateGraphs(guo);
|
|
|
|
// Update the graphs immediately
|
|
AstarPath.active.FlushGraphUpdates();
|
|
|
|
// Check if all nodes are in the same area and that they are walkable, i.e that there are paths between all of them
|
|
worked = PathUtilities.IsPathPossible(nodes);
|
|
|
|
// If it did not work, revert the GUO
|
|
if (!worked || alwaysRevert) {
|
|
guo.RevertFromBackup();
|
|
// Recalculate connected components
|
|
AstarPath.active.hierarchicalGraph.RecalculateIfNecessary();
|
|
}
|
|
} finally {
|
|
graphLock.Release();
|
|
}
|
|
|
|
// Disable tracking nodes, not strictly necessary, but will slightly reduce the cance that some user causes errors
|
|
guo.trackChangedNodes = false;
|
|
|
|
return worked;
|
|
}
|
|
}
|
|
}
|