combotree 可以异步加载吗_Unity AssetBundle 资源打包,加载,本地缓存方式,安卓,PC本地加载路径问题...

本文详细介绍了Unity中的AssetBundle概念、作用及使用流程,包括资源打包、AssetBundle的本地同步/异步加载,以及服务器下载加载。此外,还解决了资源在不同平台的本地路径问题和材质丢失问题。
摘要由CSDN通过智能技术生成

AssetBundle的定义和作用:

1,AssetBundle是一个压缩包包含模型、贴图、预制体、声音、甚至整个场景,可以在游戏运行的时候被加载。

2,AssetBundle自身保存着互相的依赖关系。

3,压缩包可以使用LZMA和LZ4压缩算法,减少包大小,更快的进行网络传输。

4,把一些可以下载内容放在AssetBundle里面,可以减少安装包的大小。

AssetBundle使用流程(打包方法):

1,首先要选中需要打包的资源在Inspector面板最下方指定这个资源的AssetBundle属性(包名和后缀),注意这里的名字和后缀是不区分大小写的,如下图:

3f10b958e79abc786d0d5186ac7af372.png

d53d19525a89f75f99da8682d22ad563.png

2,构建AssetBundle,这里需要用到编辑器扩展技术,我把资源打包在了StreamingAssets目录下,这是一个Assets下的特殊目录,StreamingAssets也就是流式资源载入目录,该目录被拷贝到build文件夹中,不会修改,一般用于放置音频文件。代码如下:

public class CreateAssetBundles
{

    [MenuItem("Tools/Build AssetBundle")]
    static void CreateAssetBundle()
    {
        string path = "Assets/StreamingAssets";

        if(Directory.Exists(path) == false)//判断这个文件夹存不存在
        {
            Directory.CreateDirectory(path);
        }

        BuildPipeline.BuildAssetBundles(path, BuildAssetBundleOptions.None, BuildTarget.Android);

    }
}

3,在编辑器下面打包出来的AB包可以放在本地上,也可以放在服务器上加载。

AssetBundle资源的加载(本地加载,服务器下载):

1,本地同步加载AssetBundle包并且获取包的内容方式,AssetBundle.LoadFromFile(string path),从磁盘上的文件同步加载AssetBundle,代码如下:

 private void LoadFromFile(string path)
    {
       
        //传入这个AB包存在本地的路径加载本地资源
        AssetBundle ab = AssetBundle.LoadFromFile(path);

        //获取可使用AssetBundle这个类里面的LoadAsset<T>(string name)方法获取资源
        GameObject wallPrefab = ab.LoadAsset<GameObject>("CubeWall");

        Instantiate(wallPrefab);//实例化这个游戏物体

    }

2,本地异步加载AssetBundle包并且获取包的内容方式,AssetBundle.LoadFromMemoryAsync(byte[] bytes),代码如下:

IEnumerator LoadFromMemoryAsync(string path)
    {
       
        //打开二进制数组文件,并将打开的数据传进去
        AssetBundleCreateRequest createRequest = AssetBundle.LoadFromMemoryAsync(File.ReadAllBytes(path));

        yield return createRequest;//等待加载时间

        AssetBundle ab = createRequest.assetBundle;//获取加载出来的东西

        GameObject prefab = ab.LoadAsset< GameObject > ("CubeWall");
        Instantiate(prefab);

    }

3,下面代码是异步加载的一个变形同步加载,AssetBundle.LoadFromMemory(byte[] bytes),他的作用有很多,下文会说到

private void LoadFromMemory(string path)
    {
        //异步加载的一个变形同步加载,传入具有AssetBundle数据的字节数组
        AssetBundle ab = AssetBundle.LoadFromMemory(File.ReadAllBytes(path));

        GameObject wallPrefab = ab.LoadAsset<GameObject>("CubeWall");//获取这个名字的游戏物体

        Instantiate(wallPrefab);//实例化这个游戏物体
    }

4,使用UnityWebRequestAssetBundle.GetAssetBundle(string uri)到服务器下载AB包,现在官方推荐的主流方式,以前使用的WWW方式下载,还有UnityWebRequest.GetAssetBundle(string uri)这两种方式都已经弃用了;使用这个方式不但可以下载服务器上的资源,同时他也可以加载本地的资源,但是强烈建议如果要加载本地资源,还是使用本地同步/异步加载的方式比较妥当,两种方式下面代码都有写到,留意代码注释:

IEnumerator MyUnityWebRequest()
    {
        //本地加载路径前面要加上file://否则会出错
        //string uri = @"file://D:Unity3D_ProjectAdvancedAsset Bundle ProjectAssetBundlescubewall.unity3d";
        //UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(uri);

        //服务器上下载
        UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle("http://localhost/AssetBundles/cubewall.unity3d");

        yield return request.SendWebRequest();

        if (string.IsNullOrEmpty(request.error) == false)//判断下载有没有出错,request.error表示错误信息
        {
            Debug.Log(request.error);//输出错误
            yield break;//退出携程
        }

        //AssetBundle ab = DownloadHandlerAssetBundle.GetContent(request);//获取下载到的资源

        //获取资源的另外一种方式,直接获取到UnityWebRequest下载到的东西然后强转成DownloadHandlerAssetBundle,然后再获取到AssetBundle
        AssetBundle ab = (request.downloadHandler as DownloadHandlerAssetBundle).assetBundle;

        GameObject prefab = ab.LoadAsset<GameObject>("CubeWall");

        Instantiate(prefab);
}

