[原]unity3d之http多線程異步資源下載


鄭重聲明:轉載請注明出處 U_探索

本文誕生於樂元素面試過程,被面試官問到AssetBundle多線程異步下載時,愣了半天,同樣也被深深的鄙視一回(做了3年多u3d 這個都沒用過),所以發誓要實現出來填補一下自己的空白,同時分享給大家。說明:本人只在pc和Android下測試好使,其他平台未知!

直接貼代碼,都是C# http的API,不懂得自己百科。

using UnityEngine;
using System.Collections;
using System;
using System.Text;
using System.Net;
using System.IO;


internal class WebReqState
{
    public byte[] Buffer;
    
    public FileStream fs;
    
    public const int BufferSize = 1024;
    
    public Stream OrginalStream;
    
    public HttpWebResponse WebResponse;
    
    public WebReqState(string path)
    {
        Buffer = new byte[1024];
        fs = new FileStream(path,FileMode.Create);
    }

}

public class HttpHelper {

    string path = null;
    string assetName;
    public HttpHelper(string path)
    {
        this.path = path;
    }
    
    public  void AsyDownLoad(string url)
{
    Debug.Log(url);
    assetName = url.Split('/')[4];
    Debug.Log(assetName);
    HttpWebRequest httpRequest = WebRequest.Create(url) as HttpWebRequest;
    httpRequest.BeginGetResponse( new AsyncCallback(ResponseCallback), httpRequest);
}
    
    void ResponseCallback(IAsyncResult ar)
{
    HttpWebRequest req = ar.AsyncState as HttpWebRequest;
    if(req == null) return;
    HttpWebResponse response = req.EndGetResponse(ar) as HttpWebResponse;
    if(response.StatusCode != HttpStatusCode.OK)
    {
        response.Close();
        return;
    }
    Debug.Log(path+ "/"+assetName);
    WebReqState st = new WebReqState(path+ "/"+assetName);
    st.WebResponse = response;
    Stream responseStream = response.GetResponseStream();
    st.OrginalStream = responseStream;
    responseStream.BeginRead(st.Buffer,0,WebReqState.BufferSize,new AsyncCallback(ReadDataCallback),st);
}
    
    void ReadDataCallback(IAsyncResult ar)
{
    WebReqState rs = ar.AsyncState as WebReqState;
    int read =rs.OrginalStream.EndRead(ar);
    if(read>0)
    {
        rs.fs.Write(rs.Buffer,0,read);
        rs.fs.Flush();
        rs.OrginalStream.BeginRead(rs.Buffer, 0, WebReqState.BufferSize, new AsyncCallback(ReadDataCallback), rs);
    }
    else
    {
        rs.fs.Close();
        rs.OrginalStream.Close();
        rs.WebResponse.Close();
        Debug.Log(assetName+":::: success");
    }
}
}
View Code

下載部分:

if(GUI.Button(new Rect(0,0,100,30),"test"))
{
    string rootPath = Application.persistentDataPath;//android上保存到 /storage/sdcard0/Android/data/包名(例如:com.example.test)/files
    for(int i =0;i<str.Length;i++) //str是string型數組,存放部分assetbundle名字
    {
        Thread thread = new Thread(new ParameterizedThreadStart(DownAsset)); //ParameterizedThreadStart 多線程傳參 
        thread.Start(rootPath+"|"+str[i]); //只能帶一個object參數 所以使用字符串拼接
    }
} 
    
void DownAsset(System.Object file)
{
    string[] fileName = file.ToString().Split('|');
    HttpHelper help = new HttpHelper(fileName[0]);
    help.AsyDownLoad("http://192.168.0.103/unity/"+fileName[1]+".AssetBundle");//注意在手機上測試 該對Ip地址
}

 

下載完成后 可以去/storage/sdcard0/Android/data/包名(例如:com.example.test)/files查找對應文件

加載部分:

if(GUI.Button(new Rect(0,30,100,30),"load"))
{
    for(int i =0;i<str.Length;i++)
    {
        StartCoroutine(LoadAsset(str[i],i));
    }
}
IEnumerator LoadAsset(string name,int i)
{
    WWW w = new WWW("file://"+Application.persistentDataPath+"/"+name+".AssetBundle");
    yield return w;
    Instantiate(w.assetBundle.mainAsset,new Vector3(i*2,0,0),Quaternion.identity);
    w.assetBundle.Unload(false);
}

 

注意事項:

1、pc測試 需要修改IP地址,本地測試改為127.0.0.1 同時Application.persistentDataPath最好做修改,因為在pc上Application.persistentDataPath:C:\Users\用戶名\AppData\LocalLow\DefaultCompany\u3d工程名,可以下載到此文件夾下,但是加載的時候會報錯,沒什么權限之類的

2、android上需要stripping level設置為Disabled


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM