I want to use Coroutine in my script. But I couldn't use "StartCoroutine" because I didn't inherit MonoBehaviour.
As far as I know, I have to inherit Monobehaviour to use Coroutine. But now I can't inherit Monobehaviour. Is there any way to use Coroutine in this situation? The same goes for the Invoke function.
CodePudding user response:
I will call what you want to achieve: a Coroutine Management feature and my understanding is that you want to include that feature inside your non-MonoBehaviour class. But thanks to my Remember quote above you cannot do it right now.
But including it in-side a .dll might be possible as a .dll can contain many classes. And you can use Access Modifiers to enforce your rules (the internal modifier is my favorite).
If I were you I would treat Coroutine Management as a separate problem and would build a .dll to handle them separately so that it would not mess up with my game-play business.
CodePudding user response:
You could do what @Nikel said, and create a new MonoBehaviour
class to use for your Coroutine
, or you could pass a MonoBehaviour
in parameters:
public class Timer
{
private IEnumerator _timerCoroutine;
private readonly Action _action;
private readonly float _timeToWaitInSeconds;
/// <summary>
/// Creates a new timer that will execute the given action after the given time.
/// </summary>
/// <param name="timeToWaitInSeconds"></param>
/// <param name="action"></param>
public Timer(float timeToWaitInSeconds, Action action)
{
_timeToWaitInSeconds = timeToWaitInSeconds;
_action = action;
}
/// <summary>
/// Starts a timer that will execute an action after the time has passed
/// </summary>
/// <param name="monoBehaviour">The MonoBehaviour that will be used to start the coroutine</param>
public void Start(MonoBehaviour monoBehaviour)
{
_timerCoroutine = TimerCoroutine();
monoBehaviour.StartCoroutine(_timerCoroutine);
}
/// <summary>
/// Stops the timer
/// </summary>
/// <param name="monoBehaviour">The MonoBehaviour that will be used to stop the coroutine</param>
public void Stop(MonoBehaviour monoBehaviour)
{
monoBehaviour.StopCoroutine(_timerCoroutine);
}
/// <summary>
/// The coroutine that will execute an Action after the time has passed
/// </summary>
/// <returns></returns>
private IEnumerator TimerCoroutine()
{
yield return new WaitForSeconds(_timeToWaitInSeconds);
_action?.Invoke();
}
}
Then create a Timer
in a MonoBehaviour
as follows:
private void Start()
{
var timer = new Timer( 5f, () => Debug.Log("Timer with 5 seconds finished") );
timer.Start(this);
}
CodePudding user response:
Coroutine doesn't work without MonoBehaviour, but if you want to use Coroutine in non-MonoBehaviour class you can transmit MonoBehaviour class in constructor or create empty MonoBehaviour to run coroutines on them. It`s will looks like:
pubclic class CoroutineHost : MonoBehaviour{}
public class NonMonoClass
{
private CoroutineHost _host;
NonMonoClass()
{
_host = new GameObject("CoroutineHost")
.AddComponent<CoroutineHost>();
}
public void RunYourCoroutine()
{
_host.StartCoroutine(nameof(YourCoroutine));
}
// Here is should be your coroutine logic
private IEnumerator YourCoroutine();
//Finalizer need to destroy gameobject
//when non-mono class will be ready for garbage collection.
~NonMonoClass()
{
_host.StopAllCoroutines();
GameObject.Destroy(_host.gameobject);
_host = null;
}
}