• (转)Resources和AssetBundle(新旧版)学习


    Resources:
     
    Resources的缺点:1.与显示Inspector上直接引用相比,Resources使用不方便.
        2.不管你Resources上的资源是否调用了,当你发布的时候,Resources上的资源会全部一起打包掉,无法作更新.
     
    Resources里的方法:
    Resources.Load :动态加载特殊文件夹Resources里的文件.
    Resources.UnloadAsset:回收指定的缓存.
    Resources.UnloadUnusedAsset:回收没有被引用的缓存
     
    这里加点额外东西,如果保存东西到Resources文件夹,而Resources文件夹不存在保存时候会报错,所以要添加预防机制(不仅这里用,还可以延伸到许多方面):
    首先引用System.IO和UnityEditor 前者是Directory需要,后者是AssetDatabase需要     
            string filePath = Application.dataPath + "/Resources";
            if (!Directory.Exists(filePath)) //检测Resources文件夹是否存在
            {
                AssetDatabase.CreateFolder("Assets","Resources"); //创建Resources文件夹
            }
       GameObject go = 随便;
       AssetDatabase.CreateAsset(go,"Assets/Resources/go.prefab");//创建文件go
       AssetDatabase.Refresh(); //刷新一下
     
    AssetBundle:

    AssetBundle可以把你所需要用的文件(音乐,纹理,模型,prefab,场景)用特殊的文件格式导出(.unity),在适当的时候再导入这些文件.


    在一些大型游戏里面,一个场景里面的内容非常的多,如果一下子全部加载完可能要等很长的时间,玩家等读条读完都想睡了.我们可以先读取附近的内容,进去后再慢慢读取其他内容,这样可以有效利用内存资源.动态加载资源可以用AssetBundle,Resources.Load().
     
    AssetBundle最初的设计目的好像是为了简化游戏更新.
     
    AssetBundle可以打包任何Unity能够识别的文件,由文件格式决定.如果你想要打包任何自定义的二进制文件,你要把后缀名改为".bytes".Unity会把他们打导成TextAssets
     
    有创建资源包的方式:
    unity5:在Inspector的最下方
    然后调用函数BuildPipeline.BuildAssetBundles()就行了.他会根据依赖关系自动打包.
    但有一个非常深的坑:他不会给你自动判断哪些资源是公用的,也就是你有2个文件同时使用同一个Texture,但你这个Texture没有设置AssetBundle他会重复打印1次.
    用这种打包方法下面MOMO的方法也无法用了,因为AssetBundle.CreateFromFile不能加载压缩过的AssetBundle.
     
    具体用法:
    [MenuItem ("Assets/Build AssetBundles")] static void BuildAllAssetBundles () { BuildPipeline.BuildAssetBundles ("AssetBundles");
    //BuildPipeline.BuildAssetBundles ("Assets/AssetBundles");
    //这个方法其他重载的参数与旧版没差
    }
    要先在项目文件夹里创建AssetBundles这个文件夹.注意是项目文件夹而不是Assets里,这是官方代码,为了方便我请倾向于改成注释的样子.AssetBundles中,会出现2种文件格式,1.是没有后缀的,2.是后缀是.manifest.
    没有后缀的是代表项目的依赖关系,有后缀名的用txt打开可以看到其资源依赖关系和crc.
     
    旧版:
    (需要注意的方式1,3为了不同平台打包的文件是不通用的)
    1.BuildPipeline.BuildAssetBundle :可以构建任意类型的资源包
    public static function BuildAssetBundle(mainAsset: Object, assets: Object[], pathName: string, out crc uint, assetBundleOptions:BuildAssetBundleOptions, targetPlatform: BuildTarget): bool;
    直接拿个最长的来作参数解释 :  
    mainAsset:打包的单个文件.  assets:打包的文件组. pathName:存放地址 
    out uint crc:输出一个参数作为检测更新使用,当使用WWW.LoadFromCacheOrDownLoad函数的时候可以使用此参数. 
    assetBundleOptions:特殊选项,可以输入0(没有特殊选项).  targetPlatform : 选择该包要使用的平台
        [MenuItem("Test/Create AssetBundles")]
        static void CreateAssetBundle()
        {
    //选择保存文件的途径
            string path = EditorUtility.SaveFilePanel("Save Resource", "", "New Resource", "assetbundle");
     
            if (path.Length != 0)
            {
       //Project里选中的文件
                Object[] selection = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);
     //这里第1参数和第2参数好像重复了,第1参数填null完全没影响.官方代码也不能尽信...
                BuildPipeline.BuildAssetBundle(Selection.activeObject, selection, path);
                Selection.objects = selection;
            }
        }
    2.BuildPipeline.BuildStreamedSceneAssetBundle:只打包场景.
    3.BuildPipeline.BuildAssetBundleExplicitAssetNames:BuildPipeline.BuildAssetBundle差不多,只是多了参数自定义每个物体的名字.
    方式2,3用法和方式1差不多.
     
    读取资源包:
    最好的例子就是官方例子了,很详细.
    假如我把打包文件放到Resources里,文件名叫a.unity3d
     
    void Start(){
    //在不同的平台上,路径是不同的,这个需要注意
    public static readonly string path = 
    #if UNITY_ANDROID 
    "jar:file://" + Application.dataPath + "!/assets/"; 
    #elif UNITY_IPHONE 
    Application.dataPath + "/Raw/"; 
    #elif UNITY_STANDALONE_WIN || UNITY_EDITOR 
    "file://" + Application.dataPath + "/StreamingAssets/"; 
    #else 
         string.Empty;  
    #endif
    StartCoroutine(LoadAssetBundle(path + "a.assetbundle"));
    }
     
    IEnumerator LoadAssetBundle(string path) {
            //根据参数1(服务器或本地下载地址)和参数2(版本号)查找AssetBundle.如果本地找不到就会从服务器下载(即更新版本)
            WWW www = WWW.LoadFromCacheOrDownload(path, 1);
     
            // Wait for download to complete
            yield return www;
     
            // 读取AssetBundle
            AssetBundle bundle = www.assetBundle;
      //加载
            Object obj1 = bundle.LoadAsset("GameObject");
     
            // 释放bundle的缓存
            bundle.Unload(false);
     
            // 停止下载,释放缓存
            www.Dispose();
        }
     
    www是一个简单的访问网页的类.通过连接WWW(url)在后台开始下载,并且返回一个新的WWW对象。你可以检查isDone属性来查看是否已经下载完成,或者yield自动等待下载物体,直到它被下载完成(不会影响游戏的其余部分)。
     
    在Momo的博客上,建议不要再用WWW.LoadFromCacheOrDownload.因为有更好的方法.完美转发MOMO原文.链接在最后

    因为是异步方法,而且还占用内存。

    强烈建议使用AssetBundle.CreatFromFile 它是一个同步方法。现在IOS 和 android 都支持了,强烈建议用。

    打包的时候需要选择不压缩。

    因为不压缩, 所以就需要我们自己来压缩资源了, 可以用LZMA 和 GZIP来进行压缩。

    1.打包出来的Assetbundle我们自己用LZMA压缩,上传到服务器上。

    2.IOS或者Android下载这些assetbundle

    3.解压缩这些assetbundle并且保存在Application.persistentDataPath 目录下。

    4.以后通过AssetBundle.CreatFromFile  读取assetbundle。

    关于这些方法对内存的影响及清除缓存的方法:http://www.manew.com/home.php?mod=spacecp&ac=blog&blogid=3285&op=edit

     
    参考博客MOMO:http://www.xuanyusong.com/archives/2405/
  • 相关阅读:
    学习过程之python跳一跳
    OSError: [WinError -2147221003] 找不到应用程序: 'QR.png' 的解决方法
    易知大学 任务25 第一次爬虫与测试
    linux常用命令
    健身日志
    JavaScript JSON
    常用注解 开发SpringBoot项目
    网络基础
    jQuery MINI UI 学习之分页查询
    Springboot集成ActivitiModel提示输入密码
  • 原文地址:https://www.cnblogs.com/backlighting/p/5061559.html
Copyright © 2020-2023  润新知