2015-12-15 79 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");   
    } 
相关问题