Unity 从服务器加载AssetBundle资源写入本地内存,并将下载保存的AB资源从本地内存加载至场景

从服务器加载资源:

AB资源打包后有一个【目录文件】AssetBundle,他保存了所有AB资源的路径与名称,

通过aLLAssetBundleURL链接路径 组拼 从【目录文件】获得的AB资源的名字,然后再协程方法内编写相关代码,从而实现从服务器加载资源的功能。详细见代码。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using System.IO;

public class DownLoadAssetBundle : MonoBehaviour
{
    //AB资源文件保存在服务器中的位置(我的服务器寄了,加载不到了)
    private string mainAssetBundleURL = @"http://120.24.90.173/Luademo/AssetBundles/AssetBundles";
    private string aLLAssetBundleURL = @"http://120.24.90.173/Luademo/AssetBundles/";
    
    void Start()
    {
        StartCoroutine("DownLoadMainAssetBundle");
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            LoadAssetBundle();
        }
    }
    
    /// <summary>
    /// 下载主[目录]AssetBundle文件
    /// </summary>
    IEnumerator DownLoadMainAssetBundle()
    {
        //创建一个获取 AssetBundle 文件的 web 请求.
        UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(mainAssetBundleURL);

        //发送这个 web 请求.
        yield return request.SendWebRequest();

        //从 web 请求中获取内容,会返回一个 AssetBundle 类型的数据.
        AssetBundle ab = DownloadHandlerAssetBundle.GetContent(request);

        if (ab == null)
        {
            Debug.Log("not ab");
        }

        //从这个“目录文件 AssetBundle”中获取 manifest 数据.
        AssetBundleManifest manifest = ab.LoadAsset<AssetBundleManifest>("AssetBundleManifest");

        //获取这个 manifest 文件中所有的 AssetBundle 的名称信息.
        string[] names = manifest.GetAllAssetBundles();
        for (int i = 0; i < names.Length; i++)
        {
            //组拼出下载的路径链接.
            Debug.Log(aLLAssetBundleURL + names[i]);

            //下载单个AssetBundle文件加载到场景中.
            //StartCoroutine(DownLoadSingleAssetBundle(aLLAssetBundleURL + names[i]));
            
            //下载AssetBundle并保存到本地.
            StartCoroutine(DownLoadAssetBundleAndSave(aLLAssetBundleURL + names[i]));
        }

    }

    /// <summary>
    /// 下载单个AssetBundle文件加载到场景中
    /// </summary>
    IEnumerator DownLoadSingleAssetBundle(string url)
    {
        UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(url);
        yield return request.SendWebRequest();
        AssetBundle ab = DownloadHandlerAssetBundle.GetContent(request);

        //通过获取到的 AssetBundle 对象获取内部所有的资源的名称(路径),返回一个数组.
        string[] names = ab.GetAllAssetNames();
        for (int i = 0; i < names.Length; i++)
        {
            //Debug.Log(names[i]);

            //截取路径地址中的文件名,且无后缀名. 需要引入 System.IO 命名空间.
            string tempName = Path.GetFileNameWithoutExtension(names[i]);
            Debug.Log(tempName);

            //实例化.
            GameObject obj = ab.LoadAsset<GameObject>(tempName);
            GameObject.Instantiate<GameObject>(obj);
        }
    }

    /// <summary>
    /// 下载AssetBundle并保存到本地
    /// </summary>
    IEnumerator DownLoadAssetBundleAndSave(string url)
    {
        //UnityWebRequestAssetBundle.GetAssetBundle(string uri)使用这个API下载回来的资源它是不支持原始数据访问的.
        UnityWebRequest request = UnityWebRequest.Get(url);
        yield return request.SendWebRequest();

        //表示下载状态是否完毕.
        if (request.isDone)
        {
            //使用 IO 技术把这个 request 对象存储到本地.(需要后缀)
            //SaveAssetBundle(Path.GetFileName(url), request.downloadHandler.data, request.downloadHandler.data.Length);
            SaveAssetBundle2(Path.GetFileName(url), request);
        }
    }

    /// <summary>
    /// 方法1
    /// 存储AssetBundle为本地文件
    /// </summary>
    private void SaveAssetBundle(string fileName, byte[] bytes, int count)
    {
        //创建一个文件信息对象.
        FileInfo fileInfo = new FileInfo(Application.streamingAssetsPath + "//" + fileName);

        //通过文件信息对象的“创建”方法,得到一个文件流对象.
        FileStream fs = fileInfo.Create();

        //通过文件流对象,往这个文件内写入信息.
        //fs.Write(字节数组, 开始位置, 数据长度);
        fs.Write(bytes, 0, count);

        //文件写入存储到硬盘,关闭文件流对象,销毁文件对象.
        fs.Flush();
        fs.Close();
        fs.Dispose();

        Debug.Log(fileName + "下载完毕");
    }

    /// <summary>
    /// 方法2
    /// 存储AssetBundle为本地文件
    /// </summary>
    private void SaveAssetBundle2(string fileName, UnityWebRequest request)
    {
        //构造文件流.
        FileStream fs = File.Create(Application.streamingAssetsPath + "//" + fileName);

        //将字节流写入文件里,request.downloadHandler.data可以获取到下载资源的字节流.
        fs.Write(request.downloadHandler.data, 0, request.downloadHandler.data.Length);

        //文件写入存储到硬盘,关闭文件流对象,销毁文件对象.
        fs.Flush();
        fs.Close();
        fs.Dispose();

        Debug.Log(fileName + "下载完毕");
    }

    /// <summary>
    /// 从本地加载 AB 资源并实例化
    /// </summary>
    private void LoadAssetBundle()
    {
        //从本地加载 AB 资源到内存.
        AssetBundle assetBundle = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/player1.ab");

        //从 AB 资源中获取资源.
        GameObject player = assetBundle.LoadAsset<GameObject>("Necromancer");

        GameObject.Instantiate<GameObject>(player, Vector3.zero, Quaternion.identity);
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_55532142/article/details/125351463