Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 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 /
  • Help Room /
This question was closed Apr 14, 2019 at 08:08 AM by KevRev for the following reason:

The question is answered, right answer was accepted

avatar image
0
Question by KevRev · Feb 06, 2019 at 09:21 PM · aispace shooterbehaviour

How to stop a.i. just circling eachother?

Hi all,

I'm a hobbyist with very little experience, but have been trying to avoid buying pre-built assets and am having a stab at creating my own A.I. logic. I've been scouring the forums to get ideas on how to implement it, and have settled on a simple finite state machine (fsm). Though i'm thinking my problem may need a stacked fsm...

I've got Defend, Seek, Attack and Evade modes working, but the ships end up just circling each other switching rapidly between all states.

Any advice greatly appreciated.

 using UnityEngine;
 
 public class SpaceBattle : MonoBehaviour
 {
     public Transform moon;
     public GameObject[] enemyShips;
     private Transform target;
 
     public GameObject Bullet_Emitter;
     public GameObject Bullet;
     public float Bullet_Forward_Force;
 
     public bool chasing = false;
     public float distance;
     public float nearest = 10000;
     public string targeted;
 
     public float rotationSpeed;
     public float maxDist;
     public float minDist;
     public float fireDist;
     public string mode="Seek";
 
     //debug
     public string TargetName;
 
     public float moveSpeed;
     private void Start()
     {
         enemyShips = GameObject.FindGameObjectsWithTag("EnemyShip");
     }
     void Update()
     {
         enemyShips = null;
         enemyShips = GameObject.FindGameObjectsWithTag("EnemyShip");
         Debug.Log("Enemy Ships Found: " + enemyShips.Length);
 
         if (target != null && target!=moon)
         {
             //If target is further than maxDist we lost the target
             if ((target.transform.position - transform.position).magnitude >= maxDist)
             {
                 target.GetComponentInParent<EnemyShip>().targeted =null;
                 target = null;
                 nearest = 10000;
             }
             // else nearest = (target.transform.position - transform.position).magnitude;
         }
 
 
         target = null;
         // Look for a nearby target
         nearest = 1000;
         for (int i = 0; i < enemyShips.Length; i++)
         {
             if (enemyShips[i].GetComponent<EnemyShip>().targeted != null)
             {
                 distance = (enemyShips[i].transform.position - transform.position).magnitude;
                 Debug.Log("Checking " + enemyShips[i].name + "...  distance is " + distance.ToString()+" and Max:"+maxDist+" Nearest:"+nearest+"  i="+i.ToString());
                 if (distance < nearest)
                 {
                     Debug.Log("Found a nearer target: " + enemyShips[i].name + " " + distance);
                     nearest = distance;
                     target = enemyShips[i].transform;
                 }
             }
         }
         if (target != null) target.GetComponentInParent<EnemyShip>().targeted = this.name;
         if (target == null || (moon.transform.position - transform.position).magnitude>1000) target = moon;
         TargetName = target.name;
 
 
         if (target == moon)
         {
             mode = "Defend";
         }
         else if (nearest <= minDist)
         {
             mode = "Evade";
         }
         else if (nearest>=fireDist && mode=="Evade")
         {
             mode = "Attack";
         }
         else if (mode=="Seek" && nearest<=fireDist)
         {
             mode = "Attack";
         }
         else if (nearest<=maxDist)
         {
             mode = "Seek";
         }
 
         switch (mode)
         {
             case "Seek":
                 {
                     SeekTarget(transform, target);
                     MoveToTarget(transform, target);
                     break;
                 }
             case "Defend":
                 {
                     SeekTarget(transform, moon);
                     MoveToTarget(transform, moon);
                     break;
                 }
             case "Evade":
                 {
                     EvadeTarget(transform, target);
                     break;
                 }
             case "Attack":
                 {
                     SpeedToTarget(transform, target);
                     FireAtTarget(transform, target);
                     break;
                 }
         }
     }
 
     void EvadeTarget(Transform rTransform, Transform rtarget)
     {
         rTransform.rotation = Quaternion.Slerp(rTransform.rotation, Quaternion.LookRotation(rTransform.position - rtarget.position), rotationSpeed * Time.deltaTime);
         rTransform.position += rTransform.forward * moveSpeed * Time.deltaTime;
 
     }
 
     void SeekTarget(Transform rTransform, Transform rtarget)
     {
         rTransform.rotation = Quaternion.Slerp(rTransform.rotation, Quaternion.LookRotation(rtarget.position - rTransform.position), rotationSpeed * Time.deltaTime);
         Debug.Log("Seeking " + rtarget.name);
     }
 
     void MoveToTarget(Transform rTransform, Transform rtarget)
     {
         rTransform.position += rTransform.forward * moveSpeed * Time.deltaTime;
         Debug.Log("Moving towards " + rtarget.name);
     }
     void SpeedToTarget(Transform rTransform, Transform rtarget)
     {
         rTransform.rotation = Quaternion.Slerp(rTransform.rotation, Quaternion.LookRotation(predictedPosition(rtarget.position,rTransform.position,rtarget.GetComponentInParent<Rigidbody>().velocity, 30f) - rTransform.position), rotationSpeed * Time.deltaTime);
         rTransform.position += rTransform.forward * (moveSpeed*1.5f) * Time.deltaTime;
         Debug.Log("Attacking " + rtarget.name);
     }
     void FireAtTarget(Transform rTransform, Transform rtarget)
     {
         if (Physics.Raycast(rTransform.position, rTransform.forward, 100) && GameObject.FindGameObjectsWithTag("FriendlyFire").Length < 3)
         {
             GameObject Temporary_Bullet_Handler;
             Temporary_Bullet_Handler = Instantiate(Bullet, Bullet_Emitter.transform.position, Bullet_Emitter.transform.rotation) as GameObject;
             Temporary_Bullet_Handler.transform.Rotate(Vector3.left * 90);
             Rigidbody Temporary_RigidBody;
             Temporary_RigidBody = Temporary_Bullet_Handler.GetComponent<Rigidbody>();
             Temporary_RigidBody.AddForce(transform.forward * Bullet_Forward_Force);
             Destroy(Temporary_Bullet_Handler, 0.5f);
         }
     }
 
     private Vector3 predictedPosition(Vector3 targetPosition, Vector3 shooterPosition, Vector3 targetVelocity, float projectileSpeed)
     {
         Vector3 displacement = targetPosition - shooterPosition;
         float targetMoveAngle = Vector3.Angle(-displacement, targetVelocity) * Mathf.Deg2Rad;
         //if the target is stopping or if it is impossible for the projectile to catch up with the target (Sine Formula)
         if (targetVelocity.magnitude == 0 || targetVelocity.magnitude > projectileSpeed && Mathf.Sin(targetMoveAngle) / projectileSpeed > Mathf.Cos(targetMoveAngle) / targetVelocity.magnitude)
         {
             Debug.Log("Position prediction is not feasible.");
             return targetPosition;
         }
         //also Sine Formula
         float shootAngle = Mathf.Asin(Mathf.Sin(targetMoveAngle) * targetVelocity.magnitude / projectileSpeed);
         return targetPosition + targetVelocity * displacement.magnitude / Mathf.Sin(Mathf.PI - targetMoveAngle - shootAngle) * Mathf.Sin(shootAngle) / targetVelocity.magnitude;
     }
 }
 
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

