- Home /
Coroutine?
Is there a way to run coroutines in classes which does not inherit from monobehaviour? Or is there any other way to use yield return null in such a class?
Yes to the second question. yield
is a C# iterator thing, it's not Unity-specific. The function it's used in has to return IEnumerator
or IEnumerable
, and the proscription against ref
and out
parameters is part of C# too. You could have one in any class.
you can bypass the ref issue with a delegate:
IEnumerator $$anonymous$$yCoroutine(System.Action<bool> action) //Bool for the example, any type will do
{
// Some stuff
action(false)
// more stuff maybe
yield return null;
// Could be more there
action(true);
// or even there
}
And you use it:
bool myBool = false;
StartCoroutine(value => myBool = value);
Answer by Huacanacha · Mar 26, 2015 at 08:12 AM
You need a MonoBehaviour to tap into Unity's Coroutine system. As mentioned by Bonfire Boy the yield syntax is not Unity specific so in theory you could write your own Coroutine scheduler, but there are much easier ways.
Here are two options:
Create an new GameObject and add a MonoBehaviour component to it and use this to call StartCoroutine.
Have a MonoBehaviour in the scene that acts as your Coroutine caller. Use this to start the coroutine.
And here is a sample implementation for the first case:
coroutineHandler = new GameObject("_coroutineHandler");
coroutineHandler.AddComponent<MonoBehaviour>();
coroutineHandler.StartCoroutine(YourCoroutine());
Answer by Hrungdak · Mar 26, 2015 at 07:11 AM
You can run any public method in any class as coroutine. You can call a coroutine only from a monobehaviour-class.
Can you explain the first sentence? For example, how would I run function B in the following as a coroutine?
public class A
{
public void B() { };
}
The answer is incorrect, or at least confusingly written. To run a method as a Coroutine it needs to be in a specific format (i.e. returns an IEnumerator) and does not necessarily need to be public.
I expect they mean that you can call a Coroutine style method directly and it will execute like a standard function, but you can only get the Coroutine behaviour by calling it in a StartCoroutine on a $$anonymous$$onobehavior.
Now, Huacanacha is right, to run the method it has to meet some requirements. Example: First script calls a coroutine:
using UnityEngine;
public class CallCoRoutine : $$anonymous$$onoBehaviour {
void Start ()
{
CalledClass calledClass = new CalledClass();
StartCoroutine(calledClass.RunAsCoRoutine());
}
}
Second script: contains a method that is called, the method must return IEnumerator:
using System.Collections; using UnityEngine;
public class CalledClass {
public IEnumerator RunAsCoRoutine() {
Debug.Log("Coroutine running.");
yield return null;
}
}
This works in Unity. In my first post i did not mention that the called method must have a specific signature. For me that was obvious because i work with delegates on a daily basis. Sorry for that.
Answer by mustafa swiedan · Mar 27, 2015 at 05:51 AM
you can't , the only way to do this is to create another class that inherits from monobehaviour and inside it create an instant of the class that doesn't inherit from monobehaviour and call it's methods from the instant.
Answer by Ramlock · Mar 27, 2015 at 06:02 AM
Is there a way to run coroutines in classes which does not inherit from monobehaviour?
I'm not sure, but I have a theory:
The StartCoroutine() method is what makes the Coroutines work, but it is non-static, meaning it requires an instance of a MonoBehaviour (or derived) class in order to be called. That said, it's also public, meaning it can be called by any class that has a reference to that instance.
What I mean is that the following code will possibly work.
using UnityEngine;
using System.Collections;
class Test
{
MonoBehaviour mono;
public void StartMyCoroutine()
{
mono = new MonoBehaviour();
mono.StartCoroutine("myCoroutine");
}
private IEnumerator myCoroutine()
{
while (true)
{
//Do stuff...
yield return null;
}
}
}
If the above code doesn't work, then I'm afraid the answer is a very simple "no :/".
HOWEVER!
If you're not on a MonoBehaviour derived class, then Coroutines are probably not what you want. Instead, try using Threading: https://msdn.microsoft.com/en-us/library/aa645740%28v=vs.71%29.aspx
Or is there any other way to use yield return null in such a class?
Yes, since yield is a C# keyword: https://msdn.microsoft.com/en-us/library/vstudio/9k7k7cf0.aspx
Perhaps you'd like to check the accepted answer?
A $$anonymous$$onoBehaviour needs to exist in the scene to be considered active. Therefore an unattached new $$anonymous$$onoBehaviour won't actually do anything as it doesn't get Unity Engine events. You need to attach it to something in the scene, which could be an existing GameObject you know about or you can create a new one (per my answer above).
I actually wrote that right after the question was asked, but no moderators accepted it in time... -.-"
Ah ;)
At least I could also explain why the pure $$anonymous$$onoBehaviour method doesn't work!
True. I actually expected that, but it was worth the try ^^
In any case, I still have no idea why he wants so badly to use a coroutine outside a monobehaviour, it doesn't make any sense to me... $$anonymous$$y guess is that he just doesn't know how to use threads, which would probably be way better/cleaner.