/** Interpolates the unit along the path */ 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)]; var segmentLength = Vector3.Distance(p1, p2); while (distanceAlongSegment < segmentLength) { var interpolatedPoint = AstarSplines.CatmullRom(p0, p1, p2, p3, distanceAlongSegment / segmentLength); unit.transform.position = interpolatedPoint; yield return(null); distanceAlongSegment += Time.deltaTime * speed; } distanceAlongSegment -= segmentLength; } unit.transform.position = path.vectorPath[path.vectorPath.Count - 1]; }
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; } } }
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; }
void Select(TurnBasedAI unit) { selected = unit; }