unity 打AB包流程 发表于 2025-01-23 | 更新于 2025-01-23
| 浏览量:
下面是详细的打包流程、代码示例,以及生成版本文件的完整实现过程。此内容适用于 Unity 项目中使用 AssetBundles 打包并支持版本文件生成与热更新的场景。
1. 打包流程概述
配置资源文件 :
将需要打包的资源组织到指定目录中。
设置每个资源的 AssetBundle 名称。
打包 AssetBundles :
使用 Unity 提供的 BuildPipeline.BuildAssetBundles
方法,将资源打包成 .ab
文件。
生成版本文件 :
记录所有打包生成的 .ab
文件及其校验值(MD5 或 SHA256)。
生成一个 JSON 格式的版本文件,包含版本号、资源文件名及校验值。
上传资源和版本文件 :
2. 实现步骤 Step 1: 配置资源文件 在 Unity 中为资源设置 AssetBundle 名称:
选中需要打包的资源(例如:Prefab、Texture)。
在 Inspector 面板中,设置 AssetBundle
字段为指定的名称。例如:
character_assets
environment_assets
Step 2: 编写打包脚本 使用 Unity 提供的 API 打包资源。
示例代码:打包 AssetBundles
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 using UnityEditor;using UnityEngine;using System.IO;using System.Security.Cryptography;public class AssetBundleBuilder { [MenuItem("Tools/Build AssetBundles" ) ] public static void BuildAllAssetBundles () { string outputPath = Path.Combine(Application.dataPath, "../AssetBundles" ); if (!Directory.Exists(outputPath)) Directory.CreateDirectory(outputPath); BuildPipeline.BuildAssetBundles(outputPath, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows); GenerateVersionFile(outputPath); Debug.Log("AssetBundles and version file generated successfully!" ); } private static void GenerateVersionFile (string assetBundlePath ) { string [] files = Directory.GetFiles(assetBundlePath, "*" , SearchOption.AllDirectories); var versionData = new VersionData(); foreach (var file in files) { if (file.EndsWith(".manifest" ) || file.EndsWith(".meta" )) continue ; string fileName = Path.GetFileName(file); string hash = CalculateMD5(file); versionData.assetBundles[fileName] = hash; } versionData.version = System.DateTime.Now.ToString("yyyyMMddHHmmss" ); string versionFilePath = Path.Combine(assetBundlePath, "version.json" ); File.WriteAllText(versionFilePath, JsonUtility.ToJson(versionData, true )); } private static string CalculateMD5 (string filePath ) { using (var md5 = MD5.Create()) { using (var stream = File.OpenRead(filePath)) { var hash = md5.ComputeHash(stream); return BitConverter.ToString(hash).Replace("-" , "" ).ToLowerInvariant(); } } } } [System.Serializable ] public class VersionData { public string version; public System.Collections.Generic.Dictionary<string , string > assetBundles = new System.Collections.Generic.Dictionary<string , string >(); }
Step 3: 上传资源到服务器 将以下内容上传到服务器:
所有打包生成的 .ab
文件。
version.json
文件。
常见的上传方式:
使用 FTP 工具(如 FileZilla)手动上传。
配合自动化脚本将文件上传到服务器或存储服务(如 AWS S3、GitHub Releases)。
3. 版本文件的结构和内容 版本文件(version.json
)示例: 1 2 3 4 5 6 7 { "version" : "20250123090000" , "assetBundles" : { "character_assets" : "f2a29d0c08f2c4a3d1d7ec5b6e8b8a34" , "environment_assets" : "e1d4f7600c1f7b4a9e5f9e2b123f9a8d" } }
说明:
version
表示版本号,用时间戳生成(如 yyyyMMddHHmmss
格式)。
assetBundles
是一个字典,存储每个资源文件名及其对应的 MD5 校验值。
4. 客户端检查版本和热更新流程 在客户端,以下是资源检查和下载的基本逻辑:
获取版本文件 :
客户端启动时,下载服务器的 version.json
。
如果客户端不存在本地版本文件,则直接下载所有资源。
比较版本号 :
如果服务器版本号高于本地版本号,开始检查资源文件。
校验资源文件 :
根据服务器的版本文件中的校验值,逐一检查本地资源文件是否完整。
如果文件丢失或校验值不匹配,则下载该文件。
下载更新资源 :
将需要更新的 .ab
文件从服务器下载到本地。
更新本地的版本文件。
5. 示例代码:客户端版本检查与更新 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 using UnityEngine;using System.Collections;using System.IO;using UnityEngine.Networking;public class HotUpdateManager : MonoBehaviour { private string serverVersionUrl = "https://example.com/version.json" ; private string localVersionPath = Application.persistentDataPath + "/version.json" ; private string serverAssetBaseUrl = "https://example.com/" ; void Start () { StartCoroutine(CheckForUpdates()); } IEnumerator CheckForUpdates () { UnityWebRequest versionRequest = UnityWebRequest.Get(serverVersionUrl); yield return versionRequest.SendWebRequest(); if (versionRequest.result != UnityWebRequest.Result.Success) { Debug.LogError("Failed to fetch version.json: " + versionRequest.error); yield break ; } string serverVersionContent = versionRequest.downloadHandler.text; var serverVersionData = JsonUtility.FromJson<VersionData>(serverVersionContent); VersionData localVersionData = null ; if (File.Exists(localVersionPath)) { string localVersionContent = File.ReadAllText(localVersionPath); localVersionData = JsonUtility.FromJson<VersionData>(localVersionContent); } if (localVersionData == null || serverVersionData.version != localVersionData.version) { Debug.Log("New version detected, updating assets..." ); foreach (var asset in serverVersionData.assetBundles) { string localFilePath = Path.Combine(Application.persistentDataPath, asset.Key); if (!File.Exists(localFilePath) || GetMD5(localFilePath) != asset.Value) { yield return StartCoroutine (DownloadAsset(asset.Key )) ; } } File.WriteAllText(localVersionPath, serverVersionContent); Debug.Log("Assets updated successfully!" ); } else { Debug.Log("Assets are up-to-date." ); } } IEnumerator DownloadAsset (string assetName ) { string url = serverAssetBaseUrl + assetName; UnityWebRequest request = UnityWebRequest.Get(url); yield return request.SendWebRequest(); if (request.result == UnityWebRequest.Result.Success) { string localPath = Path.Combine(Application.persistentDataPath, assetName); File.WriteAllBytes(localPath, request.downloadHandler.data); Debug.Log($"Downloaded: {assetName} " ); } else { Debug.LogError($"Failed to download {assetName} : {request.error} " ); } } private string GetMD5 (string filePath ) { using (var md5 = System.Security.Cryptography.MD5.Create()) using (var stream = File.OpenRead(filePath)) { var hash = md5.ComputeHash(stream); return System.BitConverter.ToString(hash).Replace("-" , "" ).ToLowerInvariant(); } } }
通过以上流程,你可以实现完整的热更新功能,包括打包资源、生成版本文件、检查和下载更新资源。
HybridCLR 程序集打包成ab并加载 Unity HybridCLR 热更新程序集打包与加载流程 HybridCLR 是 Unity 的一种轻量级跨平台解决方案,支持加载 AOT(Ahead Of Time)和解释执行的程序集,适用于游戏热更新。以下是完整的 打包流程 和 加载流程 。
1. 热更新程序集打包流程 1.1 配置热更新程序集工程 步骤 1: 创建独立的热更新工程
在 Unity 项目中,创建一个独立的 C# 项目用于存放热更新代码。
确保该工程编译为 .dll
文件(Class Library 项目)。
使用 .NET Framework 4.x
或 .NET Standard 2.1
(与 Unity 项目一致)。
步骤 2: 添加必要引用
引用 Unity 的程序集文件:
UnityEngine.dll
UnityEngine.CoreModule.dll
这些文件可在 Unity 安装目录的 Editor/Data/Managed
或 Library/ScriptAssemblies
下找到。
步骤 3: 编写热更新代码
将需要动态更新的逻辑代码放入热更新工程。
避免引用 UnityEditor 命名空间。
特别注意 :在 HybridCLR 中,一部分代码会运行在 AOT 模式,因此需要合理规划哪些代码进入热更新工程,哪些留在主工程中。
1.2 编译与输出程序集 步骤 1: 编译热更新程序集
使用 Visual Studio 或 Rider 将热更新工程编译为 .dll
文件。
输出文件如:
HotUpdate.dll
(主程序集)
HotUpdate.pdb
(符号文件,用于调试)。
步骤 2: 标记为热更新程序集
在 Unity 的主工程中,创建一个文件夹(如 Assets/HotUpdateAssemblies
),将编译好的 .dll
文件放入该目录。
步骤 3: 使用 AssetBundle 打包
在 Unity 中创建一个脚本,用于将这些 .dll
文件打包成 AssetBundle:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 using UnityEditor;using UnityEngine;public class AssetBundleBuilder { [MenuItem("Tools/Build AssetBundles" ) ] public static void BuildHotUpdateAssemblies () { string outputPath = "Assets/StreamingAssets/HotUpdateBundles" ; if (!System.IO.Directory.Exists(outputPath)) System.IO.Directory.CreateDirectory(outputPath); AssetBundleBuild[] buildMap = new AssetBundleBuild[1 ]; buildMap[0 ] = new AssetBundleBuild { assetBundleName = "hotupdateassemblies" , assetNames = new [] { "Assets/HotUpdateAssemblies/HotUpdate.dll" } }; BuildPipeline.BuildAssetBundles(outputPath, buildMap, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows64); Debug.Log("Hot update AssetBundle built successfully!" ); } }
这会将 HotUpdate.dll
打包到一个名为 hotupdateassemblies
的 AssetBundle 中。
步骤 4: 上传到资源服务器
将打包生成的 AssetBundle(如 hotupdateassemblies
) 上传到远程服务器(如 GitHub Releases、CDN、阿里云 OSS 等),以便运行时下载。
2. 热更新程序集加载流程 2.1 配置 HybridCLR 步骤 1: 安装 HybridCLR
在 Unity 项目中,按照 HybridCLR 的官方文档安装 HybridCLR 插件。
安装后会生成以下文件和配置:
HybridCLR/HotUpdateAssemblies
文件夹(存放热更新程序集)。
HybridCLR
配置文件(设置热更新相关参数)。
步骤 2: 配置 AOT 元数据
AOT 模式需要将部分元数据文件(.dll
)打包到游戏中。
在 HybridCLR/HotUpdateAssemblies
文件夹中,放入所有热更新相关的 .dll
文件。
2.2 加载热更新程序集 步骤 1: 下载 AssetBundle
游戏启动时,从远程服务器下载最新的 AssetBundle 文件。
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 using System.Collections;using UnityEngine;public class HotUpdateManager : MonoBehaviour { private const string AssetBundleURL = "https://your-server.com/hotupdateassemblies" ; IEnumerator Start () { using var www = UnityEngine.Networking.UnityWebRequestAssetBundle.GetAssetBundle(AssetBundleURL); yield return www.SendWebRequest(); if (www.result != UnityEngine.Networking.UnityWebRequest.Result.Success) { Debug.LogError("Failed to download AssetBundle: " + www.error); yield break ; } var assetBundle = UnityEngine.Networking.DownloadHandlerAssetBundle.GetContent(www); if (assetBundle == null ) { Debug.LogError("Failed to load AssetBundle." ); yield break ; } TextAsset dllAsset = assetBundle.LoadAsset<TextAsset>("HotUpdate.dll" ); if (dllAsset == null ) { Debug.LogError("Failed to load HotUpdate.dll from AssetBundle." ); yield break ; } LoadHotUpdateAssembly(dllAsset.bytes); } private void LoadHotUpdateAssembly (byte [] dllBytes ) { var assembly = System.Reflection.Assembly.Load(dllBytes); var type = assembly.GetType("HotUpdate.Program" ); var method = type.GetMethod("Main" ); method?.Invoke(null , null ); } }
步骤 2: 加载热更新程序集
使用 System.Reflection.Assembly.Load
加载 HotUpdate.dll
,并调用其中的入口方法(如 Main()
)。
步骤 3: 切换逻辑到热更新代码
在热更新程序集(如 HotUpdate.dll
)中,处理游戏的逻辑更新。例如:1 2 3 4 5 6 7 8 9 10 11 namespace HotUpdate { public class Program { public static void Main () { Debug.Log("HotUpdate assembly loaded successfully!" ); } } }
3. 总结 打包流程
在独立的 C# 项目中编写热更新代码,编译为 .dll
文件。
将 .dll
文件放入 Unity 项目中并打包为 AssetBundle。
将打包的 AssetBundle 上传到远程服务器。
加载流程
游戏启动时,下载远程的 AssetBundle 文件。
解压并加载 .dll
文件到内存。
使用 Assembly.Load
加载程序集,并调用热更新代码入口(如 Main()
方法)。
切换游戏逻辑到热更新代码。
通过 HybridCLR,这种热更新流程实现了代码与资源的分离更新,提升了项目的维护性和灵活性。
热更程序集打包成