Use WWW and UnityWebRequest in the Editor Window plugin

Viewed 857

In Unity I have a custom window and I am trying to load an image from Amazon S3 and display it within the window. However, my function doesn't seem to execute. If I put a Debug.Log in the function it never gets logged, however, a Debug.Log before the function gets called (LoadAvatarTexture) does log. From what I understand is that IEnumerator doesn't work in an EditorWindow class, but works for a MonoBehaviour class. What can I do to make my editor window load an image?

public class MyEditorWindow : EditorWindow {

  Texture2D avatarTexture;

  [MenuItem("GameSmart/Player Manager", false, 0)]
  public static void ShowManager() {
    var window = EditorWindow.GetWindow(typeof(MyEditorWindow));
    window.titleContent = new GUIContent("Player Manager");
    window.minSize = new Vector2(400, 300);
  }

  void OnGUI() {
    var loadPlayer = GUILayout.Button("Load Player");
    if (loadPlayer) {
      Debug.Log("I log to the console just fine");
      LoadAvatarTexture("http://dev-avatars.gamesmart.com/default.png");
    }
    if (avatarTexture != null) {
      float aspect = (float)avatarTexture.width / (float)avatarTexture.height;
      Rect previewRect = GUILayoutUtility.GetAspectRect(aspect, GUILayout.Width(100), GUILayout.ExpandWidth(true));
      GUI.DrawTexture(previewRect, avatarTexture, ScaleMode.ScaleToFit, true, aspect);
    }
  }

  IEnumerator LoadAvatarTexture(string url) {
    Debug.Log("I do not log to the console");
    var www = new WWW(url);
    yield return www;
    avatarTexture = www.texture;
  }

}
1 Answers

However, my function doesn't seem to execute.

That's because LoadAvatarTexture is a coroutine function. You don't call a coroutine function like a normal function. You start it with the StartCoroutine function. For example, StartCoroutine(LoadAvatarTexture()).

Even starting it with StartCoroutine wouldn't work in your particular case because this is an Editor plugin and StartCoroutine requires instance of MonoBehaviour to work. You only get access to StartCoroutine when your script derive from MonoBehaviour but it doesn't.

You have two options:

1. Continue to have the LoadAvatarTexture function as a coroutine function which it is currently is but get instance of MonoBehaviour from the camera or any Object in the scene. I prefer the main camera since it's unlikely to be disabled.

Replace

LoadAvatarTexture("http://dev-avatars.gamesmart.com/default.png");

with

//Get camera's MonoBehaviour
MonoBehaviour camMono = Camera.main.GetComponent<MonoBehaviour>();
//Use it to start your coroutine function
camMono.StartCoroutine(LoadAvatarTexture("http://dev-avatars.gamesmart.com/default.png"));

Note that you must check for error before using the request. Below is your new LoadAvatarTexture function modified to check for error:

IEnumerator LoadAvatarTexture(string url)
{
    Debug.Log("I do not log to the console");
    var www = new WWW(url);
    yield return www;
    if (string.IsNullOrEmpty(www.error))
        avatarTexture = www.texture;
    else
        Debug.Log(www.error);
}

2. Another option is to make the LoadAvatarTexture function to be a normal (void) function instead of coroutine function then use WWW.isDone to determine when the request is done.

void OnGUI()
{
    var loadPlayer = GUILayout.Button("Load Player");
    if (loadPlayer)
    {
        Debug.Log("I log to the console just fine");
        LoadAvatarTexture("http://dev-avatars.gamesmart.com/default.png");
    }

    //Check if request is done then get the texture
    if (www != null && www.isDone)
    {
        if (string.IsNullOrEmpty(www.error))
            avatarTexture = www.texture;
        else
            Debug.Log(www.error);

        //Reset
        www = null;
    }

    if (avatarTexture != null)
    {
        float aspect = (float)avatarTexture.width / (float)avatarTexture.height;
        Rect previewRect = GUILayoutUtility.GetAspectRect(aspect, GUILayout.Width(100), GUILayout.ExpandWidth(true));
        GUI.DrawTexture(previewRect, avatarTexture, ScaleMode.ScaleToFit, true, aspect);
    }
}

WWW www;
void LoadAvatarTexture(string url)
{
    Debug.Log("I do not log to the console");
    www = new WWW(url);
    if (string.IsNullOrEmpty(www.error))
        avatarTexture = www.texture;
    else
        Debug.Log(www.error);
}
Related