# Coroutine Helper

## What for

Sometime you want to call coroutines **not** from Monobehaviour.\
Or you want to make delay before doing smth.

CoroutineHelper will help in this situations.

### How to use

add **`using Game.Core;`**

In non-Monobehaviour classes:

```csharp
[System.Serializable]
public class NotMonoBehaviour {
    [SerializedField] private float attackPerformDelay;
    private Coroutine performAttackProccess;
    
    public void DoAttack() {
        // stops coroutine if it's running
        CoroutineHelper.Stop(ref performAttackProccess);
        
        // starts new coroutine, 
        // we remember coroutine obj to stop it then to avoid demon behaviour
        performAttackProccess = CoroutineHelper.Run(PerformAttack);
    }
    
    private IEnumerator PerformAttack() {
        print("Attack perform!");
        // .. some stuff
    }
}
```

In MonoBehaviour:

```csharp
[System.Serializable]
public class Example : MonoBehaviour {
    [SerializedField] private float attackPerformDelay;
    private Coroutine performAttackProccess;
    
    public void DoAttack() {
        // 1. you can stop coroutine running on this behaviour like this
        // note that first parameter is MonoBehaviour where coroutine runs (this)
        CoroutineHelper.Stop(this, ref performAttackProccess);
        // 2. or use equivalent snippet:
        if (performAttackProccess != null) {
            StopCoroutine(performAttackProccess);
            performAttackProccess = null;
        }
        
        // start new coroutine, 
        // we remember coroutine obj to stop it then to avoid demon behaviour
        performAttackProccess = StartCoroutine(PerformAttack);
    }
    
    private IEnumerator PerformAttack() {
        print("Attack perform!");
        // .. some stuff
    }
}
```

### CoroutineHelper.WaitForAction()

How to use invoke function delays like unity Invoke() function but with CoroutineHelper (benefit is that we can stop it and pass parameters):

{% hint style="warning" %}
You should **not** use Unity Invoke(name, delay) function because you can't stop it.
{% endhint %}

```csharp
[System.Serializable]
public class Example : MonoBehaviour {
    [SerializedField] private float attackPerformDelay;
    private Coroutine performAttackProccess;
    
    public void DoAttack() {
        // You can stop delay like this:
        CoroutineHelper.Stop(ref attackPerformDelay);
    
        // Do attackPerformDelay and Invoke PerformAttack()
        performAttackProccess = 
            CoroutineHelper.WaitForAction(PerformAttack, attackPerformDelay);
    }
    
    private void PerformAttack() {
        print("Attack perform!");
        // .. some stuff
    }
    
    // example how to call method with delay and parameters
    CoroutineHelper.WaitForAction(() => YouMethod(parameters), delay);
}
```

{% hint style="info" %}
DOTween package has similar functionality (you can use it or CoroutineHelper):

you can use DOVirtual.DelayedCall(method, delay) that runs method after delay and you can stop it like coroutine:

`Tween delay = DOVirtual.DelayedCall(method, delay);`\
`// to kill`\
`delay.SafeKill();`
{% endhint %}

{% hint style="danger" %}
To avoid error on app close if you use coroutines that runs on CoroutineHelper instance and want to stop coroutine execution in OnDestroy() callback from other MonoBehaviour\
\
-> User CoroutineHelper.IsInstanceExist check before stopping, if it's false then do not call CoroutineHelper in OnDestroy().
{% endhint %}
