Pim Middelberg
Pim Middelberg

Reputation: 11

Coroutines and triggers

My problem is that I'm making a game with unity, and what I want to do is when the enemy in my game hits the obstacle, it does x damage every one second.

There's a collider and health script on the "desk" obstacle, and a collider and script for movement and attacking on the enemy.

The enemy stops when colliding with the desk object, and does damage! but, the damage is continuous... I've tried coroutines and Invoke's but all the results are the same; 10 damage per trigger detection, not per second.

Here are the scripts:

Enemy movement and attack:

private Animator anim;
public GameObject Desk;
private DeskHealth deskHealth;
//private bool inQueue = false;
private bool collidingWithDesk;
public float timeAfterStart;
[Range(0,10)]
public float attackSpeedEnemy = 1f;

[Range(10,100)]
public float walkSpeed;

[SerializeField] float damageDealtToDesk = 10f;


void Start () {
    anim = GetComponent<Animator>();  
    deskHealth = GetComponent<DeskHealth>();
    collidingWithDesk = false;
}

void Update()
{
    if (collidingWithDesk == false)
    {
        enemyIsWalking();
    }
}

void enemyIsWalking()
{
    transform.Translate(0, 0, (-walkSpeed * Time.deltaTime));
}

IEnumerator enemyIsAttacking()
{
    var deskHealth = Desk.GetComponent<DeskHealth>();
    deskHealth.DealDamageToDesk(damageDealtToDesk);
    yield return new WaitForSeconds(5f);        
}

void OnTriggerStay(Collider otherCollider)
{
    if (otherCollider.tag == "Desk")
    { 
        collidingWithDesk = true;
        transform.Translate(0, 0, 0);
        anim.Play("enemyHit");
        StartCoroutine(enemyIsAttacking());
    }
}

desk Health:

[SerializeField] float deskHealth;
Animator anim;

public void DealDamageToDesk(float deskDamage)

{
    deskHealth -= deskDamage;
    if (deskHealth <= 0)
    {
        print("am ded");
        //anim.Play("deskDestroyed");
    }
}

Upvotes: 0

Views: 1275

Answers (1)

La pieuvre
La pieuvre

Reputation: 468

For what the doc says "OnTriggerStay is called once per physics update for every Collider other that is touching the trigger." Which mean that your code :

if (otherCollider.tag == "Desk")
{ 
    collidingWithDesk = true;
    transform.Translate(0, 0, 0);
    anim.Play("enemyHit");
    StartCoroutine(enemyIsAttacking());
}

will be called every update then pause for 5 seconds because of yield return new WaitForSeconds(5f); You should use OnColliderEnter or it might be even better to use OnTriggerEnter instead, because this one will be called once. Then change the value inside the WaitForSeconds call to 1 if you want it once per second.

Also as specified by Draco18s your yield wait for nothing. You should do something like that :

IEnumerator enemyIsAttacking()
{
    var deskHealth = Desk.GetComponent<DeskHealth>();
    while(collidingWithDesk)
    {
        deskHealth.DealDamageToDesk(damageDealtToDesk);
        yield return new WaitForSeconds(1f);        
    }
}

void OnTriggerExit(Collider otherCollider)
{
    if (otherCollider.tag == "Desk")
    { 
        collidingWithDesk = false;
        // rest of your code
    }
}

Upvotes: 1

Related Questions