summaryrefslogtreecommitdiff
path: root/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/TurnBased
diff options
context:
space:
mode:
Diffstat (limited to 'Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/TurnBased')
-rw-r--r--Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/TurnBased/BlockManager.cs181
-rw-r--r--Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/TurnBased/BlockManager.cs.meta12
-rw-r--r--Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/TurnBased/SingleNodeBlocker.cs70
-rw-r--r--Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/TurnBased/SingleNodeBlocker.cs.meta12
4 files changed, 275 insertions, 0 deletions
diff --git a/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/TurnBased/BlockManager.cs b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/TurnBased/BlockManager.cs
new file mode 100644
index 0000000..0a725e4
--- /dev/null
+++ b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/TurnBased/BlockManager.cs
@@ -0,0 +1,181 @@
+using UnityEngine;
+using System.Collections.Generic;
+
+namespace Pathfinding {
+ using Pathfinding.Util;
+
+ /// <summary>
+ /// Manager for blocker scripts such as SingleNodeBlocker.
+ ///
+ /// This is part of the turn based utilities. It can be used for
+ /// any game, but it is primarily intended for turn based games.
+ ///
+ /// See: TurnBasedAI
+ /// See: turnbased (view in online documentation for working links)
+ /// See: traversal_provider (view in online documentation for working links)
+ /// </summary>
+ [HelpURL("https://arongranberg.com/astar/documentation/stable/blockmanager.html")]
+ public class BlockManager : VersionedMonoBehaviour {
+ /// <summary>Contains info on which SingleNodeBlocker objects have blocked a particular node</summary>
+ Dictionary<GraphNode, List<SingleNodeBlocker> > blocked = new Dictionary<GraphNode, List<SingleNodeBlocker> >();
+
+ public enum BlockMode {
+ /// <summary>All blockers except those in the TraversalProvider.selector list will block</summary>
+ AllExceptSelector,
+ /// <summary>Only elements in the TraversalProvider.selector list will block</summary>
+ OnlySelector
+ }
+
+ /// <summary>Blocks nodes according to a BlockManager</summary>
+ public class TraversalProvider : ITraversalProvider {
+ /// <summary>Holds information about which nodes are occupied</summary>
+ readonly BlockManager blockManager;
+
+ /// <summary>Affects which nodes are considered blocked</summary>
+ public BlockMode mode { get; private set; }
+
+ /// <summary>
+ /// Blockers for this path.
+ /// The effect depends on <see cref="mode"/>.
+ ///
+ /// Note that having a large selector has a performance cost.
+ ///
+ /// See: mode
+ /// </summary>
+ readonly List<SingleNodeBlocker> selector;
+
+ public TraversalProvider (BlockManager blockManager, BlockMode mode, List<SingleNodeBlocker> selector) {
+ if (blockManager == null) throw new System.ArgumentNullException("blockManager");
+ if (selector == null) throw new System.ArgumentNullException("selector");
+
+ this.blockManager = blockManager;
+ this.mode = mode;
+ this.selector = selector;
+ }
+
+ #region ITraversalProvider implementation
+
+ public bool CanTraverse (Path path, GraphNode node) {
+ // This first IF is the default implementation that is used when no traversal provider is used
+ if (!node.Walkable || (path != null && (path.enabledTags >> (int)node.Tag & 0x1) == 0)) {
+ return false;
+ } else if (mode == BlockMode.OnlySelector) {
+ return !blockManager.NodeContainsAnyOf(node, selector);
+ } else {
+ // assume mode == BlockMode.AllExceptSelector
+ return !blockManager.NodeContainsAnyExcept(node, selector);
+ }
+ }
+
+ public bool CanTraverse (Path path, GraphNode from, GraphNode to) {
+ return CanTraverse(path, to);
+ }
+
+ public uint GetTraversalCost (Path path, GraphNode node) {
+ // Same as default implementation
+ return path.GetTagPenalty((int)node.Tag) + node.Penalty;
+ }
+
+ // This can be omitted in Unity 2021.3 and newer because a default implementation (returning true) can be used there.
+ public bool filterDiagonalGridConnections {
+ get {
+ return true;
+ }
+ }
+
+ #endregion
+ }
+
+ void Start () {
+ if (!AstarPath.active)
+ throw new System.Exception("No AstarPath object in the scene");
+ }
+
+ /// <summary>True if the node contains any blocker which is included in the selector list</summary>
+ public bool NodeContainsAnyOf (GraphNode node, List<SingleNodeBlocker> selector) {
+ List<SingleNodeBlocker> blockersInNode;
+
+ if (!blocked.TryGetValue(node, out blockersInNode)) {
+ return false;
+ }
+
+ for (int i = 0; i < blockersInNode.Count; i++) {
+ var inNode = blockersInNode[i];
+ for (int j = 0; j < selector.Count; j++) {
+ // Need to use ReferenceEquals because this code may be called from a separate thread
+ // and the equality comparison that Unity provides is not thread safe
+ if (System.Object.ReferenceEquals(inNode, selector[j])) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /// <summary>True if the node contains any blocker which is not included in the selector list</summary>
+ public bool NodeContainsAnyExcept (GraphNode node, List<SingleNodeBlocker> selector) {
+ List<SingleNodeBlocker> blockersInNode;
+
+ if (!blocked.TryGetValue(node, out blockersInNode)) {
+ return false;
+ }
+
+ for (int i = 0; i < blockersInNode.Count; i++) {
+ var inNode = blockersInNode[i];
+ bool found = false;
+ for (int j = 0; j < selector.Count; j++) {
+ // Need to use ReferenceEquals because this code may be called from a separate thread
+ // and the equality comparison that Unity provides is not thread safe
+ if (System.Object.ReferenceEquals(inNode, selector[j])) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) return true;
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Register blocker as being present at the specified node.
+ /// Calling this method multiple times will add multiple instances of the blocker to the node.
+ ///
+ /// Note: The node will not be blocked immediately. Instead the pathfinding
+ /// threads will be paused and then the update will be applied. It is however
+ /// guaranteed to be applied before the next path request is started.
+ /// </summary>
+ public void InternalBlock (GraphNode node, SingleNodeBlocker blocker) {
+ AstarPath.active.AddWorkItem(new AstarWorkItem(() => {
+ List<SingleNodeBlocker> blockersInNode;
+ if (!blocked.TryGetValue(node, out blockersInNode)) {
+ blockersInNode = blocked[node] = ListPool<SingleNodeBlocker>.Claim();
+ }
+
+ blockersInNode.Add(blocker);
+ }));
+ }
+
+ /// <summary>
+ /// Remove blocker from the specified node.
+ /// Will only remove a single instance, calling this method multiple
+ /// times will remove multiple instances of the blocker from the node.
+ ///
+ /// Note: The node will not be unblocked immediately. Instead the pathfinding
+ /// threads will be paused and then the update will be applied. It is however
+ /// guaranteed to be applied before the next path request is started.
+ /// </summary>
+ public void InternalUnblock (GraphNode node, SingleNodeBlocker blocker) {
+ AstarPath.active.AddWorkItem(new AstarWorkItem(() => {
+ List<SingleNodeBlocker> blockersInNode;
+ if (blocked.TryGetValue(node, out blockersInNode)) {
+ blockersInNode.Remove(blocker);
+
+ if (blockersInNode.Count == 0) {
+ blocked.Remove(node);
+ ListPool<SingleNodeBlocker>.Release(ref blockersInNode);
+ }
+ }
+ }));
+ }
+ }
+}
diff --git a/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/TurnBased/BlockManager.cs.meta b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/TurnBased/BlockManager.cs.meta
new file mode 100644
index 0000000..ff85dc9
--- /dev/null
+++ b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/TurnBased/BlockManager.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: df8c077ca577944689559bb9e97f9576
+timeCreated: 1453722739
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/TurnBased/SingleNodeBlocker.cs b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/TurnBased/SingleNodeBlocker.cs
new file mode 100644
index 0000000..496de8e
--- /dev/null
+++ b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/TurnBased/SingleNodeBlocker.cs
@@ -0,0 +1,70 @@
+using UnityEngine;
+
+namespace Pathfinding {
+ /// <summary>
+ /// Blocks single nodes in a graph.
+ ///
+ /// This is useful in turn based games where you want
+ /// units to avoid all other units while pathfinding
+ /// but not be blocked by itself.
+ ///
+ /// Note: To use this with a movement script, you have to assign the BlockManager's traversal provider to either <see cref="Seeker.traversalProvider"/> or <see cref="FollowerEntity.pathfindingSettings.traversalProvider"/>.
+ ///
+ /// See: TurnBasedAI for example usage
+ ///
+ /// See: BlockManager
+ /// See: turnbased (view in online documentation for working links)
+ /// See: traversal_provider (view in online documentation for working links)
+ /// </summary>
+ [HelpURL("https://arongranberg.com/astar/documentation/stable/singlenodeblocker.html")]
+ public class SingleNodeBlocker : VersionedMonoBehaviour {
+ public GraphNode lastBlocked { get; private set; }
+ public BlockManager manager;
+
+ /// <summary>
+ /// Block node closest to the position of this object.
+ ///
+ /// Will unblock the last node that was reserved (if any)
+ /// </summary>
+ public void BlockAtCurrentPosition () {
+ BlockAt(transform.position);
+ }
+
+ /// <summary>
+ /// Block node closest to the specified position.
+ ///
+ /// Will unblock the last node that was reserved (if any)
+ /// </summary>
+ public void BlockAt (Vector3 position) {
+ Unblock();
+ var node = AstarPath.active.GetNearest(position, NNConstraint.None).node;
+ if (node != null) {
+ Block(node);
+ }
+ }
+
+ /// <summary>
+ /// Block specified node.
+ ///
+ /// Will unblock the last node that was reserved (if any)
+ /// </summary>
+ public void Block (GraphNode node) {
+ if (node == null)
+ throw new System.ArgumentNullException("node");
+
+ manager.InternalBlock(node, this);
+ lastBlocked = node;
+ }
+
+ /// <summary>Unblock the last node that was blocked (if any)</summary>
+ public void Unblock () {
+ if (lastBlocked == null || lastBlocked.Destroyed) {
+ lastBlocked = null;
+ return;
+ }
+
+ manager.InternalUnblock(lastBlocked, this);
+ lastBlocked = null;
+ }
+ }
+}
diff --git a/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/TurnBased/SingleNodeBlocker.cs.meta b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/TurnBased/SingleNodeBlocker.cs.meta
new file mode 100644
index 0000000..bdd19e7
--- /dev/null
+++ b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/TurnBased/SingleNodeBlocker.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: b45e20632f1604fc6bb73e0e79cd7368
+timeCreated: 1451482127
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant: