簡體   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