In my fps shooter game, I have a ai enemy/shooter. If you come too close, he will chase you. If you come closer, he will shoot. I have the problem that if an obstacle is in the way of you and the enemy, and you are in shooting range, he will try shooting at you but hit the obstacle. One idea is to ray cast, and if the ray cast doesn’t hit the player, chase. But how would I implement this?
code:
using UnityEngine;
using UnityEngine.AI;
public class enemys : MonoBehaviour
{
public NavMeshAgent agent;
public Transform player;
public LayerMask whatIsGround, whatIsPlayer;
public Vector3 walkPoint;
bool walkPointSet;
public float walkPointRange;
public float timeBetweenAttacks;
bool alreadyAttacked;
public float Accuracy;
public float dmg;
public float sightRange, attackRange;
public bool playerInSightRange, playerInAttackRange;
public ParticleSystem flash;
private void Awake()
{
player = GameObject.Find("player").transform;
agent = GetComponent<NavMeshAgent>();
}
private void Update()
{
playerInSightRange = Physics.CheckSphere(transform.position, sightRange, whatIsPlayer);
playerInAttackRange = Physics.CheckSphere(transform.position, attackRange, whatIsPlayer);
if (!playerInSightRange && !playerInAttackRange) Patroling();
if (playerInSightRange && !playerInAttackRange) ChasePlayer();
if (playerInSightRange && playerInAttackRange) AttackPlayer();
}
private void Patroling()
{
if (!walkPointSet) SearchWalkpoint();
if (walkPointSet)
agent.SetDestination(walkPoint);
Vector3 distanceToWalkPoint = transform.position - walkPoint;
if (distanceToWalkPoint.magnitude < 1f)
walkPointSet = false;
}
private void SearchWalkpoint()
{
float randomZ = Random.Range(-walkPointRange, walkPointRange);
float randomx = Random.Range(-walkPointRange, walkPointRange);
walkPoint = new Vector3(transform.position.x + randomx, transform.position.y, transform.position.z + randomZ);
if (Physics.Raycast(walkPoint, -transform.up, 2f, whatIsGround))
walkPointSet = true;
}
private void ChasePlayer()
{
agent.SetDestination(player.position);
}
private void AttackPlayer()
{
agent.SetDestination(transform.position);
transform.LookAt(player);
if (!alreadyAttacked)
{
//start of shooting
flash.Play();
RaycastHit hit;
if (Physics.Raycast(gameObject.transform.position, gameObject.transform.forward, out hit, 100))
{
if (Random.value < Accuracy/100+1)
{
Debug.Log("player");
playerDeath playerDeath = hit.transform.GetComponent<playerDeath>();
if (playerDeath != null)
{
playerDeath.Damage(dmg);
}
}
else
Debug.Log("miss");
Debug.Log("shot");
}
//end of shooting
alreadyAttacked = true;
Invoke(nameof(ResetAttack), timeBetweenAttacks);
}
}
private void ResetAttack()
{
alreadyAttacked = false;
}
}