[原]unity3d之http多线程异步资源下载

本文诞生于乐元素面试过程,被面试官问到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");
    }
}
}
复制代码

下载部分:

复制代码
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

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity3D中,多线程的交互可以通过以下几种方式实现: 1. 协程(Coroutine):Unity提供了协程的机制,通过使用yield语句可以在不同的帧之间切换执行,以实现多线程的效果。协程适合处理一些需要在后台进行长时间计算或操作的任务,而不会阻塞主线程。 2. 线程(Thread):Unity并不直接支持多线程,但您可以使用C#提供的System.Threading命名空间来创建和管理线程。但需要注意的是,Unity中的大部分API都是在主线程中执行的,因此在使用线程时需要小心处理线程间的数据同步和协调。 3. 主线程调用(MainThreadDispatcher):如果您需要在其他线程中执行某些逻辑并与Unity主线程进行交互,可以使用MainThreadDispatcher来将操作推迟到主线程执行。MainThreadDispatcher是一个辅助类,可以将任务添加到主线程的队列中,以确保在正确的时机执行。 4. Job System 和 Burst Compiler:Unity 2018.1版本及以后引入了Job System和Burst Compiler,它们可以用于高效地在多个工作线程上执行计算密集型任务。Job System允许您将任务拆分为小的工作单元,并在多个工作线程上并行执行,而Burst Compiler可以优化任务的执行效率。 需要注意的是,在多线程编程中,需要特别注意线程安全和数据同步的问题,避免出现竞争条件和数据不一致的情况。此外,由于Unity的渲染和更新是在主线程中进行的,因此需要注意在其他线程中进行计算或操作时不要阻塞主线程,以避免影响游戏的性能和流畅度。 总之,Unity3D提供了多种方式来进行多线程的交互,您可以根据具体需求选择合适的方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值