summaryrefslogtreecommitdiff
path: root/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/ExampleScenes/Scenes/HexagonalTurnBased/TurnBasedManager.cs
diff options
context:
space:
mode:
authorchai <215380520@qq.com>2024-05-23 10:08:29 +0800
committerchai <215380520@qq.com>2024-05-23 10:08:29 +0800
commit8722a9920c1f6119bf6e769cba270e63097f8e25 (patch)
tree2eaf9865de7fb1404546de4a4296553d8f68cc3b /Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/ExampleScenes/Scenes/HexagonalTurnBased/TurnBasedManager.cs
parent3ba4020b69e5971bb0df7ee08b31d10ea4d01937 (diff)
+ astar project
Diffstat (limited to 'Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/ExampleScenes/Scenes/HexagonalTurnBased/TurnBasedManager.cs')
-rw-r--r--Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/ExampleScenes/Scenes/HexagonalTurnBased/TurnBasedManager.cs196
1 files changed, 196 insertions, 0 deletions
diff --git a/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/ExampleScenes/Scenes/HexagonalTurnBased/TurnBasedManager.cs b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/ExampleScenes/Scenes/HexagonalTurnBased/TurnBasedManager.cs
new file mode 100644
index 0000000..4523399
--- /dev/null
+++ b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/ExampleScenes/Scenes/HexagonalTurnBased/TurnBasedManager.cs
@@ -0,0 +1,196 @@
+using UnityEngine;
+using System.Collections;
+using System.Collections.Generic;
+using Pathfinding;
+using Pathfinding.Util;
+using UnityEngine.EventSystems;
+
+namespace Pathfinding.Examples {
+ /// <summary>Helper script in the example scene 'Turn Based'</summary>
+ [HelpURL("https://arongranberg.com/astar/documentation/stable/turnbasedmanager.html")]
+ public class TurnBasedManager : VersionedMonoBehaviour {
+ TurnBasedAI selected;
+
+ public float movementSpeed;
+ public GameObject nodePrefab;
+ public LayerMask layerMask;
+
+ List<GameObject> possibleMoves = new List<GameObject>();
+ EventSystem eventSystem;
+
+ public State state = State.SelectUnit;
+
+ public enum State {
+ SelectUnit,
+ SelectTarget,
+ Move
+ }
+
+ protected override void Awake () {
+ base.Awake();
+ eventSystem = UnityCompatibility.FindAnyObjectByType<EventSystem>();
+ }
+
+ void Update () {
+ var mousePos = Input.mousePosition;
+
+ // If the game view is not active, the mouse position can be infinite
+ if (!float.IsFinite(mousePos.x)) return;
+
+ Ray ray = Camera.main.ScreenPointToRay(mousePos);
+
+ // Ignore any input while the mouse is over a UI element
+ if (eventSystem.IsPointerOverGameObject()) {
+ return;
+ }
+
+ if (state == State.SelectTarget) {
+ HandleButtonUnderRay(ray);
+ }
+
+ if (state == State.SelectUnit || state == State.SelectTarget) {
+ if (Input.GetKeyDown(KeyCode.Mouse0)) {
+ var unitUnderMouse = GetByRay<TurnBasedAI>(ray);
+
+ if (unitUnderMouse != null) {
+ Select(unitUnderMouse);
+ DestroyPossibleMoves();
+ GeneratePossibleMoves(selected);
+ state = State.SelectTarget;
+ }
+ }
+ }
+ }
+
+ // TODO: Move to separate class
+ void HandleButtonUnderRay (Ray ray) {
+ var button = GetByRay<Astar3DButton>(ray);
+
+ if (button != null && Input.GetKeyDown(KeyCode.Mouse0)) {
+ button.OnClick();
+
+ DestroyPossibleMoves();
+ state = State.Move;
+ StartCoroutine(MoveToNode(selected, button.node));
+ }
+ }
+
+ T GetByRay<T>(Ray ray) where T : class {
+ RaycastHit hit;
+
+ if (Physics.Raycast(ray, out hit, float.PositiveInfinity, layerMask)) {
+ return hit.transform.GetComponentInParent<T>();
+ }
+ return null;
+ }
+
+ void Select (TurnBasedAI unit) {
+ selected = unit;
+ }
+
+ IEnumerator MoveToNode (TurnBasedAI unit, GraphNode node) {
+ var path = ABPath.Construct(unit.transform.position, (Vector3)node.position);
+
+ path.traversalProvider = unit.traversalProvider;
+
+ // Schedule the path for calculation
+ AstarPath.StartPath(path);
+
+ // Wait for the path calculation to complete
+ yield return StartCoroutine(path.WaitForPath());
+
+ if (path.error) {
+ // Not obvious what to do here, but show the possible moves again
+ // and let the player choose another target node
+ // Likely a node was blocked between the possible moves being
+ // generated and the player choosing which node to move to
+ Debug.LogError("Path failed:\n" + path.errorLog);
+ state = State.SelectTarget;
+ GeneratePossibleMoves(selected);
+ yield break;
+ }
+
+ // Set the target node so other scripts know which
+ // node is the end point in the path
+ unit.targetNode = path.path[path.path.Count - 1];
+
+ yield return StartCoroutine(MoveAlongPath(unit, path, movementSpeed));
+
+ unit.blocker.BlockAtCurrentPosition();
+
+ // Select a new unit to move
+ state = State.SelectUnit;
+ }
+
+ /// <summary>[MoveAlongPath]</summary>
+ /// <summary>Interpolates the unit along the path</summary>
+ static IEnumerator MoveAlongPath (TurnBasedAI unit, ABPath path, float speed) {
+ if (path.error || path.vectorPath.Count == 0)
+ throw new System.ArgumentException("Cannot follow an empty path");
+
+ // Very simple movement, just interpolate using a catmull-rom spline
+ float distanceAlongSegment = 0;
+ for (int i = 0; i < path.vectorPath.Count - 1; i++) {
+ var p0 = path.vectorPath[Mathf.Max(i-1, 0)];
+ // Start of current segment
+ var p1 = path.vectorPath[i];
+ // End of current segment
+ var p2 = path.vectorPath[i+1];
+ var p3 = path.vectorPath[Mathf.Min(i+2, path.vectorPath.Count-1)];
+
+ // Approximate the length of the spline
+ var segmentLength = Vector3.Distance(p1, p2);
+
+ // Move the agent forward each frame, until we reach the end of the segment
+ while (distanceAlongSegment < segmentLength) {
+ // Use a Catmull-rom spline to smooth the path. See https://en.wikipedia.org/wiki/Cubic_Hermite_spline#Catmull%E2%80%93Rom_spline
+ var interpolatedPoint = AstarSplines.CatmullRom(p0, p1, p2, p3, distanceAlongSegment / segmentLength);
+ unit.transform.position = interpolatedPoint;
+ yield return null;
+ distanceAlongSegment += Time.deltaTime * speed;
+ }
+
+ distanceAlongSegment -= segmentLength;
+ }
+
+ // Move the agent to the final point in the path
+ unit.transform.position = path.vectorPath[path.vectorPath.Count - 1];
+ }
+ /// <summary>[MoveAlongPath]</summary>
+
+ void DestroyPossibleMoves () {
+ foreach (var go in possibleMoves) {
+ GameObject.Destroy(go);
+ }
+ possibleMoves.Clear();
+ }
+
+ /// <summary>[GeneratePossibleMoves]</summary>
+ void GeneratePossibleMoves (TurnBasedAI unit) {
+ var path = ConstantPath.Construct(unit.transform.position, unit.movementPoints * 1000 + 1);
+
+ path.traversalProvider = unit.traversalProvider;
+
+ // Schedule the path for calculation
+ AstarPath.StartPath(path);
+
+ // Force the path request to complete immediately
+ // This assumes the graph is small enough that
+ // this will not cause any lag
+ path.BlockUntilCalculated();
+
+ foreach (var node in path.allNodes) {
+ if (node != path.startNode) {
+ // Create a new node prefab to indicate a node that can be reached
+ // NOTE: If you are going to use this in a real game, you might want to
+ // use an object pool to avoid instantiating new GameObjects all the time
+ var go = GameObject.Instantiate(nodePrefab, (Vector3)node.position, Quaternion.identity) as GameObject;
+ possibleMoves.Add(go);
+
+ go.GetComponent<Astar3DButton>().node = node;
+ }
+ }
+ }
+ /// <summary>[GeneratePossibleMoves]</summary>
+ }
+}