Unity5的AssetBundle打包机制和以前版本不太一样。简单的说就是,只要给你要打包的资源设置一个AssetBundleName ,Unity自身会对这些设置了名字的资源进行打包,如果一个资源依赖了另一个资源。Unity自己会处理依赖关系,AssetBundleManifest文件就保存着这些资源的依赖关系。
比如一个UI面板.Prefab,依赖了一个图集Atlas,一个字体文件
做个测试:
只给UI面板3.prefab设置AssetBundleName。
打出包来看,别看只有371KB,那是因为我拿得面板不是很复杂,依赖的图集,字体,本身就不是很大。
要是项目中的话,你不处理依赖打包的话,几M都是有的。
要是有其它的UI面板,设置AssetBundleName,打出包,都是这么大的
依赖文件显示资源没依赖,这是因为每一个面板里面都单独打包了一份图集资源,字体资源。显然这是不可取的。
对于同类型的UI面板来说,这些图集和字体文件,大家用的都是同一份,只要打包出一份,大家共享就好了。
接下给图集资源,字体文件都设置AssetBundleName,再进行打包,可以看到变小了。
在看.manifest文件,有了依赖关系。
项目中,资源辣么多,总不能在编辑器里一个一个给资源进行设置AssetBundleName吧,那会蛋疼死的,是吧。
上代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
| using UnityEngine;
using System.Collections;
using UnityEditor;
using System.IO;
/// <summary>
/// 把Resource下的资源打包成.unity3d 到StreamingAssets目录下
/// </summary>
public class Builder : Editor
{
public static string sourcePath = Application.dataPath + "/Resources";
const string AssetBundlesOutputPath = "Assets/StreamingAssets";
[MenuItem("Tools/AssetBundle/Build")]
public static void BuildAssetBundle()
{
ClearAssetBundlesName ();
Pack (sourcePath);
string outputPath = Path.Combine (AssetBundlesOutputPath,Platform.GetPlatformFolder(EditorUserBuildSettings.activeBuildTarget));
if (!Directory.Exists (outputPath))
{
Directory.CreateDirectory(outputPath);
}
//根据BuildSetting里面所激活的平台进行打包
BuildPipeline.BuildAssetBundles (outputPath,0,EditorUserBuildSettings.activeBuildTarget);
AssetDatabase.Refresh ();
Debug.Log ("打包完成");
}
/// <summary>
/// 清除之前设置过的AssetBundleName,避免产生不必要的资源也打包
/// 之前说过,只要设置了AssetBundleName的,都会进行打包,不论在什么目录下
/// </summary>
static void ClearAssetBundlesName()
{
int length = AssetDatabase.GetAllAssetBundleNames ().Length;
Debug.Log (length);
string[] oldAssetBundleNames = new string[length];
for (int i = 0; i < length; i++)
{
oldAssetBundleNames[i] = AssetDatabase.GetAllAssetBundleNames()[i];
}
for (int j = 0; j < oldAssetBundleNames.Length; j++)
{
AssetDatabase.RemoveAssetBundleName(oldAssetBundleNames[j],true);
}
length = AssetDatabase.GetAllAssetBundleNames ().Length;
Debug.Log (length);
}
static void Pack(string source)
{
DirectoryInfo folder = new DirectoryInfo (source);
FileSystemInfo[] files = folder.GetFileSystemInfos ();
int length = files.Length;
for (int i = 0; i < length; i++) {
if(files[i] is DirectoryInfo)
{
Pack(files[i].FullName);
}
else
{
if(!files[i].Name.EndsWith(".meta"))
{
file (files[i].FullName);
}
}
}
}
static void file(string source)
{
string _source = Replace (source);
string _assetPath = "Assets" + _source.Substring (Application.dataPath.Length);
string _assetPath2 = _source.Substring (Application.dataPath.Length + 1);
//Debug.Log (_assetPath);
//在代码中给资源设置AssetBundleName
AssetImporter assetImporter = AssetImporter.GetAtPath (_assetPath);
string assetName = _assetPath2.Substring (_assetPath2.IndexOf("/") + 1);
assetName = assetName.Replace(Path.GetExtension(assetName),".unity3d");
//Debug.Log (assetName);
assetImporter.assetBundleName = assetName;
}
static string Replace(string s)
{
return s.Replace("\\","/");
}
}
public class Platform
{
public static string GetPlatformFolder(BuildTarget target)
{
switch (target)
{
case BuildTarget.Android:
return "Android";
case BuildTarget.iOS:
return "IOS";
case BuildTarget.WebPlayer:
return "WebPlayer";
case BuildTarget.StandaloneWindows:
case BuildTarget.StandaloneWindows64:
return "Windows";
case BuildTarget.StandaloneOSXIntel:
case BuildTarget.StandaloneOSXIntel64:
case BuildTarget.StandaloneOSXUniversal:
return "OSX";
default:
return null;
}
}
} |
有了这个包含所有资源的依赖关系的.manifest文件,那么在加载使用一个资源的时候,就要根据这个文件,先去加载这个资源依赖的所有资源,然后再加载这个资源,然后就可以使用啦。加载这块,下次再整理。
代码都在这了,工程我就不上传了。
拜了个拜!
|