WWW需要注意的問題
1.WWW.LoadFromCacheOrDownload的侷限性
WWW.LoadFromCacheOrDownload只能用於AssetBundle類型,而且只有這些屬性有值,且訪問不會報錯:
assetBundle, progress, error, url, Dispose()
其它的函數和屬性都會報錯,size、bytesDownloaded、bytes、audioClip ...
很多人都在這個地方耗費了不少時間,這麼不友好的設計真是要不得。
2.WWW.EscapURL的純粹性
C#中類似的功能叫做UrlEncode,這類函數的用途只是對path和query部分進行編碼,而不是對整個url編碼。
例如:
http://www.baidu.com/下載完畢
編碼就變成:
http%3a%2f%2fwww.baidu.com%2f%e4%b8%8b%e8%bd%bd%e5%ae%8c%e6%af%95
這樣的url地址,瀏覽器不認,所有的程序都不認,一定要注意。
WWW.EscapURL就是個純粹的編碼函數,如果已經編碼了,再次調用會重複編碼,不會智能檢測。
WWW手冊說
Note: URL must be '%' escaped.
經測試,未編碼的url也可以,可能是新版內部已經自動對url智能編碼。
3.在WWW加載過程中訪問其屬性要慎重
在WWW.isDone返回true之前,好多屬性的訪問會報錯:assetBundle,audioClip, bytes ...
在加載過程中,訪問這些屬性不會報錯:isDone, progress, uploadProgress, error, url
尤其注意:如果網絡比較卡,在加載過程中訪問bytesDownloaded不僅會報錯,而且卡死整個主線程。我本來想用bytesDownloaded除以已知的size得到加載進度,看來只能用WWW.progress了。
4.同步和異步問題
不管有沒有使用yield return www,WWW都是異步加載的。但推薦使用yield,經測試發現不使用協程序,如下代碼就會造成卡頓:
客戶端代碼Test.cs:
public class Test : MonoBehaviour
{
WWW www;
float time;
void Update()
{
string url = "http://127.0.0.1/1.php";
if (www == null)
{
time = Time.time;
www = new WWW(url);//會卡頓
//StartCoroutine(load(url));//不會卡頓
}
if (Time.time - time > 1f)
{
Debug.Log("timeout");
www.Dispose();
www = null;
}
}
IEnumerator load(string url)
{
www = new WWW(url);
yield return www;
}
}
服務端代碼1.php:
<?php
sleep(2);//延遲2秒
echo "hello world!";
5.加載線程和主線程
我使用了yield return www,然後又在主線程中Update中不停的檢測www的屬性,於是就發生了下面的錯誤。
get_assetBundle can only be called from the main thread.
Constructors and field initializers will be executed from the loading thread when loading a scene.
Don't use this function in the constructor or field initializers, instead move initialization code to the Awake or Start function.
這段話的意思是不要在成員變量聲明的時候和構造函數裏面調用unity對象的屬性,因爲成員變量聲明和構造函數是在“加載線程”中的,unity變量的屬性只能在主線程中調用,協程的執行不在主線程中,所以出現此錯誤?
下面這句話會報錯:
public static DirectoryInfo dir = new DirectoryInfo(Application.persistentDataPath + "/");
6.WWW不僅僅是個加載器
WWW不僅不數據從網絡或本地磁盤加載到內存,而且還對assetBundle(lzma壓縮包)進行了解壓縮。我以前認爲不僅解壓縮,而且還把texture、audio等資源解碼出來,其實沒有,text、bytes、texture等屬性是調用的時候才動態解碼出來的。
WWW做的事情不夠純粹,好處是方便,壞處是耦合,試想手遊更新過程:把資源從網絡上下載下來,然後寫入本地磁盤,這個過程根本不需要對assetBundle解壓縮。好在要更新的內容一般不是很多,更新完畢可以立即釋放assetBundle,就不必單獨用HttpClient等類進行更新了。
7.不要反覆直接調用WWW的屬性
反編譯WWW的源碼可以看到text、bytes、texture等屬性是動態獲取的,沒調用一次就要重新計算一次。
public string text
{
get{
if (!this.isDone)
{
throw new UnityException("WWW is not ready downloading yet");
}
byte[] bytes = this.bytes;
return this.GetTextEncoder().GetString(bytes, 0, bytes.Length);
}
}
public extern byte[] bytes
{
[WrapperlessIcall]
[MethodImpl(MethodImplOptions.InternalCall)]
get;
}
public Texture2D texture
{
get
{
return this.GetTexture(false);
}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.