- Home /
Problem with enemy AI
Hey guys ! I have been trying to make an simple AI, that goes to player and when its in range, it attacks. All worked well, but then I added more attacks (like kick) and ruined my code :D It changes attacks depending on attNumber. If attnumber is 0 it makes attack 1 and increases attNumber. If attNumber is 1,it makes attack 2 and increase attNumber. Is same while having attNumber 1, but instead of increasing attNumber, it sets it 0 again. But when I play the game it makes all 3 attacks and then it stops. I tried everything but nothing worked. Please help me.
public class Chase : MonoBehaviour {
public Transform player;
public Animator anim;
public Slider healthbar;
public int attNumber;
public int attCooldown;
public int attCooldown2;
public int attCooldown3;
// Use this for initialization
void Start () {
anim = GetComponent<Animator>();
}
// Update is called once per frame
void Update () {
if (healthbar.value <= 0) return;
Vector3 direction = player.position - this.transform.position;
float angle = Vector3.Angle(direction, this.transform.forward);
//Když je dále než 25 a pod stupněm více než 100
if (Vector3.Distance(player.position, this.transform.position) < 25 && angle < 180)
{
direction.y = 0;
//Otoč se na něj
this.transform.rotation = Quaternion.Slerp(this.transform.rotation,
Quaternion.LookRotation(direction), 0.1f);
//Vypni Idle
anim.SetBool("isIdle", false);
//Když je dále než 5, jdi k němu
if (direction.magnitude > 5)
{
this.transform.Translate(0, 0, 0.05f);
anim.SetBool("isWalking", true);
anim.SetBool("isAttacking", false);
}
//Jinak když je blíže než 5 ...
if(direction.magnitude < 5)
{
// ... attNumer je 0 tak použij útok 1, vypni Walk a zvyš attNumber o 1
if (attNumber == 0)
{
anim.SetBool("isAttacking", true);
anim.SetBool("isAttacking2", false);
anim.SetBool("isAttacking3", false);
anim.SetBool("isWalking", false);
StartCoroutine(AttCooldown());
attNumber = attNumber + 1;
}
else if (attNumber == 1)
{
anim.SetBool("isAttacking2", true);
anim.SetBool("isAttacking", false);
anim.SetBool("isAttacking3", false);
anim.SetBool("isWalking", false);
StartCoroutine(AttCooldown());
attNumber = attNumber + 1;
}
else if (attNumber == 2)
{
anim.SetBool("isAttacking3", true);
anim.SetBool("isAttacking", false);
anim.SetBool("isAttacking2", false);
anim.SetBool("isWalking", false);
StartCoroutine(AttCooldown());
attNumber = 0;
}
else
{
anim.SetBool("isAttacking", false);
anim.SetBool("isAttacking2", false);
anim.SetBool("isAttacking3", false);
attNumber = 0;
}
}
}//Jinak zapni Idle a vypni Walk
else
{
anim.SetBool("isIdle", true);
anim.SetBool("isWalking", false);
}
}
IEnumerator AttCooldown()
{
yield return new WaitForSeconds(attCooldown);
}
}
I would try to actually put the change of the attack number inside of the coroutine, after the 'WaitForSeconds' call.
IEnumerator AttCooldown()
{
yield return new WaitForSeconds(attCooldown);
attNumber++;
if( attNumber > 2 ){
attNumber = 0;
}
}
I'm not really sure it would help, but from the first look at it, it seems that you start the coroutine and then instantly change the attack number, and then while the coroutine is still playing, the update method changes the number of attack and it repeats this way.
You should look into FS$$anonymous$$'s. The idea behind a Finite State $$anonymous$$achine is that the object exists in only one state at a time, and upon switching the state, the behaviour is different. If you simply want to cycle through attacks or choose one at random, you could always keep an array of attack numbers and random through it prior to the attack method, or as @Scoutas pointed out that your coroutine doesn't do anything, so switching the attack type in there would be optimal. Still a coroutine isn't a good way to handle cooldowns. It is a repeating method, infinitely repeating unless stopped, and if you stop it after each 1st iteration it makes it even less useful. Basically ALL a coroutine does is this.
private bool isActive;
private float time;
public float IterateTime;
void Update()
{
if (isActive)
{
if (time > 0)
{
time -= Time.deltaTime;
}
else
{
time = IterateTime;
DoStuff();
}
}
}
public void DoStuf()
{
}
just a tip : try to break your code into functions as well as create a better animation controller
if (attNumber == 0)
{
Punch();
}
else if(attNumber == 1)
{
$$anonymous$$ick();
}
else if(attkNumber == 2 )
{
Shoot();
}
Answer by divovo · Apr 02, 2017 at 09:56 AM
Thank you guys ! I hav dne it another way and it seems to work ! Thanks everyone !
attCooldown = 0;
if (attNumber == 0 && attCooldown <= 0)
{
Attack1();
attCooldown = attCooldownDeposit;
attCooldown -= Time.deltaTime;
attNumber += 1;
}
else if (attNumber == 1 && attCooldown <= 0)
{
Attack2();
attCooldown = attCooldownDeposit;
attCooldown -= Time.deltaTime;
attNumber += 1;
}
else if (attNumber == 2 && attCooldown <= 0)
{
Attack3();
attCooldown = attCooldownDeposit;
attCooldown -= Time.deltaTime;
attNumber = 0;
}
else
{
NotAttack();
}
Your answer
Follow this Question
Related Questions
Enemy AI problems 2 Answers
EnemyAI C# Error 1 Answer
Super Sonic Movement Help 1 Answer
the attack is synchronized if there is more than one enemy 1 Answer
Looping Between Waypoints 1 Answer