减少包大小打包方式:我们可以将一些共用的图片/材质单独打包成一个包,这样做可以大大的减小AB包的大小,因为我们在打包的时候系统或默认将这个包的依赖一起打包进去的,当我们打包的A包和B包都依赖同一个材质/图片时那么系统就会默认的将这个依赖同时打包到A包和B包里,这样就会导致我们打包出来的AB包比较大,但当我们将A包和B包的依赖单独打包成一个包时,这时系统就不会再将这个依赖打包到两个包里了,这样我们的包就会小很多,不过当我们要用到包的资源,在加载包的资源之前,先把这个包的依赖加载出来,加载包的依赖的,代码如下:(这里加载依赖的时候需要注意的是我们要加载的是跟文件目录名字一样的后缀为manifest包,比如我们上面构造AB包的时候是直接在Asset文件下创建了StreamingAssets将打包出来的包放在StreamingAssets这个文件夹下,那么我们加载的依赖包就是StreamingAssets.manifest这个包)

        //加载这个物体的依赖
        //加载生成AB包文件时系统自动生成的一个名字跟文件目录一样的后缀为manifest包
        AssetBundle manifestAB = AssetBundle.LoadFromFile("AssetBundles/AssetBundles");

        //获取到他的AssetBundleManifest文件
        AssetBundleManifest manifest = manifestAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest");

        string[] strs = manifest.GetAllDependencies("cubewall.unity3d");//获取到传进去的包的所有依赖的包的名字

        //遍历并加载所有依赖的包
        foreach (string name in strs)
        {
            //加载依赖,将文件的根目录(我们打包出来的包的保存路径)+包名(即我们自己定义的AssetBundle打包的名字和后缀)传进去
            AssetBundle.LoadFromFile(rootDirectory + name);
        }

如何将从服务器上下载回来的AB包保存到本地上,代码如下:

1,要获取到服务器上下载回来的数据,需要用到UnityWebRequest.Get(string uri) 这个API去下载,只有使用这个API下载回来的资源我们才是可以访问到数据的,官方有一个专门用于下载AB包的API UnityWebRequestAssetBundle.GetAssetBundle(string uri)使用这个API下载回来的资源它是不支持原始数据访问的,也就是说我们想要保存从服务器上下载回来的AB包资源就不能使用这个API了,从服务器上下载AB包并保存到本地的代码如下:

 //获取服务器上的资源
    IEnumerator MyUnityWebRequest()
    {
        string uri = "http://localhost/AssetBundles/res.ab";//服务器地址

        request = UnityWebRequest.Get(uri);//要使用这种方式获取资源,才能访问到他的字节流

        //这个方法主要是用来获取AssetBundle资源的,但他下载到的数据是不给访问的,如果想访问或者保存下载回来的数据用上面的UnityWebRequest.Get()
        //request = UnityWebRequestAssetBundle.GetAssetBundle(pathMP);

        yield return request.SendWebRequest();
        
         //保存下载回来的文件
        if (request.isDone)
        {
            //构造文件流
           FileStream fs = File.Create(Application.persistentDataPath + "/res.ab");
            //将字节流写入文件里,request.downloadHandler.data可以获取到下载资源的字节流
           fs.Write(request.downloadHandler.data, 0, request.downloadHandler.data.Length);

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

        }

        //这里我们直接使用异步加载的一个变形同步加载,获取下载回来的资源
        ab = AssetBundle.LoadFromMemory(request.downloadHandler.data);

        //ab = (request.downloadHandler as DownloadHandlerAssetBundle).assetBundle;

    }

2,从服务器下载回来的数据并保存在本地后,如何加载保存在本地的数据,方式有很多种,可以用到上面介绍的,同步加载方式;异步加载方式;或者是异步加载的变形同步加载都可以主要看需求的,我这里使用了官方推荐的专门获取AB包的API来加载,代码如下:

IEnumerator MyData()
    {
        //加载保存在本地的资源
        request = UnityWebRequestAssetBundle.GetAssetBundle(Application.persistentDataPath + "/res.ab");

        yield return request.SendWebRequest();

        ab = (request.downloadHandler as DownloadHandlerAssetBundle).assetBundle;

       
    }

把打包好的AB包直接放在本地上StreamingAssets文件夹下,在进入游戏后直接从本地进行加载的路径问题(PC端与安卓端的路径)

1,为什么要放在StreamingAssets这个文件夹下来加载呢,因为该目录会被拷贝到

build文件夹中,不会修改,他是流式资源载入目录,而且官方也专门给我们封装了加载路径

2,加载StreamingAssets这个文件夹下的资源的路径是:

Application.streamingAssetsPath+"/"+文件名称组成,这里需要加载的资源要带后缀

这个路径的真实路径在PC端和安卓端都是不同的,Unity会根据发布的平台而进行变动,

值得一提的是在Unity旧版本里面发布安卓端,使用这个路径加载StreamingAssets

下的资源他是会报错的,但是现在新版本(2019版)经过实验是不会出现任何问题的不管

是PC端还是安卓端加载都没有任何问题,如果你的版本是旧版本或者是在安卓端加载时

路径出现问题,那么可以使用:

"jar:file://" + Application.dataPath + "!/assets/"+文件名称组成 这个路径,这个路径

是旧版本安卓端加载StreamingAssets文件夹下资源的路径。

加载AssetBundle 资源,运行游戏时出现材质丢失问题解决方法:

1,我们在打包AB包的时候,Unity默认是不连Shader一同打包进去的,所以当我们在

发布运行的时候就会出现材质丢失的问题,所以这个时候就需要我们自行添加了,添加步骤如

下:点击Edit>Project Settings>Graphics,然后下拉到Always Included Shaders,

将Size改大一些,然后在将丢失的那个材质所使用的Shader添加进去,然后再重新打包运

行就可解决材质丢失的问题。

c377b63436d7f932da0a5ae591600302.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值