[英]Unity3D Coroutine Error
我被Unity脚本困住了。 我有3个文件: Scene.cs , Player.cs和NetworkUtil.cs 。 我无法编译我的代码,因为我不知道如何将Coroutine响应传递回Scene。
在Scene.cs
( MonoBehavior
类)中:
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.cs
( Object
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.cs
( Object
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.cs
& Player.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.