Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using UnityEngine;
- using System.Collections;
- using System.Collections.Generic;
- using System.Threading;
- [CreateAssetMenu(fileName = "Seeker", menuName = "RTSObjects/Seeker", order = 1)]
- public class Seeker : Actor
- {
- public override void Clone(ListObject tar)
- {
- base.Clone(tar);
- Seeker t = tar as Seeker;
- Template = t.Template;
- ingameObject = t.ingameObject;
- Speed = t.Speed;
- }
- public List<NodeElement> path = new List<NodeElement>();
- public NodeElement curNode;
- public NodeElement LastDestination;
- Transform tr;
- public NodeElement LastPathElement()
- {
- return path[path.Count - 1];
- }
- public override void Spawn(NodeElement p)
- {
- base.Spawn(p);
- tr = ingameObject.transform;
- curNode = PathfindingMap.VecToNode(Mathf.RoundToInt(tr.position.x), Mathf.RoundToInt(tr.position.z));
- path.Add(curNode);
- LastDestination = curNode;
- curNode.occupied = this;
- }
- public Animator anim;
- public float Speed = 4;
- public Quaternion DesiredRotation;
- protected virtual void Rotate()
- {
- if (path.Count > 1)
- {
- DesiredRotation = Quaternion.LookRotation(path[1].pos() - curNode.pos());
- tr.rotation = Quaternion.Slerp(tr.rotation, DesiredRotation, Time.deltaTime * 4);
- }
- }
- public bool StoppedMoving()
- {
- return path.Count <= 1 ;
- }
- float recalculateCooldown = 0;
- protected void RecalculatePath()
- {
- if (path.Count > 1)
- {
- if (path[1].occupied != null && recalculateCooldown > 1)
- {
- recalculateCooldown = 0;
- SetDestination(LastDestination, true);
- }
- else
- {
- recalculateCooldown += Time.deltaTime;
- }
- }
- /* else
- {
- if (curNode.occupied != this)
- {
- SetDestination(curNode, true);
- }
- }*/
- if (recalculating)
- {
- recalculateTimer += Time.deltaTime;
- if (recalculateTimer > 0.5f)
- {
- recalculateTimer = 0;
- recalculating = false;
- SetDestination(LastDestination, true);
- }
- }
- }
- public override void LateUpdate()
- {
- if (path.Count > 1)
- {
- for (int i = 0; i < path.Count - 1; i++)
- {
- Debug.DrawLine(path[i].pos(), path[i + 1].pos(), Color.blue);
- }
- }
- RecalculatePath();
- Camera main = Camera.main;
- RaycastHit hit;
- Ray ray = main.ScreenPointToRay(Input.mousePosition);
- if (Physics.Raycast(ray, out hit))
- {
- if (Input.GetKeyDown(KeyCode.Mouse0))
- SetDestination(SquareGrid.GetNodeAt((int)hit.point.x, (int)hit.point.z), false);
- }
- Rotate();
- if (path.Count > 1)
- {
- Vector3 pos = path[1].pos();
- tr.position = Vector3.Slerp(tr.position, pos, Time.deltaTime * Speed);
- if (Vector3.Distance(tr.position, pos) < 0.4f)
- {
- path[0].occupied = null;
- path.RemoveAt(0);
- path[0].occupied = this;
- curNode = path[0];
- }
- // anim.SetFloat("Speed", 1);
- }
- else
- {
- if (path.Count == 0)
- {
- path.Add(curNode);
- }
- path[0].occupied = this;
- // anim.SetFloat("Speed", 0);
- }
- }
- public void SetDestination(Vector3 _pos, bool recalculating = false)
- {
- int x = Mathf.RoundToInt(_pos.x);
- int y = Mathf.RoundToInt(_pos.z);
- SetDestination(PathfindingMap.VecToNode(x, y), recalculating);
- }
- Thread PathFinder;
- public void SetDestination(NodeElement goal, bool recalculating = false)
- {
- if (goal != null)
- if (SquareGrid.InBounds(goal))
- {
- if ((goal != curNode || recalculating) && (goal != LastDestination || recalculating == true))
- {
- LastDestination = goal;
- goal = SquareGrid.FindNearestReachable(this, goal, recalculating);
- PathFinder = new Thread(() => MultiThreadAStar(goal));
- PathFinder.Start();
- }
- }
- }
- protected List<NodeElement> searchedNodes = new List<NodeElement>();
- static public double Heuristic(NodeElement a, NodeElement b)
- {
- return Mathf.Abs(a.x - b.x) + Mathf.Abs(a.y - b.y);
- }
- public NodeElement _start, _goal, closestPossible;
- PriorityQueue frontier;
- public static int MaxNodesPerSearch = 250;
- public Dictionary<NodeElement, NodeElement> camefrom = new Dictionary<NodeElement, NodeElement>();
- public Dictionary<NodeElement, double> costsofar = new Dictionary<NodeElement, double>();
- protected bool unreachableTarget = false;
- //gets called as a new thread
- public void MultiThreadAStar(NodeElement goal)
- {
- //reference to the map
- SquareGrid graph = PathfindingMap.grid();
- //frontier/priority que
- frontier = new PriorityQueue();
- //add the current node as the start of the frontier
- frontier.Enqueue(curNode, 0);
- _start = curNode;
- _goal = goal;
- camefrom.Clear();
- costsofar.Clear();
- //first node came from itself, cost 0
- camefrom[_start] = _start;
- costsofar[_start] = 0;
- closestPossible = _start;
- //do this until the frontier becomes empty (or we reach the goal)
- while (frontier.Count > 0)
- {
- //current node is the one closest to the goal
- NodeElement current = frontier.Dequeue();
- if (current.Equals(goal))
- {
- break;
- }
- //regular A* neighbors, in other words everyone surrounding the current node
- foreach (var next in SquareGrid.Neighbors(current, this))
- {
- //ignore it if it's occupied by another unit
- if (next.occupied == null)
- {
- //add it to the optimal paths if it isn't in the frontier, or it's cost is lower than the current one
- double newCost = costsofar[current] + graph.Cost(current, next);
- if (!costsofar.ContainsKey(next)
- || newCost < costsofar[next])
- {
- double h = Heuristic(next, goal);
- double h2 = Heuristic(closestPossible, goal);
- double priority = newCost + Heuristic(next, goal);
- frontier.Enqueue(next, priority);
- camefrom[next] = current;
- costsofar[next] = newCost;
- //save the closest node to the goal, in case we can't reach the goal
- if (h2 > h)
- {
- closestPossible = next;
- }
- }
- }
- }
- }
- //reconstruct the path
- FindShortestPath();
- }
- bool recalculating = false;
- float recalculateTimer = 0;
- public void FindShortestPath()
- {
- path.Clear();
- NodeElement next = _goal;
- //end of the path is the closest node to the goal
- if (!camefrom.ContainsKey(next))
- {
- next = closestPossible;
- }
- path.Add(next);
- for (int i = 0; i < camefrom.Count; i++)
- {
- next = camefrom[next];
- path.Add(next);
- if (next == _start)
- {
- path.Reverse();
- break;
- }
- }
- //if the path is too short, the unit was probably surrounded and couldn't move, restart the path in a second or so
- if (path.Count <= 2 && Vector3.Distance(curNode.pos(), LastDestination.pos()) > 2.5f)
- {
- recalculating = true;
- recalculateTimer = 0;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement