WaitForSeconds without Monobehaviour

Hello,

i use a class, which is not a derived from Monobehaviour. In these class i need a function WaitForSeconds:

IEnumerator wait(int s) {
	Debug.Log(Time.time);
	yield return new WaitForSeconds(s);
	Debug.Log(Time.time);
}

Of course i could to it with

System.Threading.Thread.Sleep(2000);

but the screen shouldn’t freeze. Is there another solution like WaitForSeconds?

Thank you

1 Like

Hm, that sounds like an interesting question. I don’t have an answer jet but I found three links about that:

http://answers.unity3d.com/questions/379440/a-simple-wait-function-without-coroutine-c.html Check especially the comment of Julien.Lynge

http://unitygems.com/threads/

http://forum.unity3d.com/threads/94220-A-more-flexible-coroutine-interface

Hope that you find an answer in one of the links. I definitely will check them when I find some time :wink:

As long as there is at least one object in the scene that inherits MonoBehaviour (and there always should be), then you can find it and use it as a surrogate for managing coroutines in your class. But, the only thing that this avoids is the requirement to pass a MonoBehaviour object specifically to it, which really isn’t all that impressive.

using UnityEngine;
using System.Collections;

public class Test
{
    private MonoBehaviour _mb; // The surrogate MonoBehaviour that we'll use to manage this coroutine. 

    public void StartCoroutine()
    {
        Debug.Log("Starting...");
        _mb = GameObject.FindObjectOfType<MonoBehaviour>();
        if (_mb != null)
        {
            Debug.Log("Found a MonoBehaviour.");
            _mb.StartCoroutine(CoroutineTest());
        }
        else
            Debug.Log("No MonoBehaviour object was found in the scene (which should basically be impossible).");
    }

	private IEnumerator CoroutineTest () 
    {
        Debug.Log("Hello");
	    yield return new WaitForSeconds(1);
        Debug.Log("World");
    }
}

ps
Just keep in mind that FindObjectOfType isn’t a very cheap operation. So, if you’re going to be calling coroutines this way frequently, you should cache the MonoBehaviour object that you find for future coroutine calls and avoid calling FindObjectOfTime every time you want to start it.

pps
This will probably fail if the MonoBehaviour object that it finds is disabled.

Something a bit more flexible -

public class SomeClass
{
    IEnumerator DoSomething()
    {
        yield return new WaitForSeconds(5);
        Debug.Log("Done");
    }
}

public class SomeMono : MonoBehaviour
{
    public IEnumerator DoCoroutine(IEnumerator cor)
    {
        while (cor.MoveNext())
            yield return cor.Current;
    }
}

// then you could do this somewhere in SomeClass
someMonoInstance.StartCoroutine("DoCoroutine", this.DoSomething());
4 Likes

Im at work so cant give you the exact code atm, but i have a custom wait function that sets the current time to a variable, adds n seconds then when current time equals the modified time returns a bool as true. Its not the cleaneat in the world, but it works for my purpose.

Couldnt you derive the base class from monobehavior then access those functions through the child( again, not home cant test, never tried).

thanks a lot, that works for me :slight_smile:

one last question:
ist it possible to wait till the end? My code looks like this:

public static void doSth(int[] list) {
	foreach (int t in list) {
	...
					
		_mb.StartCoroutine(wait(t));
				
		Debug.Log(Time.time);
			
	}
}

static IEnumerator wait(float s) {
		
	yield return new WaitForSeconds(s);
}

Edit: Never mind, I had a dumb idea but tested it and it won’t work.

This throws the following error:
An object reference is required to access non-static member `UnityEngine.MonoBehaviour.StartCoroutine(string, object)’