Advertisement
Guest User

Untitled

a guest
Apr 2nd, 2015
1,019
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 8.07 KB | None | 0 0
  1. //#define ASTARDEBUG
  2. using UnityEngine;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using Pathfinding;
  6. using Pathfinding.RVO;
  7.  
  8. /** Base class for AIs.
  9.  *
  10.  * \see AIPath
  11.  * \see AI2DTopDown
  12.  */
  13. [RequireComponent(typeof(Seeker))]
  14. public abstract class AIPathBase : MonoBehaviour {
  15.    
  16.     /** Determines how often it will search for new paths.
  17.      * If you have fast moving targets or AIs, you might want to set it to a lower value.
  18.      * The value is in seconds between path requests.
  19.      */
  20.     public float repathRate = 0.5F;
  21.    
  22.     /** Target to move towards.
  23.      * The AI will try to follow/move towards this target.
  24.      * It can be a point on the ground where the player has clicked in an RTS for example, or it can be the player object in a zombie game.
  25.      */
  26.     public Transform target;
  27.    
  28.     /** Enables or disables searching for paths.
  29.      * Setting this to false does not stop any active path requests from being calculated or stop it from continuing to follow the current path.
  30.      * \see #canMove
  31.      */
  32.     public bool canSearch = true;
  33.    
  34.     /** Enables or disables movement.
  35.       * \see #canSearch */
  36.     public bool canMove = true;
  37.    
  38.     /** Maximum velocity.
  39.      * This is the maximum speed in world units per second.
  40.      */
  41.     public float speed = 3;
  42.    
  43.     /** Rotation speed.
  44.      * Rotation is calculated using Quaternion.SLerp. This variable represents the damping, the higher, the faster it will be able to rotate.
  45.      */
  46.     public float turningSpeed = 5;
  47.    
  48.     /** Distance from the target point where the AI will start to slow down.
  49.      * Note that this doesn't only affect the end point of the path
  50.      * but also any intermediate points, so be sure to set #forwardLook and #pickNextWaypointDist to a higher value than this
  51.      */
  52.     public float slowdownDistance = 0.6F;
  53.    
  54.     /** Determines within what range it will switch to target the next waypoint in the path */
  55.     public float pickNextWaypointDist = 2;
  56.    
  57.     /** Target point is Interpolated on the current segment in the path so that it has a distance of #forwardLook from the AI.
  58.       * See the detailed description of AIPath for an illustrative image */
  59.     public float forwardLook = 1;
  60.    
  61.     /** Distance to the end point to consider the end of path to be reached.
  62.      * When this has been reached, the AI will not move anymore until the target changes and OnTargetReached will be called.
  63.      */
  64.     public float endReachedDistance = 0.2F;
  65.    
  66.     /** Do a closest point on path check when receiving path callback.
  67.      * Usually the AI has moved a bit between requesting the path, and getting it back, and there is usually a small gap between the AI
  68.      * and the closest node.
  69.      * If this option is enabled, it will simulate, when the path callback is received, movement between the closest node and the current
  70.      * AI position. This helps to reduce the moments when the AI just get a new path back, and thinks it ought to move backwards to the start of the new path
  71.      * even though it really should just proceed forward.
  72.      */
  73.     public bool closestOnPathCheck = true;
  74.    
  75.     protected float minMoveScale = 0.05F;
  76.    
  77.     /** Cached Seeker component */
  78.     protected Seeker seeker;
  79.    
  80.     /** Cached Transform component */
  81.     protected Transform tr;
  82.    
  83.     /** Time when the last path request was sent */
  84.     protected float lastRepath = -9999;
  85.    
  86.     /** Current path which is followed */
  87.     protected Path path;
  88.    
  89.     /** Current index in the path which is current target */
  90.     protected int currentWaypointIndex = 0;
  91.    
  92.     /** Holds if the end-of-path is reached
  93.      * \see TargetReached */
  94.     protected bool targetReached = false;
  95.    
  96.     /** Only when the previous path has been returned should be search for a new path */
  97.     protected bool canSearchAgain = true;
  98.  
  99.     protected Vector3 lastFoundWaypointPosition;
  100.     protected float lastFoundWaypointTime = -9999;
  101.  
  102.     /** Returns if the end-of-path has been reached
  103.      * \see targetReached */
  104.     public bool TargetReached {
  105.         get {
  106.             return targetReached;
  107.         }
  108.     }
  109.    
  110.     /** Holds if the Start function has been run.
  111.      * Used to test if coroutines should be started in OnEnable to prevent calculating paths
  112.      * in the awake stage (or rather before start on frame 0).
  113.      */
  114.     private bool startHasRun = false;
  115.    
  116.     /** Initializes reference variables.
  117.      * If you override this function you should in most cases call base.Awake () at the start of it.
  118.       * */
  119.     protected virtual void Awake () {
  120.         seeker = GetComponent<Seeker>();
  121.        
  122.         //This is a simple optimization, cache the transform component lookup
  123.         tr = transform;
  124.     }
  125.    
  126.     /** Starts searching for paths.
  127.      * If you override this function you should in most cases call base.Start () at the start of it.
  128.      * \see OnEnable
  129.      * \see RepeatTrySearchPath
  130.      */
  131.     protected virtual void Start () {
  132.         startHasRun = true;
  133.         OnEnable ();
  134.     }
  135.    
  136.     /** Run at start and when reenabled.
  137.      * Starts RepeatTrySearchPath.
  138.      *
  139.      * \see Start
  140.      */
  141.     protected virtual void OnEnable () {
  142.        
  143.         lastRepath = -9999;
  144.         canSearchAgain = true;
  145.  
  146.         lastFoundWaypointPosition = GetFeetPosition ();
  147.  
  148.         if (startHasRun) {
  149.             //Make sure we receive callbacks when paths complete
  150.             seeker.pathCallback += OnPathComplete;
  151.            
  152.             StartCoroutine (RepeatTrySearchPath ());
  153.         }
  154.     }
  155.    
  156.     public void OnDisable () {
  157.         // Abort calculation of path
  158.         if (seeker != null && !seeker.IsDone()) seeker.GetCurrentPath().Error();
  159.        
  160.         // Release current path
  161.         if (path != null) path.Release (this);
  162.         path = null;
  163.        
  164.         //Make sure we receive callbacks when paths complete
  165.         seeker.pathCallback -= OnPathComplete;
  166.     }
  167.    
  168.     /** Tries to search for a path every #repathRate seconds.
  169.       * \see TrySearchPath
  170.       */
  171.     protected IEnumerator RepeatTrySearchPath () {
  172.         while (true) {
  173.             float v = TrySearchPath ();
  174.             yield return new WaitForSeconds (v);
  175.         }
  176.     }
  177.    
  178.     /** Tries to search for a path.
  179.      * Will search for a new path if there was a sufficient time since the last repath and both
  180.      * #canSearchAgain and #canSearch are true and there is a target.
  181.      *
  182.      * \returns The time to wait until calling this function again (based on #repathRate)
  183.      */
  184.     public float TrySearchPath () {
  185.         if (Time.time - lastRepath >= repathRate && canSearchAgain && canSearch && target != null) {
  186.             SearchPath ();
  187.             return repathRate;
  188.         } else {
  189.             //StartCoroutine (WaitForRepath ());
  190.             float v = repathRate - (Time.time-lastRepath);
  191.             return v < 0 ? 0 : v;
  192.         }
  193.     }
  194.    
  195.     /** Requests a path to the target */
  196.     public virtual void SearchPath () {
  197.        
  198.         if (target == null) throw new System.InvalidOperationException ("Target is null");
  199.        
  200.         lastRepath = Time.time;
  201.         //This is where we should search to
  202.         Vector3 targetPosition = target.position;
  203.        
  204.         canSearchAgain = false;
  205.        
  206.         //Alternative way of requesting the path
  207.         //ABPath p = ABPath.Construct (GetFeetPosition(),targetPoint,null);
  208.         //seeker.StartPath (p);
  209.        
  210.         //We should search from the current position
  211.         seeker.StartPath (GetFeetPosition(), targetPosition);
  212.     }
  213.    
  214.     public virtual void OnTargetReached () {
  215.         //End of path has been reached
  216.         //If you want custom logic for when the AI has reached it's destination
  217.         //add it here
  218.         //You can also create a new script which inherits from this one
  219.         //and override the function in that script
  220.     }
  221.    
  222.     /** Called when a requested path has finished calculation.
  223.       * A path is first requested by #SearchPath, it is then calculated, probably in the same or the next frame.
  224.       * Finally it is returned to the seeker which forwards it to this function.\n
  225.       */
  226.     public virtual void OnPathComplete (Path _p) {
  227.         ABPath p = _p as ABPath;
  228.         if (p == null) throw new System.Exception ("This function only handles ABPaths, do not use special path types");
  229.        
  230.         canSearchAgain = true;
  231.        
  232.         //Claim the new path
  233.         p.Claim (this);
  234.        
  235.         // Path couldn't be calculated of some reason.
  236.         // More info in p.errorLog (debug string)
  237.         if (p.error) {
  238.             p.Release (this);
  239.             return;
  240.         }
  241.        
  242.         //Release the previous path
  243.         if (path != null) path.Release (this);
  244.        
  245.         //Replace the old path
  246.         path = p;
  247.        
  248.         //Reset some variables
  249.         currentWaypointIndex = 0;
  250.         targetReached = false;
  251.     }
  252.    
  253.     public virtual Vector3 GetFeetPosition () {
  254.         return tr.position;
  255.     }
  256. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement