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 /
avatar image
0
Question by Bezari0us · Jul 04, 2019 at 10:16 AM · scripting problemfpsai

Need help with FPS Shooting AI Behaviour script

Okay, all I have now is an AI that can move and rotate to find player position (using nav mesh agent) and playing running animation, can stop and play shooting animation if the player is in its shooting range. And here is my problem:

Despite the shooting animation is playing, the AI is not actually shooting at all. I have some timer variables to make AI raycast shooting look like an automatic rifle behaviour (10 bullets/1s for example) but the problem is that the countdown timer is not decreasing. Every time I move the player and then if the AI found the player again, the countdown decreases for about 0,0001 second and then stops. (AI still moves if I move or stays at shooting position and plays shooting animation if the player is not moving).

Can someone take a look at my script and tell me if I'm missing something. Thank you for taking your time to read my question. Here is the script:

 public class AIBehaviour : MonoBehaviour
 {
 
     public enum State
     {
         FindingTarget,
         Shooting
     }
 
     public State state = State.FindingTarget;
 
     public int damage;
 
     public float moveSpeed;
 
     public float delayToShoot;
 
     [Tooltip("The time to check if Player is still there at the position being shot")]
     public float nextTimeToSearch;
 
     public Transform gunTip;
 
     private Transform _target;
 
     private NavMeshAgent _agent;
 
     private Animator _anim;
 
     private bool _targetInRange;
 
     [SerializeField] private float _countdownToSearch;
 
     [SerializeField] private float _countdownToShoot;
 
     void Start()
     {
         _agent = GetComponent<NavMeshAgent>();
         _target = PlayerManager.instance.player.transform;
         _anim = GetComponentInChildren<Animator>();
         state = State.FindingTarget;
         _agent.speed = moveSpeed;
         _countdownToSearch = nextTimeToSearch;
         _countdownToShoot = delayToShoot;
     }
 
     private void Update()
     {
         // if there is target to find at all
         if (_target != null)
         {
             // find target
             if (!_targetInRange)
             {
                 FindTarget();
             }
 
             if (state == State.Shooting && _targetInRange)
             {
                 // check if player is still at the being shot position
                 if (_countdownToSearch <= 0)
                 {
                     _countdownToSearch = nextTimeToSearch;
                     RaycastHit hit;
                     if (Physics.Raycast(gunTip.position, gunTip.forward, out hit, Mathf.Infinity))
                     {
                         if (!hit.transform.gameObject.CompareTag("Player"))
                         {
                             Debug.Log("Player has moved!");
                             // then find player again
                             _targetInRange = false;
                             FindTarget();
                         }
                         else return;
                     }
                 }
                 else _countdownToSearch -= Time.deltaTime;
 
             }
 
             else if (state == State.FindingTarget && _targetInRange && state != State.Shooting)
             {
                 Shoot();
                 _anim.SetBool("Fire", true);
             }
         }
         else
         {
             Debug.LogWarning("Currently there is no player in the scene");
         }
     }
 
     void FindTarget()
     {
         state = State.FindingTarget;
 
         _agent.speed = moveSpeed;
         _agent.SetDestination(_target.position);
         _anim.SetFloat("Speed", _agent.speed);
         _anim.SetBool("Fire", false);
 
         Quaternion lookRotation = Quaternion.LookRotation(_target.position - transform.position);
         transform.rotation = Quaternion.Slerp(transform.rotation, lookRotation, Time.deltaTime * 5f);
 
         RaycastHit raycasthit;
         if (Physics.Raycast(gunTip.position, gunTip.forward, out raycasthit, Mathf.Infinity))
         {
             if (raycasthit.transform.gameObject.tag == "Player")
             {
                 _targetInRange = true;
                 Debug.Log("Found Player!");
             }
             else
             {
                 _targetInRange = false;
                 _agent.isStopped = false;
                 return;
             }
         }
     }
 
     void Shoot()
     {
         state = State.Shooting;
         Debug.Log("Fire!");
         _agent.isStopped = true;
 
         transform.LookAt(_target);
 
         if (_countdownToShoot <= 0)
         {
             RaycastHit hit;
             if (Physics.Raycast(gunTip.position, gunTip.forward, out hit, Mathf.Infinity))
             {
                 PlayerCharacter playerHealth = hit.transform.gameObject.GetComponent<PlayerCharacter>();
                 if (playerHealth != null)
                 {
                     Debug.Log("Player is being shot!");
                     playerHealth.Hurt(damage);
                 }
             }
             _countdownToShoot = delayToShoot;
         }
         else _countdownToShoot -= Time.deltaTime;
     }
 }