2 Replies

  • Sort: 
avatar image
0
Best Answer

Answer by KevRev · Feb 13, 2019 at 11:13 PM

Figured it out myself. Pretty cool little space a.i. :)

I tried updating this question with the code for everybody to use if they were interested, but the webpage wouldnt let me submit the code. :(

Comment
Add comment · Show 1 · Share
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
avatar image KevRev · Feb 08, 2019 at 11:35 PM 0
Share

That's not a bad idea. I was thinking of toying with the velocity. Similar to the "arrive" behaviour. I also read an article by a guy that developed the star wars trench run game. He used randomly placed invisible targets around the player and randomly switched to them. This gave the enemies what looked like a fairly natural movement in random directions, bringing them back around for attack. I might try implementing something similar.

avatar image
0

Answer by UltraGearGames · Feb 08, 2019 at 12:07 PM

You could set their speed to 0 when at a specific distance from each other. not angular speed though, thats rotation.

Comment
Add comment · Share
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

Follow this Question

Answers Answers and Comments

231 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Is there a way to implement a ghost mode where a ghost can replay the best possible solution of a set of data? 0 Answers

Ally AI shoot arrow 0 Answers

how to use RunCoroutine in Unity 2D Gamekit Behavior Tree 0 Answers

Is there a way to identify the state of the scene obstacles? 0 Answers

Won't fire when switching weapons? 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