2015-12-15 102 views
1

我想了解如何在Unity中編寫WWW調用。根據這裏的描述http://docs.unity3d.com/ScriptReference/WWW.html我可以檢查isDone屬性,但在同一頁面的示例中,它不會嘗試檢查isDone。在Unity中是WWW類的異步還是同步?

我的問題是,如果我打了一個WWW電話,它需要幾秒鐘的回覆,不會遊戲凍結?

我想認爲正確的代碼是這個,但是它?

StartCoroutine(WaitForResponse(myWWWObject)); 

private IEnumerator WaitForResponse(WWW aRequest) { 

    while (! aRequest.isDone) 
     yield return aRequest; 

} 

遊戲是否凍結,直到請求完成?或者它真的是異步的?

+0

從這個例子中,我猜測'yield return www;'行異步等待,直到下載頁面。該例中的 –

+0

它只是等待www請求結束(等待發生在「yield return www;」行)。 你也可以使用這個新的webrequest更多的控制:http://docs.unity3d.com/ScriptReference/Experimental.Networking.UnityWebRequest.html – mgear

+0

它是如何知道它是完整的,如果返回是IEnumerator ...沒有什麼以「測試」完成 – Elenesski

回答

1

你需要了解協同程序 - Unity的一個基本功能,允許你編寫長時間的代碼功能(例如:更長的時間然後一幀),而不是而不是凍結你的遊戲。

http://docs.unity3d.com/Manual/Coroutines.html

在C#中,你可以發現一個協程功能,因爲它有IEnumerator返回類型。並且您可以在C#關鍵字yield的代碼中發現函數將暫停的位置並再次繼續。

每個MonoBehaviour類都可以管理協程,如果您告訴它使用StartCoroutine()啓動它,那麼MonoBehaviour將在每個幀(有時多於一次)調用協程,直到協程結束。

對於WWW類(支持協同例程),你只需要調用這個:

WWW www = new WWW(url); 
    yield return www; 

您創建一個WWW類網址retrievve,產量基本被稱爲每一幀自動由MonoDevelop協程管理器管理,直到www對象表示它已完成(成功或失敗)。

在此期間,您的遊戲將不會凍結。

+0

我想我們需要回答點 –

+0

這聽起來對於我來說,線程是凍結的東西,因爲它是一個協程,它不會影響你的主要過程。只有您的主進程必須知道該線程已被鎖定並進行管理(例如,如果需要,可以將其關閉;例如停止所有協程)。 – Elenesski

+0

協程在主線程中運行 - 這是它們的關鍵原因 - 您不必擔心多線程。協程應該被設計成做很多小工作,然後通過產量放棄cpu。適合下載文件。對於你不能輕易放棄的繁重計算,線程仍然是一條可行的路線。 – peterept

0

在用於WWW鏈接文檔頁面,下面的方法是一個協程方法:

IEnumerator Start() { 
    WWW www = new WWW(url); 
    yield return www; 
    Renderer renderer = GetComponent<Renderer>(); 
    renderer.material.mainTexture = www.texture; 
} 

yield語句用於暫停執行,並且將控制返回到Unity,然後在接下來的比賽幀恢復執行。例如yield return null;將導致執行在下一幀中恢復。此外,可以使用從YieldInstruction類派生的類之一來擴展該行爲,例如WaitForSeconds

考慮yield return new WaitForSeconds(1f); - 這將在遊戲時間1秒後恢復執行。 WWW類以相似的方式工作。您可以使用該類的一個實例來執行,只有在下載完成後才返回,不需要手動輪詢isDone屬性。

請記住,你只能在Coroutines產量,我建議你閱讀它們。如果你不想在協程中做WWW請求,那麼你必須手動輪詢isDone並在完成時繼續。

要回答最後一個問題:創建WWW類的實例時遊戲是否會凍結? - 不,該課程異步工作。您可以在正常的更新/啓動等功能以及帶有良率的協同程序內使用它。

+0

協程是要走的路,因爲你無法保證外部站點的響應。此外,即使有響應的外部站點,網絡延遲也會爲請求增加大量時間,特別是如果編碼不好。 – Elenesski

+0

這取決於場景。 WWW類異步工作,所以它不會凍結主遊戲循環線程,除非你在一個while(!isDone)循環中包裝它。 – Bartosz

-1

如果我打了一個WWW電話,它需要幾秒鐘的回覆,不會遊戲凍結? 不,遊戲不會freez試試這個代碼,你會看到日誌「corou」後會立即顯示圖片下載。

public class WWWDemo : MonoBehaviour { 
    bool b = true; 
    // Use this for initialization 
    void Start() { 

    } 

    // Update is called once per frame 
    void Update() 
    { 
     if (b) { 
      StartCoroutine(ExampleCoroutine()); 
      Debug.LogWarning("after corou"); 
     } 

    } 

    IEnumerator ExampleCoroutine() 
    { 
     b = false; 
     Debug.Log("Time : " + DateTime.Now); 
     string url = "http://images.earthcam.com/ec_metros/ourcams/fridays.jpg"; 
     WWW www = new WWW(url); 
     yield return www; 
     Debug.Log("Time : " + DateTime.Now); 
     Renderer render = gameObject.GetComponent<Renderer>(); 
     render.material.mainTexture = www.texture; 
     Debug.Log("Time : " + DateTime.Now); 

    } 
} 

但下一行的執行將產生回報WWW的語句將等待unitl圖片下載後明確停止,而統一其餘的事件將執行異步

請分別考慮以下示例。開始事件執行它將等待,但更新將連續運行。

IEnumerator Start() { 
     Debug.Log("Time : " + DateTime.Now); 
     string url = "http://images.earthcam.com/ec_metros/ourcams/fridays.jpg"; 
     WWW www = new WWW(url); 
     yield return www; 
     Debug.Log("Time : " + DateTime.Now); 
     Renderer render = gameObject.GetComponent<Renderer>(); 
     render.material.mainTexture = www.texture; 
     Debug.Log("Time : " + DateTime.Now); 
    } 
void Update() 
    { 
      Debug.Log("update is running while start is waiting for downloading");   
    } 
相關問題