- Home /
Coroutines and Static function
Hi, I need to call a coroutine from a static function.
I don't know too much about coroutines... but I think I need it for loading a file using WWW.
I found this, but I don't understand how to use it...
Here is my static function:
public static string getFile(string path){
www = new WWW(path);
return www.text;
}
Any helps?
Seriously?
To have a web page processing in another script is that complicated?
I am having the same: Coroutine 'imgcube' cannot be automatically started from a static function.
and i have to spend 1 hour to learn this new type of event handling ins$$anonymous$$d of having a yield statement in a static function?
that's well inconvenient for U3D 1/10 for workflow!
Answer by whydoidoit · Mar 23, 2013 at 11:40 AM
Ok so you can't do what you want to do quite like that. The WWW will not wait when you call this, so when you call getFile you cannot have the string immediately. A good way of handling this is to use closures (it's techy, more on Unity Gems).
So I presume you currently do something like this:
someString = SomeClass.getFile("SomeURL");
Debug.Log(someString);
Process(someString);
Because of the delay we need to execute the 2nd and 3rd lines when the data is available, not straight away. To do that we create an Action closure.
SomeClass.getFile("SomeURL",(someString)=>{
Debug.Log(someString);
Process(someString);
});
So we've defined the subsequent statements as a thing we can call when the data is available. Now we need to modify the code from that other thread so that it can deal with all of this! Here's the code - add it to an new empty GameObject in your scene:
StaticCoroutine.cs
public class StaticCoroutine : MonoBehaviour{
static public StaticCoroutine instance; //the instance of our class that will do the work
void Awake(){ //called when an instance awakes in the game
instance = this; //set our static reference to our newly initialized instance
}
IEnumerator Perform(IEnumerator coroutine, Action onComplete = null)
{
onComplete = onComplete ?? delegate {};
yield return StartCoroutine(coroutine);
onComplete();
}
static public void DoCoroutine(IEnumerator coroutine, Action onComplete = null){
instance.StartCoroutine(instance.Perform(coroutine, onComplete)); //this will launch the coroutine on our instance
}
}
Now we modify getFile to call that code and pass on your closure:
public static void getFile(string path, Action<string> onComplete)
{
StaticCoroutine.DoCoroutine(DoGetFile(path, onComplete));
}
static IEnumerator DoGetFile(string path, Action<string> onComplete)
{
var www = new WWW(path);
yield return www;
onComplete(www.text);
}
So to round up - there's a modified version of the code from that other thread that works the way we need it to. You've rewritten getFile to start the coroutine and pass on the functions that you want to execute when the data is available later. Please note that in that function you now pass to getFile you can still access local variables - but do not access foreach or for loop variables unless you use a copy you take of them (it's a weird glitch).
Thanks for your reply!! I'm learning a lot of stuff :)
I got this error:
NullReferenceException: Object reference not set to an instance of an object
I/Unity ( 2035): at StaticCoroutine.DoCoroutine
on the line: instance.StartCoroutine(instance.Perform(coroutine, onComplete));
ohhh: instance is null... but why? :)
The Awake method of StaticCorouting is not called...hmmm
If the was called I don't see how instance could be null... Which is what that line appears to be complaining of. You did attach it to an active game object in your scene? Are you calling the getFile from a static constructor or as a variable allocation? That might happen before Awake.
Yes the problem is that the script was not attached on an active object... but now it works... The routine is called, the file content is retrieved, and I can print the xml file on the log file!
I get another error, but I think it's not referred to this topic: when I run:
new XmlDocument.LoadXml(someString) it displays the following error:
XmlException: Text node cannot appear in this state. Line 1, position 1.
I/Unity ( 4939): at $$anonymous$$ono.Xml2.XmlTextReader.ReadText (Boolean notWhitespace) [0x00000]
Anyway since I can see the content of the xml file in the someString variable, I think your first reply solved the problem!!
Thanks so much!
Your answer
Follow this Question
Related Questions
Getting strings from WWW 0 Answers
How to save to a database on application close 2 Answers
Ios problem with www class 2 Answers
loading asset bundle function 1 Answer