- Home /
Yielding with WWW in Editor
Hello!
I'm working on an editor tool that needs some SQL connectivity. It is an internal bug tracker. I've written a php script that will return the data I need formatted correctly, and it works, but, I have to force the application to wait using the disgusting while(!www.isDone)
approach.
In my EditorWindow
, I have a function:
public void RefreshData() {
SQL.query("SELECT * FROM users");
}
Whereas, the query method in question is somewhat like this.
public static void query(string q) {
WWW www = new WWW("...?query="+WWW.EscapeURL(q));
while(!www.isDone);
if(www.error != null)
Debug.LogError(www.error);
else
Debug.Log(www.text);
}
This works beautifully... obviously, I'll get it to return the necessary data when I write the parsing functionality, but my question is: Is there any way I can used the yield return www;
to get it to not hang the Unity Editor when I have more queries to parse?
Since this is a static method built into a static editor class, I cannot attach a MonoBehavior
to anything... thus, I cannot use the StartCoroutine method. Is there some C# interface I can implement on my EditorWindow that requires a Coroutine Scheduler?
Is there any hope for me, or will my tool forever hang?
why do you say obviously? I would say that this works only if www is multithread. I did not know it was multithread.
Hey, so even though this question is a couple of years old, I made a plugin that that makes it possible to use coroutines in Editor code: http://forum.unity3d.com/threads/released-editor-coroutines.289703/
Answer by kjems · Apr 22, 2012 at 03:47 PM
I made a ContinuationManager to handle the cases where I want to wait for a condition and then do something with an object.
The snippet below is an example of WWW using the ContinuationManager where the condition to trigger the continuation is www.isDone. The lambda closure captures the www object so it can be used when the www is done. The code is non-blocking.
var www = new WWW("someURL");
ContinuationManager.Add(() => www.isDone, () =>
{
if (!string.IsNullOrEmpty(www.error)) Debug.Log("WWW failed: " + www.error);
Debug.Log("WWW result : " + www.text);
});
The ContinuationManager
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
internal static class ContinuationManager
{
private class Job
{
public Job(Func<bool> completed, Action continueWith)
{
Completed = completed;
ContinueWith = continueWith;
}
public Func<bool> Completed { get; private set; }
public Action ContinueWith { get; private set; }
}
private static readonly List<Job> jobs = new List<Job>();
public static void Add(Func<bool> completed, Action continueWith)
{
if (!jobs.Any()) EditorApplication.update += Update;
jobs.Add(new Job(completed, continueWith));
}
private static void Update()
{
for (int i = 0; i >= 0; --i)
{
var jobIt = jobs[i];
if (jobIt.Completed())
{
jobIt.ContinueWith();
jobs.RemoveAt(i);
}
}
if (!jobs.Any()) EditorApplication.update -= Update;
}
}
$$anonymous$$ade gist with a few more features and xml documentation comments https://gist.github.com/createdbyx/2c43c0518f622a652442
Up until Unity 5.5 this was working great for us. Starting at Unity 5.5 it stopped working. Any ideas what might have changed from Unity to break this?
Answer by Gru · Aug 03, 2016 at 06:09 PM
My solution: http://www.ennoble-studios.com/tuts/making-unitys-www-class-work-in-editor-scripts.html
Hah, didn't see there was a 2nd page before posting my own. #4 on this link actually looks promising.
Answer by DaveA · Feb 28, 2012 at 02:00 AM
Does it have to be static? I've had pretty good luck using MonoBehaviour and ExecuteInEditMode, use Update to check isDone.
As great as that might be, this is supposed to work for every scene. A $$anonymous$$onoBehavior
object needs to be attached to something in the Game for it to even be instantiated - I need something that can exist in any scene and be a permanent fixture in the entire project.
How about...wait for it... a singleton with DontDestroyOnLoad()! Another day, another singleton post from me :D - Oops, this question is 2 months old x(
Answer by Skjalg · Sep 28, 2012 at 06:24 AM
In order to yield in an editor method you need to use a regular c# Thread.
http://msdn.microsoft.com/en-us/library/aa645740(v=vs.71).aspx
Does not work. WWW needs to be on the main thread.
Answer by Aurelinator · Apr 10, 2012 at 03:39 PM
So. Im saying that this class needs to exist independent of what's loaded in the scene. It is a bug tracker that connects to a database to retrieve bugs. If I create a brand new scene - I don't want to have to go ahead and create an object that for some magical reason uses game time to do something that ought to be simple.
I had just wondered if anyone had found out how to avoid the lag associated with do a WWW request in editor only code.
Honestly I had the same problem, but since the lag is not an issue for me, for the time being I use www synchronously. I watch this question in case you find a solution.
Your answer
Follow this Question
Related Questions
yield return request never returns 2 Answers
yield on a www never completes 10 Answers