Basic Following AI
Hello, I am trying to make cube enemies swarm a player. However I don't know where to start, or how to get the cube to follow the player and if it "sees" an obstacle go around it, maybe using ray casts. If possible I would like to keep all code in C#. Please Help and thank you!!
Answer by Fadawar · Feb 29, 2016 at 07:06 AM
I found that if I use the Navigation utility that Unity has I can add a NavMeshAgent to my enemy, and then by baking the surroundings using the Navigation Window, make the enemy follow the player via its transform. Link to Unity Tutorial: Here
using UnityEngine;
using System.Collections;
[RequireComponent (typeof(NavMeshAgent))]
public class EnemyMovement : MonoBehaviour
{
public Transform player;
NavMeshAgent nav;
void Awake ()
{
player = GameObject.FindGameObjectWithTag ("Player").transform;
nav = GetComponent <NavMeshAgent> ();
}
void Update ()
{
nav.SetDestination (player.position);
}
}
Answer by Incognito357 · Feb 29, 2016 at 04:36 AM
Looks like you want to look into pathfinding. There are many different types, their uses depending on how complicated or 'smart' you need or want it, and also depending on the type of terrain or area that the AI needs to navigate. Each have different performance costs of using as well. I'd look into the breadth-first algorithm if you're just starting out.
If your terrain is flat, it makes things easier to start. You can divide the terrain into 'tiles', which can correspond to an array, with locations that are obstacles marked as such in the array. Once you have this information, you can then use an algorithm to find a path between two points in the array. Depending on the algorithm, the path isn't necessarily the shortest or fastest route or most direct. A breadth-first search would probably be the shortest route in your case.
This person has done a good job of explaining briefly different types of pathfinding algorithms: http://gamedev.stackexchange.com/a/28044
Answer by nickostan · Feb 29, 2016 at 03:28 AM
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[i].transform.position);
RaycastHit wallCheck;
if(Physics.Linecast(transform.position, playersInRange[i].transform.position, out wallCheck, wallBlocks))
{
//print("player in range, no line of sight");
}
else if (dAway < enemyChaseRange)
{
isChasing = true;
//chasePlayer(playersInRange[i]);
}
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.
Answer by Zoogyburger · Feb 29, 2016 at 03:40 AM
Here's a real simple enemy follow script.
public Transform Player;
public float speed = 2f;
private float minDistance = 0.2f;
private float range;
void Update ()
{
Player = GameObject.FindWithTag ("Player").transform;
range = Vector2.Distance(transform.position, Player.position);
if (range > minDistance)
{
Debug.Log(range);
Player = GameObject.FindWithTag ("Player").transform;
transform.position = Vector2.MoveTowards(transform.position, Player.position, speed * Time.deltaTime);
}
}
}
Thank all of you for replying, I have tried to implement Zoogyburger's code, but it seems to only slide and follow the player on the x axis and won't move on the z axis to. What would I need to do in order to make this Happen? Thank you!!
Also I'm using 3d models, but I'm just using the camera to look straight down.
Hey @Fadawar, sorry I didn't know that it was a 3d game you were trying to make. In this case make my Vector 2s to a Vector 3s I suppose.
Your answer
Follow this Question
Related Questions
Enemy AI aggro based on damage 0 Answers
Enemy pathfinding script for a 2D top down shooter game 0 Answers
RPG Help please! i dont have a clue anymore 0 Answers
Scripts vs ScriptableObject 1 Answer
enemy patrolling using javascript??? 0 Answers