Unity的资源打包,如果要做完美,其实是很复杂的.那么为什么资源要打包呢,因为我们要做资源更新.没办法啊.
在我看来,完美的资源打包至少有以下几个方面要处理好:
1) 资源分类设计合理.控制包粒度,单个包不能太大.
2) 灵活的文件打包结构.支持文件和文件夹打包
3) 共用资源的完美处理.防止重复打包.
4) 快速增量打包.加快打包速度.
具体来聊一下我的一些思考.
1)资源粒度设计合理
其实就是如何划分资源.先说下我的划分.
UI .prefab
Model .prefab 需要动态加载的模型,其实就是角色
Effect .prefab 需要动态加载的特效,其实就是技能特效
Scene .unity
Sound .wav .mp3 .ogg
Animation .anim
Table .txt
Lua .lua
以上的划分也比较常规,只是动作文件的划分比较特殊点.因为动作文件共用性很强,比如所有主角的几十套装备模型都是共用的一套动作,所以把动作从模型独立出来,动态加载动作,这样打包模型,就不会打包动作进去.动态的加载,也有一些讲究,原本是每个动作单独打包,用到什么动作才加载,这样粒度最小,最完美.但是由于WWW加载是异步的,不支持同步加载动作,会有很多问题,所以最后的解决方案是,把这个模型的所有动作打成了一个Bundle包,加载一个模型前,先加载这个模型的所有动作.这样来实现同步效果.
2)灵活的文件打包结构
上面提到了动作打包,我们把一个文件夹下面的所有动作打成了一个包,我们也可以单个动作打成一个包,所谓灵活,就是这个包可以支持1个或者多个主资源.我设计了3种分组类型.这样一个包对应哪些资源,就可以划分出来.
// 分组类型
public enum GroupType
{
File_Recursion, // 按文件分组(递归遍历)
Directory_Recursion, // 按文件夹分组(递归遍历)
File_Directory, // 按文件和文件夹分组(第一级目录)
}
// 获得主资源路径
public static Dictionary<string, List<string>> GetMainAssetPaths(string path, string[] fileExtArray, GroupType groupType)
{
Dictionary<string, List<string>> paths = new Dictionary<string, List<string>>();
path = path.Replace('\\', '/');
if (groupType == GroupType.File_Directory)
{
string[] files = Directory.GetFiles(path);
string[] dictionaries = Directory.GetDirectories(path);
// 按文件分组
foreach (string file in files)
{
foreach (string fileExt in fileExtArray)
{
if (file.EndsWith(fileExt))
{
List<string> list = new List<string>(1); // 数量1
string filename = file.Replace(Application.dataPath, "Assets").Replace('\\', '/');
list.Add(filename);
string key = file.Replace('\\', '/');
key = key.Substring(key.LastIndexOf('/') + 1);
key = key.Substring(0, key.Length - fileExt.Length - 1);
paths.Add(key, list);
break;
}
}
}
// 按文件夹分组
foreach (string directory in dictionaries)
{
files = Directory.GetFiles(directory);
string key = directory.Replace('\\', '/');
key = key.Substring(key.LastIndexOf('/') + 1);
List<string> list = new List<string>();
foreach (string file in files)
{
foreach (string fileExt in fileExtArray)
{
if (file.EndsWith(fileExt))
{
string filename = file.Replace(Application.dataPath, "Assets").Replace('\\', '/');
list.Add(filename);
}
}
}
paths.Add(key, list);
}
}
else
{
GetMainAssetPathsRecursion(paths, path, path, fileExtArray, groupType);
}
return paths;
}
static void GetMainAssetPathsRecursion(Dictionary<string, List<string>> paths, string startPath, string curPath, string[] fileExtArray, GroupType groupType)
{
string[] files = Directory.GetFiles(curPath);
string[] dictionaries = Directory.GetDirectories(curPath);
foreach (string file in files)
{
foreach (string fileEnd in fileExtArray)
{
if (file.EndsWith(fileEnd))