赞
踩
转载:Unity AssetBundle 从入门到掌握(适合初学者)
Unity3d的AssetBundle打包——AssetBundle Browser(简单实现资源复用)
官网给出的解释:
1、AssetBundle 是一个存档文件,包含可在运行时由 Unity 加载的特定于平台的非代码资源(比如模型、纹理、预制件、音频剪辑甚至整个场景)。
2、AssetBundle 可以表示彼此之间的依赖关系。例如,一个 AssetBundle 中的材质可以引用另一个 AssetBundle 中的纹理。为了提高通过网络传输的效率,可以根据用例要求(LZMA 和 LZ4)选用内置算法选择来压缩 AssetBundle。
3、AssetBundle 可用于可下载内容(DLC),减小初始安装大小,加载针对最终用户平台优化的资源,以及减轻运行时内存压力。
通俗的讲,就是把资源压缩起来,在游戏运行的过程中动态的加载、下载以及卸载掉资源,这样也缩小了安装包的大小,减轻了内存的压力。
“AssetBundle”可以指两种不同但相关的东西。
1、首先是磁盘上的实际文件。这称为 AssetBundle 存档。AssetBundle 存档是一个容器,就像文件夹一样,可以在其中包含其他文件。这些附加的文件包含两种类型:
(1)一个序列化文件(Serialized File ):其中包含分解为各个对象并写入此单个文件的资源。
(2)资源文件(Resource Files):这是为某些资源(纹理和音频)单独存储的二进制数据块,允许 Unity 高效地在另一个线程上从磁盘加载它们。
2、“AssetBundle”也可以指代通过代码进行交互以便从特定 AssetBundle 存档加载资源的实际 AssetBundle 对象。该对象包含您添加到此存档文件的资源的所有文件路径的映射。
也就是说,我们可以用代码从一个特定的压缩包中加载出一个对象,这个对象包含我们一开始添加到该压缩包中的所有内容。
1、我们先新建一个Cube,给它挂载一个检测脚本,把它拖到Project资源列表下形成预制体(如下图)。
/
2、在该预制体面板下,可以看到有AssetBundle的标签,单击会看到相应的标签,没有的话我们可以点击“New”新建一个。Remove UnUsed name 是移除没有使用的属性名。
标签名的命名规则:全为小写字母,加不加后缀都可;
有三种写法:
(1)cube
(2)cube.unity3d
(3)cube.assetbundle
3、测试的代码Cube如下:
- using UnityEngine;
-
- public class Cube : MonoBehaviour {
-
- private bool mouseIn;
- private GUIStyle style = new GUIStyle();
- private void OnMouseEnter()
- {
- mouseIn = true;
- }
- private void OnMouseExit()
- {
- mouseIn = false;
- }
- private void OnGUI()
- {
- if (mouseIn)
- {
- style.fontSize = 30;
- style.normal.textColor = Color.red;
- style.alignment = TextAnchor.MiddleCenter;
- GUI.Label(new Rect(Camera.main.WorldToScreenPoint(transform.position).x, Camera.main.WorldToScreenPoint(transform.position).y + 50, 100, 50), "This is a Cube!", style);
- }
- }
- }
接下来,试着将上面的Cube预制体打包。打包的代码如下:(该脚本要放在Project下的Editor文件夹中)
- #if UNITY_EDITOR
- using UnityEditor;
- #endif
- using UnityEngine;
-
- public class BuildEditor : MonoBehaviour
- {
- /// <summary>
- /// 编辑器扩展,该脚本需要放到Editor文件夹下
- /// 需要注意的:放在Editor文件夹下的脚本在打包时不会被发布出去(也就是不会被打包出去)
- /// </summary>
- [MenuItem("Bulid/Bulid AssetBundles")]
- //unity的编辑器扩展,使用的时候需要引入命名空间using UnityEditor
- //当点击Bulid AssetBundles的时候,会执行下面的方法
- static void BulidAllAssetBundles()
- {
- //打包AssetBundles的方法
- //unity5里面的BuildPipeline方法
- //测试本地加载 方法 StreamingAssets的路径下
- //宏定义 选择发布平台:这样写可以在发布不同平台的时候不需要修改代码
- #if UNITY_ANDROID//安卓平台
- BuildPipeline.BuildAssetBundles(Application.streamingAssetsPath,
- BuildAssetBundleOptions.UncompressedAssetBundle,
- BuildTarget.Android);
- #elif UNITY_IPHONE//iOS平台
- BuildPipeline.BuildAssetBundles(Application.streamingAssetsPath,
- BuildAssetBundleOptions.UncompressedAssetBundle,
- BuildTarget.IOS);
- #elif UNITY_STANDALONE_WIN || UNITY_EDITOR
- BuildPipeline.BuildAssetBundles(
- Application.streamingAssetsPath,//打包后文件的存放路径
- BuildAssetBundleOptions.UncompressedAssetBundle,//是否压缩
- BuildTarget.StandaloneWindows);//标准window平台,AssetBundles资源在不同平台下不共享
- #endif
- }
- }
完成后,Unity的导航栏会出现AssetBundleTools。
先建一个StreamingAssets文件夹,再点击Bulid AssetBundles,就可以打包了。打包完后,有如下文件(后面再打包,不会再生成后面两个StreamingAssets文件):
并且可以把Cube跟预制体Cube删掉,不过要记得标签名跟预制体名,后面加载的时候需要用到。
AssetBundle加载方式:
- AssetBundle.LoadFromFile 从本地加载
- AssetBundle.LoadFromMemory 从内存加载
- WWW.LoadFromCacheOrDownload 下载后放在缓存中备用(该方法逐渐被弃用)
- UnityWebRequest 从服务器下载
从AssetBundle中加载资源:
- AssetBundle.LoadAsset(assetName)
- AssetBundle.LoadAllAssets() 加载AB包中所有的对象,不包含依赖的包
- AssetBundle.LoadAssetAsync() 异步加载,加载较大资源的时候
- AssetBundle.LoadAllAssetsAsync() 异步加载全部资源
- AssetBundle.LoadAssetWithSubAssets 加载资源及其子资源
以下这张表是当使用不同的压缩方式和不同的加载方法时,内存和性能的开销情况比较:
打包完,我们试着加载一下刚打包过的资源。
新建一个C#脚本,命名为Load,进行代码的编写,编写完,把它挂在场景的一个物体上,填好对应的名称即可。
- using System.Collections;
- using UnityEngine;
-
- public class Load : MonoBehaviour {
-
- //这个路径是打包的路径,(简单的说就是你的AssetBundle包的路径)
- private string pathUrl;
- [Header("标签名:")]
- public string assetBundle;
- [Header("预制体名:")]
- public string prefabName;
- private void Start()
- {
- //pathUrl = “file://” + Application.dataPath + “/StreamingAssets/”;
- pathUrl =
-
- #if UNITY_ANDROID
- "jar:file://"+Application.dataPath+"!/assets/";
- #elif UNITY_IPHONE
- Application.dataPath+"/Raw/";
- #elif UNITY_STANDALONE_WIN||UNITY_EDITOR
- "file://" + Application.dataPath + "/StreamingAssets/";
- #endif
- }
- void OnGUI()
- {
- if (GUI.Button(new Rect (100,100,100,50), "LoadAsset"))
- {
- StartCoroutine(LoadAsset());
- }
- }
- /// <summary>
- /// 加载assetBundle文件
- /// </summary>
- /// <returns></returns>
- private IEnumerator LoadAsset()
- {
- string mUrl = pathUrl + assetBundle;
- Debug.Log(mUrl);
- WWW www = new WWW(mUrl);
- Debug.Log(www.url);
- //等待www加载完成
- yield return www;
- if (!string.IsNullOrEmpty(www.error))
- {
- Debug.LogError(www.error);
- }
- else
- {
- //加载资源
- Object obj = www.assetBundle.LoadAsset(prefabName);
- //返回实例化对象
- yield return Instantiate(obj);
- //false:卸载用过的,true卸载全部
- www.assetBundle.Unload(false);
- }
- //非托管资源:GC处理不了的,一些流文件都会继承IDisposable接口
- www.Dispose();//释放资源
- }
- }
-
最终效果:
- 减少内存的使用
- 有可能导致丢失
- 在切换场景,或者确定不使用的时候卸载
AssetBundle.Unload(true) //卸载AssetBundle文件的内存镜像,且包含所有Load创建出来的对象
AssetBundle.Unload(false) //卸载AssetBundle文件的内存镜像,但是除了Load创建出来的对象
Reources.UnloadAsset(Object) //释放已加载的资源Object
Resources.UnloadUnusedAssets //卸载所有没有被场景引用的资源对象
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。