Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by Kyle 11 · Jan 30, 2012 at 01:49 AM · c#aipathfindingangryant

enemy stopping then repathing

I'm new to programming so basically I'm trying to use the AIFollow script from AngryAnt to detect if the player is within a certain range. this will cause the enemy which the script is attached to to stop and fire at the player. Then when the player is out of attack range to continue moving to the player. I know I'm doing something terribly wrong so any help would be awesomely appreciated.

Basically,

  1. head towards player.

  2. if player is within range stop and shoot towards players position.

  3. if player moves out of range, repath and move towards player.

Heres the script if you need to see it.

 using UnityEngine;
 using System.Collections;
 using Pathfinding;
 
 /** Example AI */
 [RequireComponent (typeof(Seeker))]
 [RequireComponent (typeof(CharacterController))]
 public class AIFollow : MonoBehaviour {
     
     public Rigidbody projectile;
     
     public float FireRange = 6;
     
     public Transform EnemyBulletSpawn;
     
     /** Target to move to */
     public Transform target;
     
     /** How often to search for a new path */
     public float repathRate = 0.1F;
     
     /** The minimum distance to a waypoint to consider it as "reached" */
     public float pickNextWaypointDistance = 1F;
     
     /** The minimum distance to the end point of a path to consider it "reached" (multiplied with #pickNextWaypointDistance).
      * This value is multiplied with #pickNextWaypointDistance before it is used. Recommended range [0...1] */
     public float targetReached = 0.2F;
     
     /** Units per second */
     public float speed = 5;
     
     /** How fast the AI can turn around */
     public float rotationSpeed = 1;
     
     public bool drawGizmos = false;
     
     /** Should paths be searched for.
      * Setting this to false will make the AI not search for paths anymore, can save some CPU cycles.
      * It will check every #repathRate seconds if it should start to search for paths again.
      * \note It will not cancel paths which are currently being calculated */
     public bool canSearch = true;
     
     /** Can it move. Enables or disables movement and rotation */
     public bool canMove = true;
     
     /** Seeker component which handles pathfinding calls */
     protected Seeker seeker;
     
     /** CharacterController which handles movement */
     protected CharacterController controller;
     
     /** NavmeshController which handles movement if not null*/
     protected NavmeshController navmeshController;
     
     
     /** Transform, cached because of performance */
     protected Transform tr;
     
     protected float lastPathSearch = -9999;
     
     protected int pathIndex = 0;
     
     /** This is the path the AI is currently following */
     protected Vector3[] path;
     
     /** Use this for initialization */
     public void Start () {
         seeker = GetComponent<Seeker>();
         controller = GetComponent<CharacterController>();
         navmeshController = GetComponent<NavmeshController>();
         tr = transform;
         Repath ();
     }
     
     /** Called when a path has completed it's calculation */
     public void OnPathComplete (Path p) {
         
         /*if (Time.time-lastPathSearch >= repathRate) {
             Repath ();
         } else {*/
             StartCoroutine (WaitToRepath ());
         //}
         
         //If the path didn't succeed, don't proceed
         if (p.error) {
             return;
         }
         
         //Get the calculated path as a Vector3 array
         path = p.vectorPath;
         
         //Find the segment in the path which is closest to the AI
         //If a closer segment hasn't been found in '6' iterations, break because it is unlikely to find any closer ones then
         float minDist = Mathf.Infinity;
         int notCloserHits = 0;
         
         for (int i=0;i<path.Length-1;i++) {
             float dist = Mathfx.DistancePointSegmentStrict (path[i],path[i+1],tr.position);
             if (dist < minDist) {
                 notCloserHits = 0;
                 minDist = dist;
                 pathIndex = i+1;
             } else if (notCloserHits > 6) {
                 break;
             }
         }
     }
     
     /** Waits the remaining time until the AI should issue a new path request.
      * The remaining time is defined by Time.time - lastPathSearch */
     public IEnumerator WaitToRepath () {
         float timeLeft = repathRate - (Time.time-lastPathSearch);
         
         yield return new WaitForSeconds (timeLeft);
         Repath ();
     }
     
     /** Stops the AI.
      * Also stops new search queries from being made
      * \version Before 3.0.8 This does not prevent new path calls from making the AI move again
      * \see #Resume
      * \see #canMove
      * \see #canSearch */
     public void Stop () {
         canMove = false;
         canSearch = false;
     }
     
     /** Resumes walking and path searching the AI.
      * \version Added in 3.0.8
      * \see #Stop
      * \see #canMove
      * \see #canSearch */
     public void Resume () {
         canMove = true;
         canSearch = true;
     }
     
     /** Recalculates the path to #target.
       * Queries a path request to the Seeker, the path will not be calculated instantly, but will be put on a queue and calculated as fast as possible.
       * It will wait if the current path request by this seeker has not been completed yet.
       * \see Seeker::IsDone */
     public virtual void Repath () {
         lastPathSearch = Time.time;
         
         if (seeker == null || target == null || !canSearch || !seeker.IsDone ()) {
             StartCoroutine (WaitToRepath ());
             return;
         }
         
         //Start a new path from transform.positon to target.position, return the result to the function OnPathComplete
         seeker.StartPath (transform.position,target.position,OnPathComplete);
     }
     
     /** Start a new path moving to \a targetPoint */
     public void PathToTarget (Vector3 targetPoint) {
         lastPathSearch = Time.time;
         
         if (seeker == null) {
             return;
         }
         
         //Start a new path from transform.positon to target.position, return the result to OnPathComplete
         seeker.StartPath (transform.position,targetPoint,OnPathComplete);
     }
     
     /** Called when the AI reached the end of path.
      * This will be called once for every path it completes, so if you have a really fast repath rate it will call this function often if when it stands on the end point.
      */
     public virtual void ReachedEndOfPath () {
         //The AI has reached the end of the path
     }
     
     /** Update is called once per frame */
     public void Update () {
         
         float distanceToPlayer = Vector3.Distance(this.transform.position, target.transform.position);
         
         if (path == null || pathIndex >= path.Length || pathIndex < 0 || !canMove) {
             return;
         }
         
         //Change target to the next waypoint if the current one is close enough
         Vector3 currentWaypoint = path[pathIndex];
         currentWaypoint.y = tr.position.y;
         while ((currentWaypoint - tr.position).sqrMagnitude < pickNextWaypointDistance*pickNextWaypointDistance) {
             pathIndex++;
             if (pathIndex >= path.Length) {
                 //Use a lower pickNextWaypointDistance for the last point. If it isn't that close, then decrement the pathIndex to the previous value and break the loop
                 if ((currentWaypoint - tr.position).sqrMagnitude < (pickNextWaypointDistance*targetReached)*(pickNextWaypointDistance*targetReached)) {
                     ReachedEndOfPath ();
                     return;
                 } else {
                     pathIndex--;
                     //Break the loop, otherwise it will try to check for the last point in an infinite loop
                     break;
                 }
             }
             currentWaypoint = path[pathIndex];
             currentWaypoint.y = tr.position.y;
         }
         
         
         Vector3 dir = currentWaypoint - tr.position;
         
         // Rotate towards the target
         tr.rotation = Quaternion.Slerp (tr.rotation, Quaternion.LookRotation(dir), rotationSpeed * Time.deltaTime);
         tr.eulerAngles = new Vector3(0, tr.eulerAngles.y, 0);
         
         Vector3 forwardDir = transform.forward;
         //Move Forwards - forwardDir is already normalized
         forwardDir = forwardDir * speed;
         forwardDir *= Mathf.Clamp01 (Vector3.Dot (dir.normalized, tr.forward));
         
         if (navmeshController != null) {
             navmeshController.SimpleMove (tr.position,forwardDir);
         } else {
             controller.SimpleMove (forwardDir);
     }
                 
         if(distanceToPlayer <= FireRange){
             StartCoroutine("EnemyRangedAttack");
     }
         if (distanceToPlayer > FireRange) {
             Repath();
         }
 }
     
     public IEnumerator EnemyRangedAttack () {
         print ("attack started");
         canMove = false;
         canSearch = false;
         Rigidbody Bullet;
         yield return new WaitForSeconds (0.1f);
         Bullet = Instantiate(projectile, transform.position, transform.rotation) as Rigidbody;
         Bullet.velocity = transform.TransformDirection(Vector3.forward * 10);
         canMove = true;
         canSearch = true;
         StopCoroutine("EnemyRangedAttack");
     }
         
 
     
     /** Draws helper gizmos.
      * Currently draws a circle around the current target point with the size showing how close the AI need to get to it for it to count as "reached".
      */
     public void OnDrawGizmos () {
         
         if (!drawGizmos || path == null || pathIndex >= path.Length || pathIndex < 0) {
             return;
         }
         
         Vector3 currentWaypoint = path[pathIndex];
         currentWaypoint.y = tr.position.y;
         
         Debug.DrawLine (transform.position,currentWaypoint,Color.blue);
         
         float  rad = pickNextWaypointDistance;
         if (pathIndex == path.Length-1) {
             rad *= targetReached;
         }
         
         Vector3 pP = currentWaypoint + rad*new Vector3 (1,0,0);
         for (float i=0;i<2*System.Math.PI;i+= 0.1F) {
             Vector3 cP = currentWaypoint + new Vector3 ((float)System.Math.Cos (i)*rad,0,(float)System.Math.Sin(i)*rad);
             Debug.DrawLine (pP,cP,Color.yellow);
             pP = cP;
         }
         Debug.DrawLine (pP, currentWaypoint + rad*new Vector3 (1,0,0),Color.yellow);
     }
     
 }
Comment
Add comment
10 |3000 characters needed characters left characters exceeded
â–¼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

0 Replies

· Add your reply
  • Sort: 

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

4 People are following this question.

avatar image avatar image avatar image avatar image

Related Questions

Movement around a huge object by avoiding obstacles 1 Answer

A* pathfinding for 2D top Down 0 Answers

A* pathfinding for dynamic obstacles and player made blockages? 0 Answers

Make a flying enemy ? 0 Answers

RTS dynamic formation width and length 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges