前言
一个小小的建议,有能力的同学最好还是自己去下载示例工程研究研究一整个过程是怎么实现的,毕竟自己研究会的才是真正学进去的嘛!
好了话不多说下面就开始教程吧!
开始准备
1.创建一个AssemblyDefinition命名为HotFix代表这是一个热更程序集,不知道AssemblyDefinition是什么的建议先去熟悉一下,这里不做赘述!
2.**切记!切记!切记!**热更程序集可以引用其他程序集,但是非热更程序集不能引用热更程序集!
3.创建完成之后就可以在带有HotFix程序集的目录下随意编写热更代码啦!
打包热更程序集
1.菜单栏点击打开HybridCLR/Settings
把你的热更AssemblyDefinition添加到 热更新AssemblyDefinition下面
2.编写编辑器脚本将热更程序集拷贝到你存放资源的目录下面,跟随其他资源打进资源包即可!
相关编辑器脚本代码会放在文章最后
3.编写完编辑器脚本之后执行HybridCLR/CopyToAssetBundle就可以将你的热更程序集拷贝到指定目录下面了。
加载热更代码
将刚刚打包的热更从程序集以bytes的格式加载出来,然后将该程序集加载出来
再就是调用热更代码 有两种方法
一种是在热更代码中写一个启动脚本挂载到一个预制体上面,然后直接实例化这个预制体即可
另一种就是通过反射去执行一个启动初始化的方法即可
相关代码如下
#if !UNITY_EDITOR
var _hotUpdateAss = Assembly.Load(你加载进来的bytes数据);
#else
#endif
//第一种方法
GameObject.Instance("你的启动预制体");
//第二种方法
Type entryType = _hotUpdateAss.GetType("HotFixStart");
entryType.GetMethod("Init").Invoke(null, null);
至此你的热更就完成了
AOT程序集
我们在开发的过程中难免会去引用一些其他的程序集,这个时候就需要把其他的程序集也收集起来在加载热更之前把AOT程序集先加载出来
同热更程序集不一样的是你需要把aot的名字写到settings里面如下图
然后在打包的时候把这些程序集一并打包即可
在加载热更代码的之前可以先一步将这些AOT程序集加载出来
/// <summary>
/// 为aot assembly加载原始metadata, 这个代码放aot或者热更新都行。
/// 一旦加载后,如果AOT泛型函数对应native实现不存在,则自动替换为解释模式执行
/// </summary>
private static void LoadMetadataForAOTAssemblies()
{
List<string> aotMetaAssemblyFiles = new List<string>()
{
"mscorlib.dll",
"System.dll",
"System.Core.dll",
};
/// 注意,补充元数据是给AOT dll补充元数据,而不是给热更新dll补充元数据。
/// 热更新dll不缺元数据,不需要补充,如果调用LoadMetadataForAOTAssembly会返回错误
///
HomologousImageMode mode = HomologousImageMode.SuperSet;
foreach (var aotDllName in aotMetaAssemblyFiles)
{
byte[] dllBytes = ReadBytesFromStreamingAssets(aotDllName + ".bytes");
// 加载assembly对应的dll,会自动为它hook。一旦aot泛型函数的native函数不存在,用解释器版本代码
LoadImageErrorCode err = RuntimeApi.LoadMetadataForAOTAssembly(dllBytes, mode);
Debug.Log($"LoadMetadataForAOTAssembly:{aotDllName}. mode:{mode} ret:{err}");
}
}
最后就是那段编辑器代码啦,可能导入之后会有一些引用报错,你只需要把引用的地方改到你自己的相关引用就可以了
using HybridCLR.Editor.Commands;
using System.IO;
using UnityEditor;
using UnityEngine;
namespace HybridCLR.Editor
{
public static class AssetBundleBuildCommand
{
public static string HybridCLRBuildCacheDir => Application.dataPath + "/AssetBundle/Hotscripts";
public static string AssetBundleSourceDataTempDir => $"{HybridCLRBuildCacheDir}/HotFixBytes";
public static string GetAssetBundleTempDirByTarget(BuildTarget target)
{
string path = $"{AssetBundleSourceDataTempDir}/{target}";
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
return path;
}
[MenuItem("HybridCLR/CopyToAssetBundle")]
public static void BuildSceneAssetBundleActiveBuildTarget()
{
CompileDllCommand.CompileDllActiveBuildTarget();
CopyAOTAssembliesToStreamingAssets();
CopyHotUpdateAssembliesToStreamingAssets();
AssetDatabase.Refresh();
}
public static void CopyAOTAssembliesToStreamingAssets()
{
var target = EditorUserBuildSettings.activeBuildTarget;
string aotAssembliesSrcDir = SettingsUtil.GetAssembliesPostIl2CppStripDir(target);
foreach (var dll in ProcedureLoadDLL.AOTMetaAssemblyNames)
{
string srcDllPath = $"{aotAssembliesSrcDir}/{dll}";
if (!File.Exists(srcDllPath))
{
Debug.LogError($"ab中添加AOT补充元数据dll:{srcDllPath} 时发生错误,文件不存在。裁剪后的AOT dll在BuildPlayer时才能生成,因此需要你先构建一次游戏App后再打包。");
continue;
}
string dllBytesPath = $"{GetAssetBundleTempDirByTarget(EditorUserBuildSettings.activeBuildTarget)}/{dll}.bytes";
File.Copy(srcDllPath, dllBytesPath, true);
Debug.Log($"[CopyAOTAssembliesToStreamingAssets] copy AOT dll {srcDllPath} -> {dllBytesPath}");
}
}
public static void CopyHotUpdateAssembliesToStreamingAssets()
{
var target = EditorUserBuildSettings.activeBuildTarget;
string hotfixDllSrcDir = SettingsUtil.GetHotUpdateDllsOutputDirByTarget(target);
foreach (var dll in SettingsUtil.HotUpdateAssemblyFilesExcludePreserved)
{
string dllPath = $"{hotfixDllSrcDir}/{dll}";
string dllBytesPath = $"{GetAssetBundleTempDirByTarget(EditorUserBuildSettings.activeBuildTarget)}/{dll}.bytes";
File.Copy(dllPath, dllBytesPath, true);
Debug.Log($"[CopyHotUpdateAssembliesToStreamingAssets] copy hotfix dll {dllPath} -> {dllBytesPath}");
}
}
}
}
好了文章到此结束,完结撒花!