繁体   English   中英

Unity3D协程错误

[英]Unity3D Coroutine Error

我被Unity脚本困住了。 我有3个文件: Scene.csPlayer.csNetworkUtil.cs 我无法编译我的代码,因为我不知道如何将Coroutine响应传递回Scene。

Scene.csMonoBehavior类)中:

void OnGUI() {
  if(GUI.Button(new Rect(0, 0, 100, 100), "Register")) {
    StartCoroutine(registerPlayer());
  }
}
IEnumerator registerPlayer() {
  return Player.NewPlayer("Raptor"); // since Player is not IEnumerator, this line causes error.
}

Player.csObject class)中:

public static Player NewPlayer(string name) {
  Player p = new Player();
  result = p.tryRegister();
  if(result) {
    return p;
  } else {
    return null;
  }
}

private bool tryRegister() {
  Dictionary<string, string> data = new Dictionary<string, string>();
  data.Add("some_key", "some_value");
  NetworkUtil.ExecuteAPI(data);
}

NetworkUtil.csObject class)中:

public static IEnumerator ExecuteAPI(Dictionary<string, string> data) {
  WWWForm form = new WWWForm();
  form.AddField("mode", request);
  foreach(KeyValuePair<string, string> entry in data) {
    form.AddField(entry.Key, entry.Value);
  }

  WWW handler = new WWW(API_URL, form);
  yield return handler;
  if(handler.error != null) {
    Debug.Log("Error occurred: " + handler.error); // Server Error
  } else {
    Debug.Log("Response: " + handler.text);
  }
}

如何更改代码以使流程完整?

注意:在Object类中, StartCoroutine()不存在。


编辑

我已更改代码以使用“代表和事件”:

// DelegatesAndEvents.cs
public class DelegatesAndEvents : MonoBehaviour {
    public delegate void RegisterEventHandler(Player player);
    public static event RegisterEventHandler onPlayerRegister;

    public static void NewPlayerRegistered(Player player) {
        if(onPlayerRegister != null) {
            onPlayerRegister(player);
        }
    }
}

然后在Scene.cs

void Start() {
  DelegatesAndEvents.onPlayerRegister += this.userRegistered;
}

public void userRegistered(Player player) {
  Debug.Log("User registered.");
}

我应该如何将触发器放入NetworkUtil.csPlayer.cs

这样做有多种方法,因为您不仅需要返回IEnumerator ,而且要在其上进行迭代的是Unity本身,因此您不可能捕获返回值。

从技术上讲,可以执行以下操作:

IEnumerator registerPlayer() {
  yield return Player.NewPlayer("Raptor"); // this is legal, player will be the Current value of the IEnumerator
}

如果您想做类似上面的代码的事情,则需要 coroutine 包装在另一个内,然后自己对其进行迭代(我做了类似的实现行为树的操作):

IEnumerator Wrap(IEnumerator playerRegister)
{
  while(playerRegister.MoveNext())
  {
    Player p = playerRegister.Current as Player; //this can be done if you know what you are doing
    yield return null; 
  }
}

另一种方法是不返回任何内容,而是将委托传递给coroutine ,这将被称为将必需的参数传递回调用方。

就像是:

IEnumerator DoSomething(Action<Response> whenDone)
{
  while (doingSomething)
    yield return null;

  whenDone(response);
}

编辑

您的代码的另一个问题是您正在从Player的构造函数内部调用另一个协程( ExecuteAPI )。 因此,使registerPlayer成为协程是没有意义的,因为您不会产生任何结果。

在您的情况下,最简单的方法是将一个委托传递给ExecuteAPI ,当您从服务器收到响应时将调用该委托。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM