Unity5.4 Assetbundles官方说明十(官方疑难问题解答)

转载请注明出处!

一、如何使用资源包(AssetBundle)?
  使用AssetBundle主要有两大步:第一步是从服务器上或磁盘路径下载AssetBundle,这是用WWW类完成操作;第二步是从资源包(AssetBundle)中加载程序要使用的资源(Assets)。下面是官方的C#脚本案例,创建一个GameObject:

using UnityEngine;
using System.Collections;

public class BundleLoader : MonoBehaviour
{
public string url; //路径
public int version; //版本号
public IEnumerator LoadBundle()
{
while (!Caching.ready)
yield return null;
using (WWW www = WWW.LoadFromCacheOrDownload(url, version))
{
yield return www;

if (www.error != null)
throw new Exception("WWW download had an error:" + www.error);


AssetBundle assetBundle = www.assetBundle;
GameObject gameObject = assetBundle.mainAsset as GameObject; //获取主资源对象

if(gameObject != null)

Instantiate(gameObject);
assetBundle.Unload(false);//释放没用的资源
}
}
void Start()
{
StartCoroutine(LoadBundle()); //使用协程来下载和加载资源
}
}


二、在编辑器(Editor)中如何使用资源包( AssetBundle )?
  因为创建应用程序是一个迭代的过程,那么通常情况会多次修改资源内容,这就导致我们修改资源后需要重新打包,并且测试它们是否可行。虽然可以在编辑器(Editor)中加载资源包(AssetBundle),但这是不提倡的,相反,在编辑器中测试时我们可以使用 辅助函数 AssetDatabase.LoadAssetAtPath来避免必须使用和修改资源。这个函数会让我们读取正在从资源包(AssetBundle)中加载的资源(Assets),但是会跳过资源的创建过程,而且我们的资源总是最新的。
  下面是官方的一个辅助函数的脚本,我们可以取决于是否在编辑器中运行来加载资源。

using UnityEngine;
using System.Collections;
using UnityEditor;

public class AssetBundleLoader
{
public Object Obj; //从AssetBundle中检索的对象
//协程
public IEnumerator LoadBundle<T>(string url, int version, string assetName, string assetPath) where T : Object
{
Obj = null;

#if UNITY_EDITOR

//在编辑器中获取对象的方法
Obj = AssetDatabase.LoadAssetAtPath(assetPath, typeof(T));
if (Obj == null)
Debug.LogError("Asset not found at path: " + assetPath);
yield break;

#else
//其他平台则进行正常的下载和加载
WWW download;
if ( Caching.enabled ) {
while (!Caching.ready)
yield return null;
download = WWW.LoadFromCacheOrDownload( url, version );
}
else {
download = new WWW (url);
}

yield return download;
if ( download.error != null ) {
Debug.LogError( download.error );
download.Dispose();
yield break;
}

AssetBundle assetBundle = download.assetBundle;
download.Dispose();
download = null;

if (assetName == "" || assetName == null)
Obj = assetBundle.mainAsset;
else
Obj = assetBundle.Load(assetName, typeof(T));

assetBundle.Unload(false);

#endif
}
}


   使用 上面的脚本, 如果运行打包出来的程序,我们可以从下载的资源包(AssetBundle)中获取资源对象;如果在编辑器中运行程序,我们就可以直接从项目工程文件夹中加载资源。代码示例如下:

using UnityEngine;
using System.Collections;

public class ExampleLoadingBundle : MonoBehaviour
{
public string url = "http://www.mygame.com/myBundle.unity3d"; // 下载的URL
public int version = 1; //AssetBundle的版本号

public string assetName = "MyPrefab"; // 要从资源包中加载的资源名
public string assetPath; // 工程项目中资源的所在路径

private Object ObjInstance; //要创建的对象实例
void Start()
{
StartCoroutine(Download());
}

IEnumerator Download()
{
AssetBundleLoader assetBundleLoader = new AssetBundleLoader();
yield return StartCoroutine(assetBundleLoader.LoadBundle<GameObject>(url, version, assetName, assetPath));
if (assetBundleLoader.Obj != null)
ObjInstance = Instantiate(assetBundleLoader.Obj);
}

void OnGUI()
{

//通过GUI来显示对象信息
GUILayout.Label(ObjInstance ? ObjInstance.name + " instantiated" : "");
}
}



