参考文档: 在Unity中构建AssetBundle补丁包 作者: 仙猫洞
使用 CatAssetManager.BatchLoadAssetAsync 批量加载需要热更的程序集
List<string> AOTMetaAssemblyFiles; //热更dll的AssetBundle的地址
CatAssetManager.BatchLoadAssetAsync( AOTMetaAssemblyFiles ).OnLoaded += OnAotMetaAssemblyFilesLoaded;
加载AOT元数据
private static void Run( )
{
Log.Green( "执行热更新后的代码" );
#if !UNITY_EDITOR
_hotUpdateAss = Assembly.Load( HotUpdateBytes );
#else
_hotUpdateAss = System.AppDomain.CurrentDomain.GetAssemblies( ).First( a => a.GetName( ).Name == "HotUpdate" );
#endif
Type entryType = _hotUpdateAss.GetType( "HotService" );
entryType.GetMethod( "Update" ).Invoke( null, null );
AotCompletedCallback?.Invoke( );
}
#region HotFix
private static Assembly _hotUpdateAss;
public Assembly GetAssembly( )
{
return _hotUpdateAss;
}
private static void OnAotMetaAssemblyFilesLoaded( BatchAssetHandler handler )
{
Log.Green( "AOT元数据加载完毕" );
/// 注意,补充元数据是给AOT dll补充元数据,而不是给热更新dll补充元数据。
/// 热更新dll不缺元数据,不需要补充,如果调用LoadMetadataForAOTAssembly会返回错误
///
handler.Handlers.ForEach( h =>
{
var asset = h.AssetAs<TextAsset>( );
if ( asset != null )
{
// 加载assembly对应的dll,会自动为它hook。一旦aot泛型函数的native函数不存在,用解释器版本代码
LoadImageErrorCode err = RuntimeApi.LoadMetadataForAOTAssembly( asset.bytes, HomologousImageMode.SuperSet );
Debug.Log( $"LoadMetadataForAOTAssembly:{h.Name}. mode:{HomologousImageMode.SuperSet} ret:{err}" );
if ( h.Name.EndsWith( "HotUpdate.dll.bytes" ) )
{
HotUpdateBytes = asset.bytes;
}
}
} );
//加载配置并启动游戏
Run( );
}
#endregion
HotService.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HotService
{
public static void Update( )
{
Log.Green( "已加载热更新程序集" );
}
}
Log
.cs
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using UnityEngine;
using Debug = UnityEngine.Debug;
/**
*
*
* Log Utils
*
* General log management
*
* anchor: ChenJC
*
* time: 2023/2/23
*
*/
public class Log
{
[Conditional( "ENABLE_LOG" )]
public static void Info( string msg, Object param = null )
{
if ( null == param )
{
Debug.Log( msg );
}
else
{
Debug.Log( msg, param );
}
}
[Conditional( "ENABLE_LOG" )]
public static void Info( object msg, Object param = null )
{
if ( null == param )
{
Debug.Log( msg );
}
else
{
Debug.Log( msg, param );
}
}
[Conditional( "ENABLE_LOG" )]
public static void Error( string msg, Object param = null )
{
if ( null == param )
{
Debug.LogError( msg );
}
else
{
Debug.LogError( msg, param );
}
}
[Conditional( "ENABLE_LOG" )]
public static void Error( object msg )
{
Debug.LogError( msg );
}
[Conditional( "ENABLE_LOG" )]
public static void Assert( bool condition, string msg, Object param = null )
{
if ( null == param )
{
Debug.Assert( condition, msg );
}
else
{
Debug.Assert( condition, msg, param );
}
}
[Conditional( "ENABLE_LOG" )]
public static void Warning( string msg, Object param = null )
{
if ( null == param )
{
Debug.LogWarning( msg );
}
else
{
Debug.LogWarning( msg, param );
}
}
[Conditional( "ENABLE_LOG" )]
public static void Light( string msg, Object param = null )
{
string content = $"<color=#ffff00>{msg}</color>";
if ( null == param )
{
Debug.Log( content );
}
else
{
Debug.Log( content, param );
}
}
[Conditional( "ENABLE_LOG" )]
public static void Green( string msg, Object param = null )
{
string content = $"<color=#00ff00>{msg}</color>";
if ( null == param )
{
Debug.Log( content );
}
else
{
Debug.Log( content, param );
}
}
//
//[Conditional( "ENABLE_LOG" )]
/// <summary>
/// 系统数据 任何情况下都必须输出 请不要随意调用这个方法 仅在重要的地方调用
/// </summary>
/// <param name="msg"></param>
/// <param name="param"></param>
public static void PINK( string msg, Object param )
{
string content = $"<color=#EF47D1>{msg}</color>";
Debug.Log( content, param );
}
/// <summary>
/// 系统数据 任何情况下都必须输出 请不要随意调用这个方法 仅在重要的地方调用
/// </summary>
/// <param name="msg"></param>
public static void PINK( string msg )
{
string content = $"<color=#EF47D1>♥ ♥ ♥ {msg}</color>";
Debug.Log( content );
}
}