assetbundle打包脚本在Windows平台上打包无限失败.紧急求助

方法将场景打包为AssetBundle
时间: 6:33:45
Unity3D游戏开发之使用AssetBundle和Xml实现场景的动态加载各位朋友,大家好,我是秦元培,欢迎大家关注我的博客,我的博客地址是/。 &&&&引言&&&&今天我想和大家聊聊在Unity3D中关于场景的动态加载的问题。众所周知在Unity3D游戏开发过程中,因为受到游戏容量、平台性能和热更新等诸多因素的限制,我们可能无法将所有的游戏场景打包到项目中然后相对”静态”地加载,那么这个时候就需要我们使用动态加载的方式来将游戏场景加载到场景中。博主在研究了Unity3D动态加载的相关资料后发现,目前Unity3D中实现动态加载场景的方式主要有以下两种方式: &&&&* 使用BuildStreamedSceneAssetBundle()方法将场景打包为AssetBundle:这种方法将生成一个流式的.unity3d文件,从而实现按需下载和加载,因此这种方式特别适合Web环境下游戏场景的加载,因为在Web环境下我们可以希望的是玩家可以在玩游戏的同时加载游戏。可是因为这种打包方式仅仅是保证了场景中的GameObject与本地资源的引用关系而非是将本地资源打包,因此从减少游戏容量的角度来说并不是十分实用,而且当我们使用WWW下载完AssetBundle后,需要使用Application.Load()方法来加载场景,我们知道在Unity3D中加载一个关卡(场景)是需要在BuildSetting中注册关卡的,因此在使用这种方式动态加载的时候请注意到这一点。 &&&&* 将场景内的所有物体打包为AssetBundle配合相关配置文件动态生成场景:这种方法的思路是使用一个配置文件来记录下当前场景中所有物体的位置、旋转和缩放信息,然后再根据配置文件使用Instantiate方法逐个生成即可。这种思路是考虑到需要在一个场景中动态替换GameObject或者是动态生成GameObject的情形,使用这种方法首先要满足一个条件,即:场景内所有的物体都是预制件(Prefab)。这是由Unity3D的机制决定的,因为Prefab是一个模板,当你需要动态生成一个物体的时候就需要为其提供一个模板(Prefab)。&&&&如果你对这两种方式没有什么疑问的话,那么我觉得我们可以正式开始今天的内容了。既然今天的题目已然告诉大家是使用AssetBundle和Xml文件实现场景的动态加载,我相信大家已经明白我要使用那种方式了。好了,下面我们正式开始吧!&&&&准备工作&&&&在实现场景的动态加载前,我们首先要在本地准备好一个游戏场景,然后做两件事情: &&&&* 将场景内的所有GameObject打包为AssetBundle &&&&* 将场景内所有的GameObject的信息导出为Xml文件 &&&&做这两件事情的时候,相当于我们是在准备食材和菜谱,有了食材和菜谱我们就可以烹制出美味佳肴了。可是在做着两件事情前,我们还有一件更为重要的事情要做,那就是我们需要将场景中使用到的GameObject制作成预制体(Prefab)。因为在博主的印象中,Unity3D打包的最小粒度应该是Prefab,所以为了保险起见,我还是建议大家将场景中使用到的GameObject制作成预制体(Prefab)。那么问题来了,当我们将这些Prefab打包成AssetBundle后是否还需要本地的Prefab文件?这里博主一直迷惑,因为理论上当我们将这些Prefab打包成AssetBundle后,我们实例化一个物体的时候实际上是在使用AssetBundle的Load方法来获取该物体的一个模板,这个模板应该是存储在AssetBundle中的啊!因为我的笔记本使用的是免费版的Unity3D无法对此进行测试,所以如果想知道这个问题结果的朋友可以等我下周到公司以后测试了再做讨论(我不会告诉你公司无耻地使用了破解版),当然如果有知道这个问题的答案的朋友欢迎给我留言啊,哈哈!这里就是想告诉大家要准备好场景中物体的预设体(Prefab),重要的事情说三遍!!!&&&&将场景内物体打包为AssetBundle&&&&Unity3D打包的相关内容这里就不展开说了,因为在官方API文档中都能找到详细的说明,虽然说Unity5.0中AssetBundle打包的方式发生了变化,不过考虑到大家都还在使用4.X的版本,所以等以后我用上了Unity5.0再说吧,哈哈!好了,下面直接给出代码:&&&&
[MenuItem("Export/ExportTotal----对物体整体打包")]&&&&
static void ExportAll()&&&&
string savePath=EditorUtility.SaveFilePanel("输出为AssetBundle","","New Resource","unity3d");&&&&
if(string.IsNullOrEmpty(savePath)) return;&&&&
Object[] objs=Selection.GetFiltered(typeof(Object),SelectionMode.DeepAssets);&&&&
if(objs.Length&0) return;&&&&
BuildPipeline.BuildAssetBundle(null,objs,savePath,BuildAssetBundleOptions.pleteAssets);&&&&
AssetDatabase.Refresh();&&&&
}&&&&将场景内物体信息导出为Xml文件&&&&导出场景内物体信息需要遍历场景中的每个游戏物体,因为我们在制作场景的时候通常会用一个空的GameObject作为父物体来组织场景中的各种物体,因此我们在导出Xml文件的时候仅仅考虑导出这些父物体,因为如果考虑子物体的话,可能会涉及到递归,整个问题将变得特别复杂。为了简化问题,我们这里仅仅考虑场景中的父物体。好了,开始写代码:&&&&
[MenuItem("Export/ExportScene----将当前场景导出为Xml")]&&&&
static void ExportGameObjects()&&&&
//获取当前场景完整路径&&&&
string scenePath=EditorApplication.currentScene&&&&
//获取当前场景名称&&&&
string sceneName=scenePath.Substring(scenePath.LastIndexOf("/")+1,scenePath.Length-scenePath.LastIndexOf("/")-1)&&&&
sceneName=sceneName.Substring(0,sceneName.LastIndexOf("."))&&&&
//获取保存路径&&&&
string savePath=EditorUtility.SaveFilePanel("输出场景内物体","",sceneName,"xml")&&&&
//创建Xml文件&&&&
XmlDocument xmlDoc=new XmlDocument()&&&&
//创建根节点&&&&
XmlElement scene=xmlDoc.CreateElement("Scene")&&&&
scene.SetAttribute("Name",sceneName)&&&&
scene.SetAttribute("Asset",scenePath)&&&&
xmlDoc.AppendChild(scene)&&&&
//遍历场景中的所有物体&&&&
foreach(GameObject go in Object.FindObjectsOfType(typeof(GameObject)))&&&&
//仅导出场景中的父物体&&&&
if(go.transform.parent==null)&&&&
//创建每个物体&&&&
XmlElement gameObject=xmlDoc.CreateElement("GameObject")&&&&
gameObject.SetAttribute("Name",go.name)&&&&
gameObject.SetAttribute("Asset","Prefabs/"+ go.name + ".prefab")&&&&
//创建Transform&&&&
XmlElement transform=xmlDoc.CreateElement("Transform")&&&&
transform.SetAttribute("x",go.transform.position.x.ToString())&&&&
transform.SetAttribute("y",go.transform.position.y.ToString())&&&&
transform.SetAttribute("z",go.transform.position.z.ToString())&&&&
gameObject.AppendChild(transform)&&&&
//创建Rotation&&&&
XmlElement rotation=xmlDoc.CreateElement("Rotation")&&&&
rotation.SetAttribute("x",go.transform.eulerAngles.x.ToString())&&&&
rotation.SetAttribute("y",go.transform.eulerAngles.y.ToString())&&&&
rotation.SetAttribute("z",go.transform.eulerAngles.z.ToString())&&&&
gameObject.AppendChild(rotation)&&&&
//创建Scale&&&&
XmlElement scale=xmlDoc.CreateElement("Scale")&&&&
scale.SetAttribute("x",go.transform.localScale.x.ToString())&&&&
scale.SetAttribute("y",go.transform.localScale.y.ToString())&&&&
scale.SetAttribute("z",go.transform.localScale.z.ToString())&&&&
gameObject.AppendChild(scale)&&&&
//添加物体到根节点&&&&
scene.AppendChild(gameObject)&&&&
xmlDoc.Save(savePath)&&&&
}&&&&&&&&好了,在这段代码中我们以Scene作为根节点,然后以每个GameObject作为Scene的子节点,重点在Xml文件中记录了每个GameObject的名称、Prefab、坐标、旋转和缩放等信息。下面是一个导出场景的Xml文件的部分内容:&&&& Name="DoneStealth" Asset="Assets/Done/DoneScenes/DoneStealth.unity"&&&&&
Name="char_robotGuard_002" Asset="Prefabs/char_robotGuard_002.prefab"&&&&&
x="-18.99746" y="0" z="37.2443" /&&&&&
x="0" y="0" z="0" /&&&&&
x="1" y="1" z="1" /&&&&&
Name="fx_laserFence_lasers_003" Asset="Prefabs/fx_laserFence_lasers_003.prefab"&&&&&
x="-17.90294" y="1.213998" z="24.07678" /&&&&&
x="0" y="90.00001" z="0" /&&&&&
x="1" y="1" z="3.735847" /&&&&&
Name="door_generic_slide_001" Asset="Prefabs/door_generic_slide_001.prefab"&&&&&
x="-15.91264" y="-0." z="7.006886" /&&&&&
x="0" y="90.00001" z="0" /&&&&&
x="1" y="1" z="1" /&&&&&
Name="door_generic_slide_003" Asset="Prefabs/door_generic_slide_003.prefab"&&&&&
x="-7.910765" y="-0." z="37.01304" /&&&&&
x="0" y="90.00001" z="0" /&&&&&
x="1" y="1" z="1" /&&&&&
&&&&&在这里我们假设所有的Prefab是放置在Resources/Prefabs目录中的,那么此时我们便有了两种动态加载场景的方式 &&&&* 通过每个GameObject的Asset属性,配合Resources.Load()方法实现动态加载 &&&&* 通过每个GameObject的Name属性,配合AssetBundle的Load()方法实现动态加载 &&&&这两种方法大同小异,区别仅仅在于是否需要从服务器下载相关资源。因此本文的主题是使用AssetBundle和Xml实现场景的动态加载,因此,接下来我们主要以第二种方式为主,第一种方式请大家自行实现吧!&&&&动态加载物体到场景中&&&&首先我们来定义一个根据配置文件动态加载AssetBundle中场景的方法LoadDynamicScene&&&&
根据配置文件动态加载AssetBundle中的场景&&&&
从服务器上下载的AssetBundle文件&&&&
AssetBundle文件对应的场景配置文件&&&&
public static void LoadDynamicScene(AssetBundle bundle,string xmlFile)&&&&
XmlDocument xmlDoc=new XmlDocument();&&&&
xmlDoc.LoadXml(((TextAsset)Resources.Load(xmlFile)).text);&&&&
XmlElement root=xmlDoc.DocumentE&&&&
if(root.Name=="Scene")&&&&
XmlNodeList nodes=root.SelectNodes("/Scene/GameObject");&&&&
Vector3 position=Vector3.&&&&
Vector3 rotation=Vector3.&&&&
Vector3 scale=Vector3.&&&&
foreach(XmlElement xe1 in nodes)&&&&
foreach(XmlElement xe2 in xe1.ChildNodes)&&&&
if(xe2.Name=="Transform")&&&&
position=new Vector3(float.Parse(xe2.GetAttribute("x")),float.Parse(xe2.GetAttribute("y")),float.Parse(xe2.GetAttribute("z")));&&&&
}else if(xe2.Name=="Rotation")&&&&
rotation=new Vector3(float.Parse(xe2.GetAttribute("x")),float.Parse(xe2.GetAttribute("y")),float.Parse(xe2.GetAttribute("z")));&&&&
}else{&&&&
scale=new Vector3(float.Parse(xe2.GetAttribute("x")),float.Parse(xe2.GetAttribute("y")),float.Parse(xe2.GetAttribute("z")));&&&&
GameObject go=(GameObject)GameObject.Instantiate(bundle.Load(xe1.GetAttribute("Name")),position,Quaternion.Euler(rotation));&&&&
go.transform.localScale=&&&&
}&&&&因为该方法中的AssetBundle是需要从服务器下载下来的,因此我们需要使用协程来下载AssetBundle:&&&&
IEnumerator Download()&&&&
WWW _www = new WWW ("http://localhost/DoneStealth.unity3d");&&&&
yield return _&&&&
if (string.IsNullOrEmpty (_www.error)) &&&&
if(_www.assetBundle!=null)&&&&
LoadDynamicScene(_www.assetBundle,"DoneStealth.xml");&&&&
}&&&&好了,现在运行程序,可以发现场景将被动态地加载到当前场景中:),哈哈&&&&&&&&小结&&&&&&&&使用这种方式来加载场景主要是为了提高游戏的性能,如果存在大量重复性的场景的时候,可以使用这种方式来减小游戏的体积,可是这种方式本质上是一种用时间换效率的方式,因为在使用这种方法前,我们首先要做好游戏场景,然后再导出相关的配置文件和AssetBundle,从根本上来讲,工作量其实没有减少。&&&&当场景导出的Xml文件中的内容较多时,建议使用内存池来管理物体的生成和销毁,因为频繁的生成和销毁是会带来较大的内存消耗的。说到这里的时候,我不得不吐槽下公司最近的项目,在将近300个场景中只有30个场景是最终发布游戏时需要打包的场景,然后剩余场景将被用来动态地加载到场景中,因为领导希望可以实现动态改变场景的目的,更为郁闷的是整个场景要高度DIY,模型要能够随用户拖拽移动、旋转,模型和材质要能够让用户自由替换。从整体上来讲,频繁地销毁和生成物体会耗费大量资源,因此如果遇到这种情况建议还是使用内存池进行管理吧!&&&&&&&&好了,今天的内容就是这样子了,如果大家对此有什么疑问,欢迎给我留言,谢谢大家!&&&&关于AssetBundle的整体流程
关于AssetBundle的整体流程,有需要的朋友可以参考下。第一步:制作打包工具具体可参照宣雨松的这篇文章/archives/2373/第二步:AssetBundle的加载方式可以参考/archives/2405/第三步:这里是我需要做的补充:1.AssetBundle的加载方式推荐使用AssetBundle bundle = AssetBundle.CreateFromFile(path);而非WWW的原因是前者是同步的,而后者是异步的;2.在加载一个AssetBUndle后记得要释放掉,否则再次加载时会报错,释放方法bundle.Unload(false);3.对于不同平台AssetBundle的加载方式是不同的,在编辑器环境下,可以直接将AssetBundle文件放到StreamingAsset文件夹下,因为电脑对这个文件可以使用增删读写等操作,但是在移动端却不行,只能先使用WWW加载,然后写到沙盒路径下才能做读写操作。在安卓环境下,AssetBundle可以事先放到服务器,然后下载下来直接将文件写到沙盒路径下,这样可以直接使用AssetBundle.CreateFromFile(path)来加载,注意在移动端使用AssetBundle.CreateFromFile无法直接读取StreamingAsset文件夹下的文件第四步:AssetBundle的打包模式有依赖打包,这个网上有很多资料 我就不在这里阐述了
最新教程周点击榜
微信扫一扫今天在群里问朋友有没有 同步加载 Assetbundle 的方法,同事给我指点 Unity3d 不知道在哪一个版本新增了一个 AssetBundle.CreateFromFile 的接口,这个接口是同步读取Assetbundle的。于是到帮助文档查询相关资料。
/ScriptReference/AssetBundle.CreateFromFile.html 文章转自http://blog.csdn.net/huutu 星环游戏 .cn
AssetBundle.CreateFromFile
public static AssetBundle CreateFromFile(string path);
Parameters
path Path of the file on disk
See Also: WWW.assetBundle, WWW.LoadFromCacheOrDownload.
Description
Loads an asset bundle from a disk.
Only uncompressed asset bundles are supported by this function. This is the fastest way to load an asset bundle.
文章转自http://blog.csdn.net/huutu 星环游戏 .cn
与之前使用WWW方式相比,使用 CreateFromFile读取 Assetbundle 方式有以下不同:
1、WWW是异步的, CreateFromFile 是同步的。
2、CreateFromFile接口读取的必须是没有压缩的Assetbundle文件。
来对比两种方式的打包与读取
文章转自http://blog.csdn.net/huutu 星环游戏 .cn
打包Assetbundle 压缩 与 不压缩
如果使用 CreateFromFile 这个API 来读取 Assetbundle ,那么打包 Assetbundle 的时候要注意打包成 非压缩的 ,也就是要加上 这个 设置。
BuildAssetBundleOptions.UncompressedAssetBundle
代码如下:
using UnityE
using System.C
using UnityE
using System.IO;
public class NewBehaviourScript : Editor {
[MenuItem (&cp/build Girl NoLZMA&)]
static void BuildGirlNoLZMA()
string targetdir = Application.dataPath + &/bundleNoLZMA&;
uint crc = 0;
//公共资源入栈;
BuildPipeline.PushAssetDependencies ();
string filePath = &Assets/res/01.png&;
Object obj = AssetDatabase.LoadMainAssetAtPath(filePath);
if (BuildPipeline.BuildAssetBundle(obj, null, targetdir+&/01.png.unity3d&, out crc,BuildAssetBundleOptions.UncompressedAssetBundle | BuildAssetBundleOptions.CollectDependencies | BuildAssetBundleOptions.DeterministicAssetBundle, BuildTarget.StandaloneWindows))
AssetDatabase.Refresh ();
filePath = &Assets/res/Aoki Shizuku.mp3&;
obj = AssetDatabase.LoadMainAssetAtPath(filePath);
if (BuildPipeline.BuildAssetBundle(obj, null, targetdir+&/Aoki Shizuku.mp3.unity3d&, out crc,BuildAssetBundleOptions.UncompressedAssetBundle | BuildAssetBundleOptions.CollectDependencies | BuildAssetBundleOptions.DeterministicAssetBundle, BuildTarget.StandaloneWindows))
AssetDatabase.Refresh ();
//普通资源入栈;
BuildPipeline.PushAssetDependencies ();
filePath = &Assets/Resources/Girl.prefab&;
obj = AssetDatabase.LoadMainAssetAtPath(filePath);
if (BuildPipeline.BuildAssetBundle(obj, null, targetdir+&/Girl.prefab.unity3d&, out crc,BuildAssetBundleOptions.UncompressedAssetBundle | BuildAssetBundleOptions.CollectDependencies | BuildAssetBundleOptions.DeterministicAssetBundle, BuildTarget.StandaloneWindows))
AssetDatabase.Refresh ();
BuildPipeline.PopAssetDependencies ();
BuildPipeline.PopAssetDependencies ();
[MenuItem (&cp/build Girl&)]
static void BuildGirl()
string targetdir = Application.dataPath + &/bundle&;
uint crc = 0;
//公共资源入栈;
BuildPipeline.PushAssetDependencies ();
string filePath = &Assets/res/01.png&;
Object obj = AssetDatabase.LoadMainAssetAtPath(filePath);
if (BuildPipeline.BuildAssetBundle(obj, null, targetdir+&/01.png.unity3d&, out crc, BuildAssetBundleOptions.CollectDependencies | BuildAssetBundleOptions.DeterministicAssetBundle, BuildTarget.StandaloneWindows))
AssetDatabase.Refresh ();
filePath = &Assets/res/Aoki Shizuku.mp3&;
obj = AssetDatabase.LoadMainAssetAtPath(filePath);
if (BuildPipeline.BuildAssetBundle(obj, null, targetdir+&/Aoki Shizuku.mp3.unity3d&, out crc, BuildAssetBundleOptions.CollectDependencies | BuildAssetBundleOptions.DeterministicAssetBundle, BuildTarget.StandaloneWindows))
AssetDatabase.Refresh ();
//普通资源入栈;
BuildPipeline.PushAssetDependencies ();
filePath = &Assets/Resources/Girl.prefab&;
obj = AssetDatabase.LoadMainAssetAtPath(filePath);
if (BuildPipeline.BuildAssetBundle(obj, null, targetdir+&/Girl.prefab.unity3d&, out crc, BuildAssetBundleOptions.CollectDependencies | BuildAssetBundleOptions.DeterministicAssetBundle, BuildTarget.StandaloneWindows))
AssetDatabase.Refresh ();
BuildPipeline.PopAssetDependencies ();
BuildPipeline.PopAssetDependencies ();
加上 不压缩 的设置后,打包 Assetbundle 速度明显变快。
对比两种方式打包出来的 Assetbundle 文件。& 文章转自http://blog.csdn.net/huutu 星环游戏 .cn
文章转自http://blog.csdn.net/huutu 星环游戏 .cn
WWW 与 CreateFromFile 方式读取 Assetbundle
CreateFromFile 是同步操作,WWW 是异步操作。
using UnityE
using System.C
public class NewBehaviourScript : MonoBehaviour {
// Use this for initialization
void Start () {
// Update is called once per frame
void Update () {
//Debug.Log (&Update&);
void OnGUI()
if(GUILayout.Button(&Load Girl&))
StartCoroutine(LoadDepends(&file://&+Application.dataPath+&/bundle/01.png.unity3d&));
StartCoroutine(LoadDepends(&file://&+Application.dataPath+&/bundle/Aoki Shizuku.mp3.unity3d&));
StartCoroutine(Load(&file://&+Application.dataPath+&/bundle/Girl.prefab.unity3d&));
if(GUILayout.Button(&Load Girl NOLZMA&))
AssetBundle assetbundle01=AssetBundle.CreateFromFile(Application.dataPath+&/bundleNoLZMA/01.png.unity3d&);
AssetBundle assetbundlemp3=AssetBundle.CreateFromFile(Application.dataPath+&/bundleNoLZMA/Aoki Shizuku.mp3.unity3d&);
AssetBundle assetbundle=AssetBundle.CreateFromFile(Application.dataPath+&/bundleNoLZMA/Girl.prefab.unity3d&);
Instantiate(assetbundle.mainAsset);
private IEnumerator LoadDepends(string path)
WWW www = new WWW (path);
Debug.Log(&LoadDepends 1&);
Debug.Log (&LoadDepends 2&);
Object obj= Instantiate (www.assetBundle.mainAsset);
Debug.Log(&LoadDepends 3&);
yield return new WaitForSeconds (3.0f);
private IEnumerator Load(string path)
yield return new WaitForSeconds (3f);
WWW www = new WWW (path);
Debug.Log(&Load 1&);
Debug.Log (&Load 2&);
Object obj= Instantiate (www.assetBundle.mainAsset);
Debug.Log(&Load 3&);
www.assetBundle.Unload (false);
Resources.UnloadUnusedAssets ();
文章转自http://blog.csdn.net/huutu 星环游戏 .cn
使用 不压缩 打包 Assetbundle 的方式,推荐大家使用 7Zip 的 LZMA 压缩算法进行整体压缩,在游戏开始时进行解压。
示例工程下载:
/s/1o63fOz4
文章转自http://blog.csdn.net/huutu 星环游戏 .cnUnity5.x版本AssetBundle加载研究 - Joe师傅
来源:互联网
编辑:刘梓楠
有网友碰到过这样的问题:Unity5.x版本AssetBundle加载研究 - Joe师傅,问题详细内容为:挺不错的博文:Unity5.x版本AssetBundle加载研究 - Joe师傅,我搜你通过互联网收集了相关的一些解决方案,希望对有过相同或者相似问题的网友提供帮助,具体如下:
之前说了 &Unity5.x版本AssetBundle打包研究&,没看过的请先看一下:/?p=57再来看本文,有一定的连接性。
先梳理一下思路:要加载一个资源A,必须先去加载它的所有依赖资源要知道这个资源A依赖了哪些资源,必须先去加载AssetBundleManifest通过AssetBundleManifest对象的GetAllDependencies(A)方法,获取它依赖的所有资源。依赖资源都加载了,就可以去真正加载资源A了。
注意点:1.资源A加载完了后,要记得Unload(false),资源A的依赖资源要在 资源A加载完成后,才能Unload(false),否则无法正常加载资源A2.不Unload的话也可以,那就自己做一个字典记录所有加载过的AssetBundle,还有它们的引用计数器。那样就可以先判断是否存在,然后再确定是否要去加载。
我下面的例子,采用1的方式。就是加载完了后就Unload的方式。上代码
using UnityE
using System.C
using System.Collections.G
public class AssetBundleLoaderMgr : Singleton&AssetBundleLoaderMgr&
public string m_assetPath = Application.streamingAssetsP
string assetTail = ".unity3d";
#region LoadAssetBundle
/// &summary&
/// 加载目标资源
/// &/summary&
/// &param name="name"&&/param&
/// &param name="callback"&&/param&
public void LoadAssetBundle(string name, Action&UnityEngine.Object& callback)
name = name + assetT//eg:ui/panel.unity3d
Action&List&AssetBundle&& action = (depenceAssetBundles) =&
string realName = this.GetRuntimePlatform() + "/" +//eg:Windows/ui/panel.unity3d
LoadResReturnWWW(realName, (www) =&
int index = realName.LastIndexOf("/");
string assetName = realName.Substring(index + 1);
assetName = assetName.Replace(assetTail, "");
AssetBundle assetBundle = www.assetB
UnityEngine.Object obj = assetBundle.LoadAsset(assetName);//LoadAsset(name),这个name没有后缀,eg:panel
//卸载资源内存
assetBundle.Unload(false);
for (int i = 0; i & depenceAssetBundles.C i++)
depenceAssetBundles[i].Unload(false);
//加载目标资源完成的回调
callback(obj);
LoadDependenceAssets(name, action);
/// &summary&
/// 加载目标资源的依赖资源
/// &/summary&
/// &param name="targetAssetName"&&/param&
/// &param name="action"&&/param&
private void LoadDependenceAssets(string targetAssetName, Action&List&AssetBundle&& action)
Debug.Log("要加载的目标资源:" + targetAssetName);//ui/panel.unity3d
Action&AssetBundleManifest& dependenceAction = (manifest) =&
List&AssetBundle& depenceAssetBundles = new List&AssetBundle&();//用来存放加载出来的依赖资源的AssetBundle
string[] dependences = manifest.GetAllDependencies(targetAssetName);
Debug.Log("依赖文件个数:" + dependences.Length);
int length = dependences.L
int finishedCount = 0;
if (length == 0)
//没有依赖
action(depenceAssetBundles);
//有依赖,加载所有依赖资源
for (int i = 0; i & i++)
string dependenceAssetName = dependences[i];
dependenceAssetName = GetRuntimePlatform() + "/" + dependenceAssetN//eg:Windows/altas/heroiconatlas.unity3d
//加载,加到assetpool
LoadResReturnWWW(dependenceAssetName, (www) =&
int index = dependenceAssetName.LastIndexOf("/");
string assetName = dependenceAssetName.Substring(index + 1);
assetName = assetName.Replace(assetTail, "");
AssetBundle assetBundle = www.assetB
UnityEngine.Object obj = assetBundle.LoadAsset(assetName);
//assetBundle.Unload(false);
depenceAssetBundles.Add(assetBundle);
finishedCount++;
if (finishedCount == length)
//依赖都加载完了
action(depenceAssetBundles);
LoadAssetBundleManifest(dependenceAction);
/// &summary&
/// 加载AssetBundleManifest
/// &/summary&
/// &param name="action"&&/param&
private void LoadAssetBundleManifest(Action&AssetBundleManifest& action)
string manifestName = this.GetRuntimePlatform();
manifestName = manifestName + "/" + manifestN//eg:Windows/Windows
LoadResReturnWWW(manifestName, (www) =&
AssetBundle assetBundle = www.assetB
UnityEngine.Object obj = assetBundle.LoadAsset("AssetBundleManifest");
assetBundle.Unload(false);
AssetBundleManifest manif = obj as AssetBundleM
action(manif);
#endregion
#region ExcuteLoader
public void LoadResReturnWWW(string name, Action&WWW& callback)
string path = "file://" + this.m_assetPath + "/" +
Debug.Log("加载:" + path);
StartCoroutine(LoaderRes(path, callback));
IEnumerator LoaderRes(string path, Action&WWW& callback)
WWW www = new WWW(path);
if (www.isDone)
callback(www);
#endregion
#region Util
/// &summary&
/// 平台对应文件夹
/// &/summary&
/// &returns&&/returns&
private string GetRuntimePlatform()
string platform = "";
if (Application.platform == RuntimePlatform.WindowsPlayer || Application.platform == RuntimePlatform.WindowsEditor)
platform = "Windows";
else if (Application.platform == RuntimePlatform.Android)
platform = "Android";
else if (Application.platform == RuntimePlatform.IPhonePlayer)
platform = "IOS";
else if (Application.platform == RuntimePlatform.OSXPlayer || Application.platform == RuntimePlatform.OSXEditor)
platform = "OSX";
#endregion
测试一下咯
using UnityE
using System.C
using System.Collections.G
public class TestAssetBundleLoader : MonoBehaviour
Dictionary&string, GameObject& GameObjectPool = new Dictionary&string, GameObject&();
void Start()
//要加载的资源的队列
Queue&string& needLoadQueue = new Queue&string&();
needLoadQueue.Enqueue("ui/plane");
needLoadQueue.Enqueue("ui/cube");
needLoadQueue.Enqueue("ui/sphere");
Load(needLoadQueue);
void Load(Queue&string& needLoadQueue)
if (needLoadQueue.Count & 0)
string needLoadAssetName = needLoadQueue.Dequeue();
AssetBundleLoaderMgr.Instance.LoadAssetBundle(needLoadAssetName, (obj) =&
GameObject go = GameObject.Instantiate(obj) as GameO
int index = needLoadAssetName.LastIndexOf("/");
string assetName = needLoadAssetName.Substring(index + 1);
//加载出来的GameObject放到GameObjectPool存储
GameObjectPool.Add(assetName, go);
Load(needLoadQueue);
Debug.Log("all finished");
有图有真相
可能代码写的还有很多优化的地方 ,毕竟100个人有100种写法,思路才是最重要的。你说呢?其实我想说的是,代码都在了,自己尝试一下吧!
posted @ 请注意,本站信息均收集自互联网,相关信息仅供参考,医疗等重要信息请以正规途径为最终意见,本站不承担任何责任!
您可能还关注

我要回帖

更多关于 assetbundle打包场景 的文章

 

随机推荐