Comment
Add comment · Show 1
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 akaBase · Jul 04, 2019 at 10:30 AM 0
Share

Couple of things.


You are using $$anonymous$$athF.Inifninity for the distance to RayCast so if RayCasting in the right direction the Player will always be in range.


Next each time you Shoot and hit the Player you are getting the PlayerCharacter component, that can be upto 10 times a second, store it somewhere as it's using resources you don't need too.


Lastly you are setting the Shoot animation and calling Shoot before you check that enough time has passed.

2 Replies

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by Bezari0us · Jul 04, 2019 at 05:01 PM

I FINALLY GOT IT TO WORK!

As it turned out that I myself made a mountain out of a molehill when using enum for a just simple finite-state machine. I tested the script without with the enum states and it turned out that, the enum state is acting like a bool. For example below lines of code will update the target position for the agent to move

 if (_target != null)
         {
             FindTarget();
         }

while this will only get the position once and will not update the new position of the target

 if (_target != null && state!=State.FindingTarget)
         {
             FindTarget();
         }

So I got rid of all the enum states and now I'm having a simple AI FPS behaviour that I want. Simple FSM. AI finds, moves and rotates to target. If found target then it aims. Then after aiming for desired seconds, it shoots. Then if the player moved ouf of shooting range or out of sight, it returns to find target. That's it. Here is the updated script. The PlayerCharacter is a script on player which contains a public function for AI to call and damage the player.

 public class AIBehaviour : MonoBehaviour
 {
     public int damage;
 
     public float moveSpeed;
 
     public float delayToShoot;
 
     [Tooltip("The time to check if Player is still there at the position being shot")]
     public float nextTimeToSearch;
 
     public float fireRate;
 
     private float _nextTimeToFire;
 
     public Transform gunTip;
 
     private Transform _target;
 
     private NavMeshAgent _agent;
 
     private Animator _anim;
 
     [SerializeField] private float _countdownToSearch;
 
 
     void Start()
     {
         _agent = GetComponent<NavMeshAgent>();
         _target = PlayerManager.instance.player.transform;
         _anim = GetComponentInChildren<Animator>();
         _agent.speed = moveSpeed;
         _countdownToSearch = nextTimeToSearch;
         _nextTimeToFire = 0;
     }
 
     private void Update()
     {
         if (_target != null)
         {
             FindTarget();
         }
     }
 
     void FindTarget()
     {
         _agent.speed = moveSpeed;
         _agent.SetDestination(_target.position);
 
         _anim.SetFloat("Speed", _agent.speed);
         _anim.SetBool("Fire", false);
 
         Quaternion lookRotation = Quaternion.LookRotation(_target.position - transform.position);
         transform.rotation = Quaternion.Slerp(transform.rotation, lookRotation, Time.deltaTime * 5f);
 
         RaycastHit raycasthit;
         if (Physics.Raycast(gunTip.position, gunTip.forward, out raycasthit, Mathf.Infinity))
         {
             if (raycasthit.transform.gameObject.tag == "Player")
             {
                 Debug.Log("Found Player!");
                 StartCoroutine(Aim());
             }
             else
             {
                 _agent.isStopped = false;
                 return;
             }
         }
     }
 
     IEnumerator Aim()
     {
         _agent.isStopped = true;
         _agent.speed = 0;
         _anim.SetFloat("Speed", _agent.speed);
         yield return new WaitForSeconds(1f);
         Shoot();
     }
 
     void Shoot()
     {
         Debug.Log("Fire!");
         _anim.SetBool("Fire", true);
         if (_nextTimeToFire <= Time.time)
         {
             _nextTimeToFire = Time.time + 1 / fireRate;
             RaycastHit hit;
             if (Physics.Raycast(gunTip.position, gunTip.forward, out hit, Mathf.Infinity))
             {
                 PlayerCharacter playerHealth = hit.transform.gameObject.GetComponent<PlayerCharacter>();
                 if (playerHealth != null)
                 {
                     //Debug.Log("Player is being shot!");
                     playerHealth.Hurt(damage);
                 }
             }
         }
     }
 }



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 Kennai · Jul 04, 2019 at 08:57 PM 0
Share

