Advertisement
Guest User

Untitled

a guest
Feb 10th, 2017
114
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 8.25 KB | None | 0 0
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Threading;
  5.  
  6. [CreateAssetMenu(fileName = "Seeker", menuName = "RTSObjects/Seeker", order = 1)]
  7. public class Seeker : Actor
  8. {
  9.     public override void Clone(ListObject tar)
  10.     {
  11.         base.Clone(tar);
  12.         Seeker t = tar as Seeker;
  13.         Template = t.Template;
  14.         ingameObject = t.ingameObject;
  15.         Speed = t.Speed;
  16.     }
  17.     public List<NodeElement> path = new List<NodeElement>();
  18.     public NodeElement curNode;
  19.     public NodeElement LastDestination;
  20.     Transform tr;
  21.     public NodeElement LastPathElement()
  22.     {
  23.         return path[path.Count - 1];
  24.     }
  25.  
  26.     public override void Spawn(NodeElement p)
  27.     {
  28.         base.Spawn(p);
  29.         tr = ingameObject.transform;
  30.         curNode = PathfindingMap.VecToNode(Mathf.RoundToInt(tr.position.x), Mathf.RoundToInt(tr.position.z));
  31.         path.Add(curNode);
  32.         LastDestination = curNode;
  33.         curNode.occupied = this;
  34.     }
  35.     public Animator anim;
  36.     public float Speed = 4;
  37.  
  38.     public Quaternion DesiredRotation;
  39.     protected virtual void Rotate()
  40.     {
  41.         if (path.Count > 1)
  42.         {
  43.             DesiredRotation = Quaternion.LookRotation(path[1].pos() - curNode.pos());
  44.             tr.rotation = Quaternion.Slerp(tr.rotation, DesiredRotation, Time.deltaTime * 4);
  45.  
  46.         }
  47.     }
  48.     public bool StoppedMoving()
  49.     {
  50.         return path.Count <= 1 ;
  51.     }
  52.     float recalculateCooldown = 0;
  53.     protected void RecalculatePath()
  54.     {
  55.         if (path.Count > 1)
  56.         {
  57.             if (path[1].occupied != null && recalculateCooldown > 1)
  58.             {
  59.                 recalculateCooldown = 0;
  60.                 SetDestination(LastDestination, true);
  61.             }
  62.             else
  63.             {
  64.                 recalculateCooldown += Time.deltaTime;
  65.             }
  66.         }
  67.        /* else
  68.         {
  69.             if (curNode.occupied != this)
  70.             {
  71.                 SetDestination(curNode, true);
  72.             }
  73.         }*/
  74.         if (recalculating)
  75.         {
  76.             recalculateTimer += Time.deltaTime;
  77.             if (recalculateTimer > 0.5f)
  78.             {
  79.                 recalculateTimer = 0;
  80.                 recalculating = false;
  81.                 SetDestination(LastDestination, true);
  82.             }
  83.         }
  84.     }
  85.     public override void LateUpdate()
  86.     {
  87.         if (path.Count > 1)
  88.         {
  89.             for (int i = 0; i < path.Count - 1; i++)
  90.             {
  91.                 Debug.DrawLine(path[i].pos(), path[i + 1].pos(), Color.blue);
  92.             }
  93.         }
  94.         RecalculatePath();
  95.         Camera main = Camera.main;
  96.         RaycastHit hit;
  97.         Ray ray = main.ScreenPointToRay(Input.mousePosition);
  98.  
  99.         if (Physics.Raycast(ray, out hit))
  100.         {
  101.             if (Input.GetKeyDown(KeyCode.Mouse0))
  102.                 SetDestination(SquareGrid.GetNodeAt((int)hit.point.x, (int)hit.point.z), false);
  103.         }
  104.         Rotate();
  105.         if (path.Count > 1)
  106.         {
  107.             Vector3 pos = path[1].pos();
  108.             tr.position = Vector3.Slerp(tr.position, pos, Time.deltaTime * Speed);
  109.             if (Vector3.Distance(tr.position, pos) < 0.4f)
  110.             {
  111.                 path[0].occupied = null;
  112.                 path.RemoveAt(0);
  113.                 path[0].occupied = this;
  114.                 curNode = path[0];
  115.             }
  116.             //  anim.SetFloat("Speed", 1);
  117.         }
  118.         else
  119.         {
  120.             if (path.Count == 0)
  121.             {
  122.                 path.Add(curNode);
  123.             }
  124.             path[0].occupied = this;
  125.             // anim.SetFloat("Speed", 0);
  126.         }
  127.  
  128.     }
  129.  
  130.     public void SetDestination(Vector3 _pos, bool recalculating = false)
  131.     {
  132.  
  133.         int x = Mathf.RoundToInt(_pos.x);
  134.         int y = Mathf.RoundToInt(_pos.z);
  135.         SetDestination(PathfindingMap.VecToNode(x, y), recalculating);
  136.     }
  137.     Thread PathFinder;
  138.     public void SetDestination(NodeElement goal, bool recalculating = false)
  139.     {
  140.         if (goal != null)
  141.             if (SquareGrid.InBounds(goal))
  142.             {
  143.                 if ((goal != curNode || recalculating) && (goal != LastDestination || recalculating == true))
  144.                 {
  145.                     LastDestination = goal;
  146.                     goal = SquareGrid.FindNearestReachable(this, goal, recalculating);
  147.                     PathFinder = new Thread(() => MultiThreadAStar(goal));
  148.                     PathFinder.Start();
  149.                 }
  150.             }
  151.     }
  152.     protected List<NodeElement> searchedNodes = new List<NodeElement>();
  153.  
  154.     static public double Heuristic(NodeElement a, NodeElement b)
  155.     {
  156.         return Mathf.Abs(a.x - b.x) + Mathf.Abs(a.y - b.y);
  157.     }
  158.     public NodeElement _start, _goal, closestPossible;
  159.     PriorityQueue frontier;
  160.     public static int MaxNodesPerSearch = 250;
  161.     public Dictionary<NodeElement, NodeElement> camefrom = new Dictionary<NodeElement, NodeElement>();
  162.     public Dictionary<NodeElement, double> costsofar = new Dictionary<NodeElement, double>();
  163.     protected bool unreachableTarget = false;
  164.     //gets called as a new thread
  165.     public void MultiThreadAStar(NodeElement goal)
  166.     {
  167.         //reference to the map
  168.         SquareGrid graph = PathfindingMap.grid();
  169.         //frontier/priority que
  170.         frontier = new PriorityQueue();
  171.         //add the current node as the start of the frontier
  172.         frontier.Enqueue(curNode, 0);
  173.         _start = curNode;
  174.         _goal = goal;
  175.         camefrom.Clear();
  176.         costsofar.Clear();
  177.         //first node came from itself, cost 0
  178.         camefrom[_start] = _start;
  179.         costsofar[_start] = 0;
  180.         closestPossible = _start;
  181.         //do this until the frontier becomes empty (or we reach the goal)
  182.         while (frontier.Count > 0)
  183.         {
  184.             //current node is the one closest to the goal
  185.             NodeElement current = frontier.Dequeue();
  186.             if (current.Equals(goal))
  187.             {
  188.                 break;
  189.             }
  190.             //regular A* neighbors, in other words everyone surrounding the current node
  191.             foreach (var next in SquareGrid.Neighbors(current, this))
  192.             {
  193.                 //ignore it if it's occupied by another unit
  194.                 if (next.occupied == null)
  195.                 {
  196.                     //add it to the optimal paths if it isn't in the frontier, or it's cost is lower than the current one
  197.                     double newCost = costsofar[current] + graph.Cost(current, next);
  198.                     if (!costsofar.ContainsKey(next)
  199.                       || newCost < costsofar[next])
  200.                     {
  201.                         double h = Heuristic(next, goal);
  202.                         double h2 = Heuristic(closestPossible, goal);
  203.                         double priority = newCost + Heuristic(next, goal);
  204.                         frontier.Enqueue(next, priority);
  205.                         camefrom[next] = current;
  206.                         costsofar[next] = newCost;
  207.                         //save the closest node to the goal, in case we can't reach the goal
  208.                         if (h2 > h)
  209.                         {
  210.                             closestPossible = next;
  211.                         }
  212.                     }
  213.                 }
  214.             }
  215.         }
  216.         //reconstruct the path
  217.         FindShortestPath();
  218.     }
  219.     bool recalculating = false;
  220.     float recalculateTimer = 0;
  221.     public void FindShortestPath()
  222.     {
  223.         path.Clear();
  224.         NodeElement next = _goal;
  225.         //end of the path is the closest node to the goal
  226.         if (!camefrom.ContainsKey(next))
  227.         {
  228.             next = closestPossible;
  229.         }
  230.         path.Add(next);
  231.         for (int i = 0; i < camefrom.Count; i++)
  232.         {
  233.             next = camefrom[next];
  234.             path.Add(next);
  235.             if (next == _start)
  236.             {
  237.                 path.Reverse();
  238.                 break;
  239.             }
  240.         }
  241.         //if the path is too short, the unit was probably surrounded and couldn't move, restart the path in a second or so
  242.         if (path.Count <= 2 && Vector3.Distance(curNode.pos(), LastDestination.pos()) > 2.5f)
  243.         {
  244.             recalculating = true;
  245.             recalculateTimer = 0;
  246.         }
  247.     }
  248. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement