2014-02-24 45 views
1

我被困在Unity腳本中。我有3個文件:Scene.cs,Player.csNetworkUtil.cs。我無法編譯我的代碼,因爲我不知道如何將Coroutine響應傳遞迴Scene。Unity3D協程錯誤

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類):

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類):

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); 
    } 
} 

我怎樣才能改變f代碼低完整?

注意:在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

+1

如果您使用委託...我注意到您有引用被添加到Start()方法中。確保在OnEnable()方法中添加引用,然後在OnDisable()方法中將其刪除,以避免內存泄漏。 – AnxGotta

回答

2

有幾種方法可以做到這一點,因爲你不僅需要返回一個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,當你從服務器收到響應時會調用該代理。

+0

代碼可以用腳本的第一部分編譯,但我不知道如何應用腳本的第二部分和第三部分。那麼如何在我的代碼中應用這些? OnGUI()函數應該是什麼?修改我的原始代碼後,OnGUI()包含'StartCoroutine(registerPlayer());'。 – Raptor

+0

感謝您的編輯;這似乎指向了我正確的方向。我嘗試應用委託和事件,但遇到一些問題。請參閱我的編輯問題,謝謝。 – Raptor

+0

由於WWW異步調用在您的NetworkUtils類中,我想在那裏您想在收到響應時引發事件。 – Heisenbug