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;
}
}