- Home /
how to make AI change from patrol to chase within a certain range
hi, im trying to make a game where the enemy will attack the player when its close to it, but if the player gets within a certain range it chases them. this is my code for the enemy currently: using System.Collections; using System.Collections.Generic; using UnityEngine;
public class Enemy : MonoBehaviour {
private Transform target; //target player to follow
public Transform[] moveSpots; //patrol spots
private int randomSpot; //number of patrol spots
public int health; //enemy health
public float speed; //enemy speed
private float timeBetweenAttack; //time between attacks
public float StartTimeBtwAttack; //start countdown till attack
private float waitTime; //how long enemy stays at patrol spot for
public float startWaitTime; //start countdown till move to next spot
public GameObject BloodEffect; //death effect
public bool FindPlayer; //find player
public Animator enemyAnim; //animation state
public BoxCollider2D AttackCollider;
public CircleCollider2D ChaseCollider;
// Use this for initialization
void Start () {
target = GameObject.FindGameObjectWithTag("Player").GetComponent<Transform>(); //find the player to target
waitTime = startWaitTime; //make waittime equal to startwaittime
randomSpot = Random.Range(0, moveSpots.Length); //choose a random first spot
}
// Update is called once per frame
void Update () {
transform.position = Vector2.MoveTowards(transform.position, moveSpots[randomSpot].position, speed * Time.deltaTime); //move toward first patrol area
//------------------------------------------------------
if (timeBetweenAttack <= 0)
{
timeBetweenAttack = StartTimeBtwAttack;
}else //if timeBetweenAttack less than/equal to 0, set timeBetweenAttack to StartTimeBetweenAttack, if not start countdown.
{
timeBetweenAttack -= Time.deltaTime;
}
//-------------------------------------------------------
if(health <= 0) // if health is 0 then kill the enemy.
{
Destroy(gameObject);
}
if (Vector2.Distance(transform.position, moveSpots[randomSpot].position) < 1f) //asks if patrol point is further that 1f away from enemy
{
if (waitTime <= 0) //if waitTime less than or equal to 0
{
randomSpot = Random.Range(0, moveSpots.Length); //picks new patrol point
waitTime = startWaitTime; //restarts countdown clock
}
else
{
waitTime -= Time.deltaTime; //counts down clock till next point
}
}
}
public void TakeDamage(int damage)
{
Instantiate(BloodEffect, transform.position, Quaternion.identity); //create blood effect
health -= damage; //take damage from health
Debug.Log("Damage Taken");
}
public void OnTriggerEnter2D(Collider2D collision)
{
if (timeBetweenAttack <= 0) //asks if timeBetweenAttack less than or equal to 0
{
if (collision.transform.name == "Player") //asks if transform name equals "player"
{
if (collision = AttackCollider)
{
Debug.Log("enemy attack");
collision.GetComponent<HealthSystem>().Damaged(); //activates Damaged() function from 'HealthSystem' script
enemyAnim.SetTrigger("Attack"); //sets animation state to Attack
enemyAnim.SetTrigger("Finish"); //sets animation state to Finish
}
else
{
if (collision = ChaseCollider)
{
if (Vector2.Distance(transform.position, target.position) > 0.5f) //asks if target is further than 0.5f away from enemy
{
Start();
transform.position = Vector2.MoveTowards(transform.position, target.position, speed * Time.deltaTime); //tells the enemy to move toward target
}
}
enemyAnim.SetTrigger("Finish"); //sets animation state to finish
}
}
}
}
}
the issue i'm having is that when i get the chase to work, the attack doesn't or vice-versa.i have two trigger colliders set to each of the collider variables but it doesn't seem to change anything, all i can get is the attack but it does it when the player enters the larger 'chase' collider.any help would be appreciated =).
Answer by hectorux · Nov 05, 2018 at 08:36 PM
There are to many things for making better that script, instead of checking every frame the life less than 0, just set it at the end of getting damage. For attack, you should make that only if it attacks, re-start the time between, if you dont make that, he will atack to air, wait the time, and then attack again. The onTriggerEnter will only exectue one time, so the transform.position = Vector2.MoveTowards(transform.position, target.position, speed * Time.deltaTime); will only happen one time, just when the player enters in range of enemy and it didnt attack the exact last frame he attacked in the air
do you have any recommendations on how to do the things you suggested in your comment? I'm fairly new to program$$anonymous$$g and am not very fluent in it. any help would be great
Sure, i made the same things when i started, try to have the Update the more clean as possible, use functions to concentrate every step, this also makes easier to try diferent apraoch, see whats goes wrong... etc.
For your case (i dont know exacly what you want) in the collision event, ins$$anonymous$$d of if(x=Y), use if(x==Y), the diference is in the first one you are setting x to be Y, and in the second you are comparing x with Y. Don't use Start function, is better to make a function called Reset (or something like) and assigned it to start and the parts you want it to.
To make more clear your code, try to use the else if() ins$$anonymous$$d of else{ if()}, just to make it more clear. Also i recomend you to change the orther of your conditions. I would start checking the collision type, then the tag ins$$anonymous$$d of name(it more clear... but you can still use name), and then i would check if i can hit the player. Then, inside this (not in the Update) i would reset the time you can hit the player:
if(attackTime<=Time.time){
attackTime=Time.time+TimeToWait;
AttackFunction();
}
If you have more questions, comment me :)
Your answer
Follow this Question
Related Questions
AI passes through walls and flies 2 Answers
My Eneny AI Script Wont Work? 2 Answers
What am I doing wrong with my AI? 1 Answer
freindly ai attack other ai. 2 Answers
How to update the nav mesh destination to a random point? 0 Answers