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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
| // Editor/AssetBundleBuild.cs
using UnityEditor;
using UnityEngine;
using System.Collections.Generic;
using System.IO;
using System.Linq;
public class AssetBundleBuild
{
[MenuItem("Tools/Build Asset Bundles")]
public static void BuildAllAssetBundles()
{
// 资源变体配置
var builds = new List<AssetBundleBuild>();
// 纹理变体
builds.Add(CreateVariantBuild("assets/textures/ui_bg", new[] { "hd", "sd" }));
builds.Add(CreateVariantBuild("assets/textures/characters", new[] { "hd", "sd" }));
// 模型变体(LOD)
builds.Add(CreateVariantBuild("assets/models/characters", new[] { "high", "medium", "low" }));
// 构建选项
var options = new BuildAssetBundleOptions
{
// 压缩选项
BuildOptions = BuildAssetBundleOptions.None |
BuildAssetBundleOptions.DisableWriteTypeTree |
BuildAssetBundleOptions.StrictMode |
BuildAssetBundleOptions.ChunkBasedCompression,
// 子文件压缩(降低运行时解压开销)
BuildOptions = BuildAssetBundleOptions.ChunkBasedCompression
};
// 目标平台
BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
// 输出路径
string outputPath = Path.Combine("Build", "AssetBundles", target.ToString());
// 创建目录
Directory.CreateDirectory(outputPath);
// 执行构建
var manifest = BuildPipeline.BuildAssetBundles(
outputPath,
builds.ToArray(),
options,
target
);
// 生成依赖关系图
GenerateDependencyGraph(manifest);
// 计算每个包的大小
AnalyzeBundleSizes(outputPath);
Debug.Log($"Asset bundles built successfully to: {outputPath}");
}
private static AssetBundleBuild CreateVariantBuild(
string assetPath,
string[] variants
)
{
var build = new AssetBundleBuild
{
assetBundleName = assetPath,
assetNames = new[] { $"{assetPath}.prefab" }
};
// 为每个变体创建资源配置
var variantAssets = new List<string>();
foreach (var variant in variants)
{
variantAssets.Add($"{assetPath}_{variant}.prefab");
}
build.assetNames = variantAssets.ToArray();
return build;
}
private static void GenerateDependencyGraph(AssetBundleManifest manifest)
{
var graph = new Dictionary<string, string[]>();
foreach (var bundle in manifest.GetAllAssetBundles())
{
var dependencies = manifest.GetAllDependencies(bundle);
graph[bundle] = dependencies;
}
// 导出为JSON
var json = JsonUtility.ToJson(graph, true);
File.WriteAllText($"{manifest.GetAllAssetBundles()[0]}_dependencies.json", json);
}
private static void AnalyzeBundleSizes(string outputPath)
{
var files = Directory.GetFiles(outputPath, "*", SearchOption.AllDirectories)
.Where(f => !f.EndsWith(".manifest") && !f.EndsWith(".meta"));
var report = new Dictionary<string, long>();
foreach (var file in files)
{
var info = new FileInfo(file);
report[Path.GetFileName(file)] = info.Length;
}
// 生成大小报告
var sorted = report.OrderByDescending(kvp => kvp.Value);
var reportLines = sorted.Select(kvp =>
$"{kvp.Key}: {FormatBytes(kvp.Value)}"
);
File.WriteAllLines(
Path.Combine(outputPath, "size_report.txt"),
reportLines
);
}
private static string FormatBytes(long bytes)
{
string[] sizes = { "B", "KB", "MB", "GB" };
double len = bytes;
int order = 0;
while (len >= 1024 && order < sizes.Length - 1)
{
order++;
len = len / 1024;
}
return $"{len:0.##} {sizes[order]}";
}
}
|