using System; using System.Collections; using System.Linq; using System.Reflection; using AOT.Boot; using UnityEngine; using YooAsset; #if !UNITY_EDITOR using HybridCLR; #endif namespace AOT.HotUpdate { /// /// 加载热更程序集并调用稳定入口 HotUpdate.Entry.Start(BootContext)。 /// public static class HotUpdateLoader { const string EntryTypeName = "HotUpdate.Entry"; const string EntryMethodName = "Start"; public static IEnumerator LoadAndStart(BootContext ctx, BootSettings settings, Action onError) { #if UNITY_EDITOR if (settings.EditorDirectHotUpdate || ctx.Package == null) { var err = InvokeEntry(FindLoadedAssembly("HotUpdate.Runtime"), ctx); if (err != null) onError?.Invoke(err); yield break; } #endif if (ctx.Package == null) { onError?.Invoke("ResourcePackage 为空,无法加载热更 DLL"); yield break; } var handle = ctx.Package.LoadAssetAsync(settings.HotUpdateDllLocation); yield return handle; if (handle.Status != EOperationStatus.Succeeded) { onError?.Invoke($"加载热更 DLL 失败: {handle.Error}"); yield break; } var raw = handle.GetAssetObject(); if (raw == null) { onError?.Invoke("热更 DLL RawFileObject 为空"); yield break; } byte[] dllBytes = raw.GetBytes(); handle.Release(); if (dllBytes == null || dllBytes.Length < 64) { onError?.Invoke($"热更 DLL 字节异常 length={dllBytes?.Length ?? 0}"); yield break; } Debug.Log($"[HotUpdateLoader] RawFile loaded location={settings.HotUpdateDllLocation} bytes={dllBytes.Length}"); #if UNITY_EDITOR // 编辑器域内已加载同名程序集,不能重复 Assembly.Load;验证 RawFile 后走反射入口。 { var err = InvokeEntry(FindLoadedAssembly("HotUpdate.Runtime"), ctx); if (err != null) onError?.Invoke(err); yield break; } #else // AOT 补充元数据:后续由 HybridCLR Generate 产物批量加载。 // HybridCLR.RuntimeApi.LoadMetadataForAOTAssembly(metaBytes, HomologousImageMode.SuperSet); Assembly asm; try { asm = Assembly.Load(dllBytes); } catch (Exception e) { onError?.Invoke($"Assembly.Load 失败: {e.Message}"); yield break; } var invokeErr = InvokeEntry(asm, ctx); if (invokeErr != null) onError?.Invoke(invokeErr); #endif } static Assembly FindLoadedAssembly(string name) { return AppDomain.CurrentDomain.GetAssemblies() .FirstOrDefault(a => string.Equals(a.GetName().Name, name, StringComparison.Ordinal)); } static string InvokeEntry(Assembly asm, BootContext ctx) { if (asm == null) return "未找到热更程序集 HotUpdate.Runtime"; var type = asm.GetType(EntryTypeName, throwOnError: false); if (type == null) return $"未找到类型 {EntryTypeName}"; var method = type.GetMethod(EntryMethodName, BindingFlags.Public | BindingFlags.Static); if (method == null) return $"未找到方法 {EntryTypeName}.{EntryMethodName}"; try { method.Invoke(null, new object[] { ctx }); return null; } catch (Exception e) { var inner = e is TargetInvocationException tie && tie.InnerException != null ? tie.InnerException : e; return $"调用热更入口失败: {inner.Message}"; } } } }