Wait for seconds Enemy IA

Hey guys, i’m making my first 2.5D platformer, i’m not a programmer.

I’m having troubles when trying to make my enemy wait to attack again if the player still in attack range.

Could someone please help? There’s a video showing the problem.

public class Locust : MonoBehaviour
{
    public GameObject LocustObj, KickDust, KickColliders, DeadDust, LocustSfx, KickSfx;

    void Start()
    {
        KickDust.SetActive(false);
        DeadDust.SetActive(false);
        KickSfx.GetComponent<AudioSource>().Stop();
    }

    private void OnTriggerEnter(Collider collision)
    {
        if (collision.gameObject.tag == "Player")
        {
            KickColliders.GetComponent<Animator>().SetTrigger("Action");
            LocustObj.GetComponent<Animator>().SetTrigger("Attack");
            LocustSfx.GetComponent<AudioSource>().Play();
            KickSfx.GetComponent<AudioSource>().Play();
            KickDust.SetActive(true);
        }
    }

    private void OnTriggerStay(Collider collision)
    {
        if (collision.gameObject.tag == "Player")
        {
            new WaitForSeconds(2);
            KickColliders.GetComponent<Animator>().SetTrigger("Action");
            LocustObj.GetComponent<Animator>().SetTrigger("Attack");
            LocustSfx.GetComponent<AudioSource>().Play();
            KickSfx.GetComponent<AudioSource>().Play();
            KickDust.SetActive(true);
        }
    }
}

WaitForSeconds doesn’t work if it’s not in a coroutine. As you’ve written it, it does nothing. You’re actually just declaring a value and not assigning it to a variable. I’ll leave it up to you to look up coroutines if you aren’t familiar with them.

However, I think you’d be better rolling your own timer. When a player enters the trigger, reset the initial timer value to 0. Then while in the stay, keep adding to eat. (Usually just adding Time.DeltaTime). If that value goes above a number like 2, trigger the attack. If not, just keep adding. If an attack is triggered, reset the value to 0.

If the player leaves the trigger, you could reset it there instead. Just whatever feels better for you.

Oh, @kdgalla posted this on another post about waitForSeconds and I feel like it’s a good explanation here also.

Hi there,

alternatively you could also start a coroutine on trigger enter that yields a waitForSeconds in a loop and verify if conditions are still met after given time

        private void OnTriggerEnter2D(Collider2D collision)
        {
            StartCoroutine(Attack(.5f));
        }

        private IEnumerator Attack(float interval)
        {
            // Or any more specific condition
            while (true)
            {
                if (ConditionNotMet)
                    yield break;

                DoAttack();

                yield return new WaitForSeconds(interval);
            }
        }

CAUTION: the code above has no interlock to prevent multiple running of this coroutine.

This is an immediate “tell” that a coroutine is a bad solution to this problem.

Coroutines are NOT always an appropriate solution: know when to use them!

https://discussions.unity.com/t/857304/4

https://discussions.unity.com/t/849607/7

As Brathann identified above, just use a timer. This is ultra simple to do:

Cooldown timers, gun bullet intervals, shot spacing, rate of fire:

https://discussions.unity.com/t/821482/2

GunHeat (gunheat) spawning shooting rate of fire:

https://discussions.unity.com/t/824570/2

What I meant with my post is that if farrico decided to go for WaitForSeconds, coroutine was one way of handling it.
You are right to add a CAUTION note, I didn’t dive into too much detail but checking that the coroutine isn’t already running is indeed crucial.
I however don’t think coroutines are necessarily a bad idea for this use case as long as they’re used right. A timer is also another way to go