三、怎样缓存资源包(AssetBundles)
  我们可以使用WWW.LoadFromCacheOrDownload来下载并自动保存缓存资源到磁盘中,但是PC/MAC以及IOS/Android应用程序都有4GB大小的限制,因此如果我们需要更多的空间,可以在官网购买一个单独的缓存许可证。(个人觉得无需购买,除非做的游戏非常大 Unity5.4 Assetbundles官方说明九(疑难问题解答) - IQ007伟哥 - IQ007伟哥的博客
  如果资源包没有压缩,并存储在StreamingAssets文件夹中,我们就可以使用AssetBundle.LoadFromFile函数来引用磁盘上的资源包。如果存储在StreamingAssets文件夹中保存的资源包被压缩了,我们需要使用WWW.LoadFromCacheOrDownload方法在缓存中复制一份未压缩的资源包。

四、资源包(AssetBundles)跨平台吗
AssetBundle在一些平台上是兼容的,下面是官方给的一个参考表:
  Standalone IOS Android
 EditorY* Y* 
 Standalone  
 IOS  
 Android   Y

  (*)移动平台的AssetBundle所包含的数据,是用优化的、平台特定的格式存储的,这跟编辑器(Editor)运行的平台是不兼容的。如果发布游戏时,每一个平台需要不同的资源包,请注意这些资源是有保护性的。尤其是不同平台间的着色器(Shader)是不同的。
  例如:GI数据是以ARM架构优化的格式存储的,因此它在X86的COU上是不加载的;着色器(Shaders)数据是以OpenGLES2的配置存储的,因此使用DX9/11渲染器的编辑器不能加载它(但是能在OpenGLCore渲染器上运行 )。在开发过程中,推荐我们在 资源包(AssetBundle)和资源包管理器(AssetBundle Manager) 中使用模拟的方式( Simulation Mode )来辅助避免编辑器和移动平台间的不兼容。

五、如何确定资源包(AssetBundle)中的资源(Asset)
  当我们打包资源包后,内部资源是通过不带扩展名的文件名来确定的。例如,一个纹理在项目工程中的目录是“ Assets/Textures/myTexture.jpg ”,需要使用“ myTexture ”的名称从资源包中加载。

六、可以在另一个游戏中重新使用资源包(AssetBundle)吗
  资源包允许我们在不同的游戏中公用资源,要求是对象引用的资源也必须包含在资源包中。在Unity5以后的版本中,都是可以公用资源包的。

七、现在打包的资源包(AssetBundle)在 Unity 今后的版本中可以使用吗
  Unity的所有机制基本都是向前兼容的,资源包也一样。资源包打包后包含一个类型树的结构,这就允许资源类型的信息可以被不同版本的Unity解析。在PC平台上类型树是默认包含的,但是在打包时可以通过 BuildAssetBundleOptions.DisableWriteTypeTree选项禁用。类型树不会包含在移动和控制台资源包中,所以每当序列化格式更改时,我们就需要重新打包。

八、如何将资源包(AssetBundle)的资源对象列出来
  我们可以使用 AssetBundle.LoadAllAssets函数来获取资源包中所有对象的数组,它不能直接返回唯一标识符的列表。我们通常的解决方法是,用一个文本资源(TextAsset)保存资源包(AssetBundle)中 不同资源的名称,然后通过这个文本资源中的内容来加载资源。

九、一个资源包(AssetBundle)如何引用其他资源包的资源
  假设资源包A包含一个预设Prefab,而Prefab使用了一个材质球Mat和一张纹理Tex;资源包B包含了一个场景Scene,这个场景中有Prefab的实例化对象,B需要访问材质Mat,除非Mat被包含在了一个特定的资源包中,否则Mat将会被同时打包仅A和B。Tex也一样。 扩展: 如果单个AssetBundle过大,只要这个AssetBundle中有一个资源改变了就需要重新下载整个AssetBundle,浪费流量和玩家的等待时间;如果单个AssetBundle过小,极端情况是每个资源一个AssetBundle,虽然实现了更新最小化,但是带来了额外开销:AssetBundle本身也是有大小的,而且查找加载AssetBundle也是需要时间的。大家都往U盘里面拷过东西,拷一个1G的文件比拷1千个1M的文件要快很多。比较合理的做法是根据逻辑来,例如每个角色可以有独立的AssetBundle,公用的一些UI资源可以打到一个AssetBundle里面,每个场景独立的UI资源可以打成独立的AssetBundle。这样做资源预加载的时候也方便,每个场景需要用到几个Bundle就加载几个Bundle,无关的资源不会被加载。

  小弟基本把官方的教程全部分享出来了,可能存在好多不足之处,希望大家能帮忙指出,我会尽快改正。小弟也是刚学习打包AssetBundle不久,爬过了许多坑,个人感觉官方的教程也有好多没有提及的坑,估计好多初学者也会钻入坑中翻来覆去。下一篇博文中将把我遇到的坑和解决方法总结一下分享给大家,并 给出完整的项目源码(包括资源的打包、下载资源包、加载资源包、获取资源几依赖资源、使用资源等)。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值