Hey,
This is how I’m doing it in my topdown shooter.
Basically:
- The enemy casts a Physics.OverlapSphere and checks if any colliders intersect with it within a certain radius i.e. 5 meters.
- An array of colliders is returned. I have a layerMask on this Overlapsphere so that the enemy doesn’t hit the colliders on the ground, etc. That would be inefficient.
- Being inefficient and explicit, I check if the collider has a tag of player using CompareTag(“Player”).
- If this evaluates to true, I make the enemy LookAt() the player, and begin movement using transform.translate in the Vector3.forward direction (move in the direciton the enemy is facing, and he’s already facing the player).
Here is the big example code you can sift through:
using UnityEngine;
using System.Collections;
public class AI_FollowController : MonoBehaviour {
Collider[] playersInRange;
Collider[] playersToAttack;
public GameObject attackSphereContainer;
private SphereCollider attackSphere;
public float searchRadius = 20f;
public LayerMask playerOnly;
public LayerMask wallBlocks;
Animator anim;
EnemyAudioManager __eam;
public float enemySpeed = 10;
public float enemyChaseRange = 20;
public float timeSinceLastAttack = 0;
public bool isChasing = false;
public bool isRunning = false;
public bool isDead = false;
public bool isAttacking = false;
// Use this for initialization
void Start () {
__eam = GetComponent<EnemyAudioManager>();
attackSphere = attackSphereContainer.GetComponent<SphereCollider>();
anim = GetComponent<Animator>();
StartCoroutine(playerCheck());
}
// Update is called once per frame
void Update () {
timeSinceLastAttack += Time.deltaTime;
if (isChasing)
{
chasePlayer(playersInRange[0]);
}
}
public IEnumerator playerCheck()
{
//print("checking for players...");
playersInRange = Physics.OverlapSphere(transform.position, searchRadius, playerOnly);
if(playersInRange.Length == 0)
{
//print("no players found");
isChasing = false;
anim.SetBool("isChasing", false);
}
else
{
//print("player<s> found, generating list");
int i = 0;
while (i < playersInRange.Length)
{
float dAway = Vector3.Magnitude(transform.position - playersInRange*.transform.position);*
RaycastHit wallCheck;
if(Physics.Linecast(transform.position, playersInRange*.transform.position, out wallCheck, wallBlocks))*
{
//print(“player in range, no line of sight”);
}
else if (dAway < enemyChaseRange)
{
isChasing = true;
//chasePlayer(playersInRange*);*
}
i++;
}
}
yield return new WaitForSeconds(0.15f);
StartCoroutine(playerCheck());
}
public void chasePlayer(Collider player)
{
if (isDead)
{
isAttacking = false;
}
else
{
float dAway = Vector3.Magnitude(transform.position - player.transform.position);
Vector3 playerPos = player.transform.position + Vector3.up * transform.position.y;
transform.LookAt(playerPos);
transform.Translate(Vector3.forward * enemySpeed * Time.deltaTime);
if (dAway < enemyChaseRange && !isRunning)
{
if (dAway < 2.0f)
{
anim.SetBool(“isAttacking”, true);
anim.SetBool(“isChasing”, true);
}
else
{
anim.SetBool(“isAttacking”, false);
anim.SetBool(“isChasing”, true);
}
}
else if (dAway < enemyChaseRange && isRunning == true)
{
if (dAway < 2.0f)
{
anim.SetBool(“isAttacking”, true);
anim.SetBool(“isRunning”, true);
}
else
{
anim.SetBool(“isAttacking”, false);
anim.SetBool(“isRunning”, true);
}
}
}
}
}
You should use OnDrawGizmos function as a good way to check how big your aggro sphere is in the Scene view.