Good job, man! I am also glad you changed your timer behaviour :)

avatar image
0

Answer by Kennai · Jul 04, 2019 at 12:51 PM

Hi, @Bezari0us! I changed value in _countdownToShoot to a time, when shoot can be done. Now you dont need to decrease delta time from countdown. Hope it solve your problem.

 public class AIBehaviour : MonoBehaviour
 {
 
     public enum State
     {
         FindingTarget,
         Shooting
     }
 
     public State state = State.FindingTarget;
 
     public int damage;
 
     public float moveSpeed;
 
     public float delayToShoot;
 
     [Tooltip("The time to check if Player is still there at the position being shot")]
     public float nextTimeToSearch;
 
     public Transform gunTip;
 
     private Transform _target;
 
     private NavMeshAgent _agent;
 
     private Animator _anim;
 
     private bool _targetInRange;
 
     [SerializeField] private float _countdownToSearch;
 
     [SerializeField] private float _countdownToShoot;
 
     void Start()
     {
         _agent = GetComponent<NavMeshAgent>();
         _target = PlayerManager.instance.player.transform;
         _anim = GetComponentInChildren<Animator>();
         state = State.FindingTarget;
         _agent.speed = moveSpeed;
         _countdownToSearch = nextTimeToSearch;
         _countdownToShoot = Time.time + delayToShoot;
     }
 
     private void Update()
     {
         // if there is target to find at all
         if (_target != null)
         {
             // find target
             if (!_targetInRange)
             {
                 FindTarget();
             }
 
             if (state == State.Shooting && _targetInRange)
             {
                 // check if player is still at the being shot position
                 if (_countdownToSearch <= 0)
                 {
                     _countdownToSearch = nextTimeToSearch;
                     RaycastHit hit;
                     if (Physics.Raycast(gunTip.position, gunTip.forward, out hit, Mathf.Infinity))
                     {
                         if (!hit.transform.gameObject.CompareTag("Player"))
                         {
                             Debug.Log("Player has moved!");
                             // then find player again
                             _targetInRange = false;
                             FindTarget();
                         }
                         else return;
                     }
                 }
                 else _countdownToSearch -= Time.deltaTime;
 
             }
 
             else if (state == State.FindingTarget && _targetInRange && state != State.Shooting)
             {
                 Shoot();
                 _anim.SetBool("Fire", true);
             }
         }
         else
         {
             Debug.LogWarning("Currently there is no player in the scene");
         }
     }
 
     void FindTarget()
     {
         state = State.FindingTarget;
 
         _agent.speed = moveSpeed;
         _agent.SetDestination(_target.position);
         _anim.SetFloat("Speed", _agent.speed);
         _anim.SetBool("Fire", false);
 
         Quaternion lookRotation = Quaternion.LookRotation(_target.position - transform.position);
         transform.rotation = Quaternion.Slerp(transform.rotation, lookRotation, Time.deltaTime * 5f);
 
         RaycastHit raycasthit;
         if (Physics.Raycast(gunTip.position, gunTip.forward, out raycasthit, Mathf.Infinity))
         {
             if (raycasthit.transform.gameObject.tag == "Player")
             {
                 _targetInRange = true;
                 Debug.Log("Found Player!");
             }
             else
             {
                 _targetInRange = false;
                 _agent.isStopped = false;
                 return;
             }
         }
     }
 
     void Shoot()
     {
         state = State.Shooting;
         Debug.Log("Fire!");
         _agent.isStopped = true;
 
         transform.LookAt(_target);
 
         if (_countdownToShoot <= Time.time)
         {
             RaycastHit hit;
             if (Physics.Raycast(gunTip.position, gunTip.forward, out hit, Mathf.Infinity))
             {
                 PlayerCharacter playerHealth = hit.transform.gameObject.GetComponent<PlayerCharacter>();
                 if (playerHealth != null)
                 {
                     Debug.Log("Player is being shot!");
                     playerHealth.Hurt(damage);
                 }
             }
             _countdownToShoot = Time.time + delayToShoot;
         }
     }
 }

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

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

278 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 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

How can I add recoil to my gun? 0 Answers

Another function for activating a different script 0 Answers

I am making an fps and I want to make allies... Help me 1 Answer

if the fps is high the camera rotate much faster 1 Answer

I'm have trouble with the ai script in standard asset 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