unityunity3d assetbundlee更新的内容会存在本地吗

扫一扫,访问微社区
后使用快捷导航没有帐号?
签到成功!您今天第{todayrank}个签到,签到排名竞争激烈,记得每天都来签到哦!已连续签到:{constant}天,累计签到:{days}天
你在使用assetbundle时可能遇到的坑【原】
热度 144751
|个人分类:|
在公司项目开发中,用到了assetbundle,由于是webplayer不像手机,流量限制几乎没有,所以场景都是用assetbundle打包后动态加载的,但是这个过程中,遇到不少坑:
1.Editor版本不能读取与自己版本不同的assetbundle
这个描述起来很简单:比如:老板原来让你用4.1打包(BuildAssetBundle)开发,开发完毕后,下半年,unity升级了,于是老板要求与时俱进,让你用4.3开发维护,这时,问题就出现了:4.1下的editor打包的assetbundle在editor下不能被4.3读取,会报错。
那么解决方法是啥呢?把所有资源重新在4.3下打包。很坑吧?但是,这问题仅仅只是在editor下会出现,webplayer不会出现。但你恐怕很少说调试程序不走editor吧?
2.assetbundle如果从WWW中被读取过一次,再读取会报错
当你把assetbundle资源用www下载下来后,往往都会使用“wwwResource.assetbundle”,但是注意,这个函数调用assetbundle的时候,只能调用一遍。意思是,当你要再次读取的时候,会报错。这时候,需要你写一套对于assetbundle的控制程序,保证第一次读取资源的时候是使用wwwResource.assetbundle,第二次再次利用,则要用已经读取出来的资源。
3.慎用BuildPipeline的PushAssetDependencies()和PopAssetDependencies()功能
在我们的项目中,打包时,用到了BuildPipeline.PushAssetDependencies()和BuildPipeline.PopAssetDependencies()的功能,这是unity里比较好的一项功能,它可以把unity里的依赖关系比较好的保存下来,并正常读取就可以还原。比如:一个模型用到了贴图1,贴图2,贴图3,这时,我们可以用这种依赖关系的方式,把模型单独打出来,同时把贴图1贴图2贴图3也单独打包出来,这样的话,如果有别的模型也用到了贴图123,只需要下载一次,然后在读进工程的时候,贴图自动找到模型,并贴上去。听起来很美,但是也有问题:严格根据依赖关系按顺序下载资源。否则,留给你的是一个个白模。我们被这个问题坑了好久。
4.Unity编译的webplayer工程,免费cache只有50MB
听起来是不是好惊讶?webplayer下的免费cache居然这么少?意味着,在webplayer下,你的LoadFromCacheOrDownload用处并不是非常大。因为你的资源需要一遍又一遍的下载,cache的作用大大缩小了。而如果你想扩展,需要联系他们的销售部,据说价格不菲。不过针对这个问题,现在有人已经利用游览器的缓存绕过了这个问题,思路比较巧妙,但是涉及到unity官方利益,我在这里就不介绍了。
&5.Unity的assetBundle依赖功能局限在相同工程下这个现象比较难以表述,举个例子会比较好:美工给我们两个模型,一个是黑色的椅子,一个是蓝色椅子,这个椅子都用了红色的椅背。但是美工给的是两个unity工程。这时候,我们为了共用红色椅背的贴图,进行依赖的建立。如果不把这两个椅子移动到同一个工程下进行带依赖关系的assetbundle打包的话,则会共用失败。不是下载两次红色椅背贴图就是其中一个出现白模,这个具体要看你怎么处理了。为什么呢?咨询过unity公司,他们告诉我们,在unity里面,每个资源都有个自己的内部id,就算是相同的资源,id在不同工程下也会不同。这样的话,不同工程下的资源自然无法建立依赖关系。其实我觉得这是一个正常的现象,但是我想说的是,所有的模型都要导入到一个unity工程里面进行打包,这个untiy工程会越来越大,最后乱七八糟难以维护。这就是assetBundle的依赖功能的小小局限。所以,如果你要打包的assetbundle比较多,比较杂,可能还是自己去实现依赖会比较好。
另外在开发中还遇到一些其他问题,我会在以后的帖子里继续介绍。
欢迎大家论坛里或者QQ()里加我,互相交流、提供线索。
遇到问题的话也可以来一起讨论,说不定我们遇到的坑别人已经有了解决方案。u3d 跳过resource检测
刚表态过的朋友 ()
作者的其他最新博客
评论 ( 个评论)
&& 说多了都是泪14:51 提问
unity assetbundle加载资源的版本号怎么获取?
unity assetbundle加载资源的版本号怎么获取?
我把资源用assetbundle打包之后放在服务器,然后用WWW.LoadFromCacheOrDownload (path, 1);来加载资源;但是这个函数的第二个参数是版本号,我不知道是什么,我的资源打包的时候没有看到版本号的设置啊,请问资源的版本号怎么设置?
按赞数排序
资源版本号是自己设定的,你可以自己写版本号的生成方法,或者使用MD5值作为版本号,下面是MD5值的代码,参考下,可能对你有帮助。
FileStream fs = new FileStream(file, FileMode.Open);
System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] retVal = puteHash(fs);
fs.Close();
StringBuilder sb = new StringBuilder();
for (int i = 0; i & retVal.L i++)
sb.Append(retVal[i].ToString("x2"));
在下载栏里有工具:Unity Md5更新版本
这个可以自动生成文件夹下的所有文件的Md5值
950关注|423收录
其他相似问题Unity5新的AssetBundle系统使用心得
& & & & Unity的AssetBundle系统是对资源管理的一个扩展,动态更新,网页游戏,资源下载都是基于AssetBundle系统的。但是不得不说,这个系统非常恶心,坑很深。至于有多深,请看这篇文章:&
& & & & 原先的AssetBundle系统需要自己写一大坨导出的代码(BuildPipeline),这个新手会无从下手,老手也经常会被坑到。想正确处理好资源的依赖关系从而保证资源完整而又不会产生重复资源,确实不是一件非常容易的事情。 & & &&
& & & & Unity5新的AssetBundle系统大大简化了这一操作。Unity打包的时候会自动处理依赖关系,并生成一个.manifest文件,这个文件描述了assetbundle包大小、crc验证、包之间的依赖关系等等,是一个文本文件。
加载资源的时候Unity会自动处理好其依赖包的加载
。(参见最后的补充,Unity并没有如此智能,新的assetbundle简化很多,但是也有一些新的坑)
& & & & 打包代码简化为一个函数(其实也没什么必要了,因为流程固定了,做成内嵌的菜单选项也没什么影响)
BuildPipeline.BuildAssetBundles(outputPath);
& & & &执行这个函数,它会自动打包工程目录下的所有的assetbundle,函数足够智能,它只会打包有修改的资源。
& & & &如何添加一个AssetBundle呢?
& & & &很简单,在资源属性窗口底部有一个选项,这个地方设置AssetBundle的名字。它会修改资源对应的.meta文件,记录这个名字。 AssetBundle的名字固定为小写。另外,每个AssetBundle都可以设置一个Variant,其实就是一个后缀,实际AssetBundle的名字会添加这个后缀。如果有不同分辨率的同名资源,可以使用这个来做区分。
& & & 我手头的模型资源非常多,所以我又写了个脚本自动遍历prefab的meta文件,添加AssetBundle名字。有一个需要注意的地方就是.meta文件貌似权限问题,无法直接写入,需要删除原文件,然后使用新的文件替换。。
# -*- coding: utf-8 -*-
import os, sys,
EXT_LIST = ['.prefab.meta', '.png.meta', '.jpg.meta'];
def doWork(path):
for root, dirs, files in os.walk(path):
for file in files:
for ext in EXT_LIST:
if file.endswith(ext):
fullPath = os.path.join(root, file)
fullPath = fullPath.replace('\\', '/')
prefabName = fullPath.replace(path, '');
prefabName = prefabName[:prefabName.find('.')] + '.data';
fileData = [];
fp = open(fullPath, 'r');
for line in fp:
if line.find('assetBundleName:') != -1:
fileData.append('
assetBundleName: ' + prefabName.lower() + '\n');
fileData.append(line);
fp.close();
# os.remove(fullPath);
fpw = open(fullPath + '.tmp', 'w');
fpw.writelines(fileData);
fpw.close();
os.remove(fullPath)
shutil.copy(fullPath + '.tmp', fullPath);
os.remove(fullPath + '.tmp')
doWork(r'Assets/Resources/Prefab/')
os.system('PAUSE')
c#编辑器扩展(与python代码功能一样,喜欢哪个用哪个)
public class ExportAssetBundles : Editor
// 设置assetbundle的名字(修改meta文件)
[MenuItem(&Tools/SetAssetBundleName&)]
static void OnSetAssetBundleName()
UnityEngine.Object obj = Selection.activeO
string path = AssetDatabase.GetAssetPath(Selection.activeObject);
string[] extList = new string[] { &.prefab.meta&, &.png.meta&, &.jpg.meta& , &.tga.meta& };
EditorUtil.Walk(path, extList, DoSetAssetBundleName);
//刷新编辑器
AssetDatabase.Refresh();
Debug.Log(&AssetBundleName修改完毕&);
static void DoSetAssetBundleName(string path)
path = path.Replace(&\\&, &/&);
int index = path.IndexOf(EditorConfig.PREFAB_PATH);
string relativePath = path.Substring(path.IndexOf(EditorConfig.PREFAB_PATH) + EditorConfig.PREFAB_PATH.Length);
string prefabName = relativePath.Substring(0, relativePath.IndexOf('.')) + EditorConfig.ASSETBUNDLE;
StreamReader fs = new StreamReader(path);
List&string& ret = new List&string&();
while((line = fs.ReadLine()) != null) {
line = line.Replace(&\n&, &&);
if (line.IndexOf(&assetBundleName:&) != -1) {
assetBundleName: & + prefabName.ToLower();
ret.Add(line);
fs.Close();
File.Delete(path);
StreamWriter writer = new StreamWriter(path + &.tmp&);
foreach (var each in ret) {
writer.WriteLine(each);
writer.Close();
File.Copy(path + &.tmp&, path);
File.Delete(path + &.tmp&);
[MenuItem(&Tools/CreateAssetBundle&)]
static void OnCreateAssetBundle()
BuildPipeline.BuildAssetBundles(EditorConfig.OUTPUT_PATH);
//刷新编辑器
AssetDatabase.Refresh();
Debug.Log(&AssetBundle打包完毕&);
& & & & 之前我简单的认为Unity既然已经做了资源依赖链,那么加载资源的时候理所应当的会自动处理好依赖关系。结果是我想的太简单了。我们必须自己手动加载依赖的assetbundle。
& & & & 我们直接调用打包函数,在打包目录会生成一个与打包目录同名的文件,比如我们打包到AssetsBundle/windows目录下,则此目录下会生成一个windows文件,以及一个windows.manifest文件。
& & & & 这个windows文件就包含了当前assetbundle的列表和依赖关系。我们需要在游戏开始的时候手动加载这个assetbundle(即windows),获取一个AssetBundleManifest对象。这个对象有GetAllAsssetBundles()函数还有一个GetAllDependencies函数。
& & & & 我们可以使用GetAllDependencies传入一个assetbundle的名字来获取其依赖的assetbundle,然后分别加载这些assetbundle。注意传入的文件名是我们生成assetbundle设置的名字,而不是全路径。可以参考windows.manifest文件查看assetbundle名字形式。
& & & & 新的问题:
& & & &由于我的资源量比较大,所以我拆分了多个生成工程。而生成assetbundle的时候指向的是一个路径,最终合并后就是一个完整的游戏资源包。我们在游戏运行加载资源的时候需要windows这个manifest文件,而它又是Unity自己生成的,并且只保存了当前项目生成的assetbundle信息,无法自动合并。从这点来说它无法满足我的需求。
& & & &我们之所以需要这个manifest文件,是因为我们要从中获取依赖关系。所以我在项目中自己维护资源列表。它可以根据生成的manifest自动生成、合并资源列表(一个json格式的文本文件)。我们在游戏开始时解析这个json文件获取到资源列表。这个资源列表同时也可以作为自动更新的文件列表。
& & & 实现方式很简单,assetbundle打包完毕后,加载manifest文件(注意这里有个坑,我会在另一篇文章里面讲解如何在Editor下加载AssetBundle),获取所有资源信息,与当前已存在的资源列表进行比对,合并。多个项目之间只要维护好一份统一的资源列表就可以了。
本分类共有文章48篇,更多信息详见
& 2012 - 2016 &
&All Rights Reserved. &
/*爱悠闲图+*/
var cpro_id = "u1888441";
/*爱悠闲底部960*75*/
var cpro_id = "u1888128";Unity3D 每次打包生成的AssetBundle Hash都不一样的原因 - 兜里
作者:切梦刀
热度:6546℃
用Unity3D做游戏开发,基本都会涉及到资源版本管理及更新,下面是做的过程中遇到的一小问题,记录一下以供参考。
而常用于标记资源版本的方法有计算文件Hash、VCS的版本等,进行文件Hash计算时发现同一个资源文件每次打包成AssetBundle后Hash都不一样,这不科学啊,这样基本是废了用Hash作版本标记的方法。
查了查资料,发现AssetBuildPipeline.BuildAssetBundle接口options参数,可以增加一项BuildAssetBundleOptions.DeterministicAssetBundle。这将保证AssetBundle使用唯一Hash进行标识,若不加这个参数AssetBundle每次构建时都生成不同ID
添加新评论
:很酷的域名
:一个bug,改好了
:磊子,你是穿越回来的不?今天是,你上面2016-0...
:磊子,你是穿越回来的不?今天才,你上面2016-0...
:没空写东西,有空时又不想写
:你怎么也这么久没有更新了
:变成什么?
:去掉BOM头变成,咋让他不变

我要回帖

更多关于 unity assetbundle 的文章

 

随机推荐