using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using Cysharp.Threading.Tasks; #if !UNITY_WEBGL using HybridCLR; #endif using UnityEngine; using YooAsset; namespace Stary.Evo { public class HotFixDllState : AbstractFSMIStateAsync { public string[] PatchedAOTAssemblyList = { "System.Core.dll", "UnityEngine.CoreModule.dll", "mscorlib.dll", "DOTween.dll", "UniTask.dll", "YooAsset.dll", "com.stary.evo.runtime.dll", "com.staryevo.tools.runtime.dll", "mscorlib.dll" }; public HotFixDllState(IFsmSystemAsync system) : base(system) { } public override async UniTask OnEnterAsync(T param) { var domainConfig = param as DomainConfig; Debug.Log("UnityEvo:热更脚本..."); var package = YooAssets.GetPackage(AppConfig.PackageDomainName); // Editor环境下,HotUpdate.dll.bytes已经被自动加载,不需要加载,重复加载反而会出问题。 // 添加类型存在性检查 var fullClassName = $"{domainConfig.@namespace}.{domainConfig.className}"; #if EDITOR_SIMULATEMODE // Editor下无需加载,直接查找获得HotUpdate程序集 Assembly hotUpdateAss = System.AppDomain.CurrentDomain.GetAssemblies() .First(a => a.GetName().Name == $"HotUpdate_{AppConfig.PackageDomainName}"); #else var hotUpdateAssemblyName = $"HotUpdate_{AppConfig.PackageDomainName}"; var assemblyType = IsAssetLoaded(fullClassName); if (assemblyType != null) { Debug.Log($"UnityEvo:热更程序集:{hotUpdateAssemblyName} 已经加载过了"); FsmSystem.SetCurState(nameof(ResStartState), domainConfig, assemblyType); return; } //判断DLL是否下载成功 foreach (var aot in PatchedAOTAssemblyList) { var aotName = $"Android_{aot}"; var handle = package.LoadAssetAsync(aotName); await handle; if (handle.Status == EOperationStatus.Succeed) { var assetObj = handle.AssetObject as TextAsset; _sAssetDatas.Add(assetObj); Debug.Log($"UnityEvo:dll:{aotName} ,下载成功"); } else { Debug.Log($"UnityEvo:dll:{aotName} ,下载失败"); } } //先补元数据 LoadMetadataForAOTAssemblies(); // 加载热更dll var hotfixDll = package.LoadAssetAsync($"Android_HotUpdate_{AppConfig.PackageDomainName}.dll"); await hotfixDll; var hotfixPdb = package.LoadAssetAsync($"Android_HotUpdate_{AppConfig.PackageDomainName}.pdb"); await hotfixPdb; Assembly hotUpdateAss = null; if (hotfixDll.Status == EOperationStatus.Succeed) { Debug.Log("UnityEvo:hotfixDll读取成功!!"); var hotfixDllAsset = hotfixDll.AssetObject as TextAsset; if (hotfixPdb.Status == EOperationStatus.Succeed) { Debug.Log("UnityEvo:hotfixPdb:读取成功!!"); var hotfixPdbAsset = hotfixPdb.AssetObject as TextAsset; if (hotfixPdbAsset != null) { Debug.Log("UnityEvo:开始加载DLL和PDB..."); try { // 分步骤验证字节数组有效性 if (hotfixDllAsset.bytes == null || hotfixDllAsset.bytes.Length == 0) { Debug.LogError("UnityEvo:热更DLL字节数组为空!"); return; } if (hotfixPdbAsset.bytes == null || hotfixPdbAsset.bytes.Length == 0) { Debug.LogWarning("UnityEvo:PDB字节数组为空,尝试仅加载DLL..."); hotUpdateAss = Assembly.Load(hotfixDllAsset.bytes); } else { // 尝试加载DLL和PDB hotUpdateAss = Assembly.Load(hotfixDllAsset.bytes, hotfixPdbAsset.bytes); } Debug.Log( $"UnityEvo:Assembly加载成功,大小:DLL={hotfixDllAsset.bytes.Length} bytes, PDB={hotfixPdbAsset.bytes.Length} bytes"); } catch (Exception ex) { Debug.LogError($"UnityEvo:Assembly加载异常: {ex}"); // 尝试仅加载DLL作为备选方案 try { Debug.Log("UnityEvo:尝试仅加载DLL..."); hotUpdateAss = Assembly.Load(hotfixDllAsset.bytes); } catch (Exception ex2) { Debug.LogError($"UnityEvo:仅加载DLL也失败: {ex2}"); return; } } } else { Debug.LogError("UnityEvo:hotfixPdb: AssetObject为空!!"); } } else { if (hotfixDllAsset != null) try { Debug.Log("UnityEvo:开始加载DLL..."); // 分步骤验证字节数组有效性 if (hotfixDllAsset.bytes == null || hotfixDllAsset.bytes.Length == 0) { Debug.LogError("UnityEvo:热更DLL字节数组为空!"); return; } hotUpdateAss = Assembly.Load(hotfixDllAsset.bytes); Debug.Log( $"UnityEvo:Assembly加载成功,大小:DLL={hotfixDllAsset.bytes.Length} bytes"); } catch (Exception e) { Debug.LogError($"UnityEvo:Assembly加载异常: {e}"); } else Debug.LogError("UnityEvo:hotfixDll: AssetObject为空!!"); } } else { Debug.LogError($"UnityEvo:Android_HotUpdate_{AppConfig.PackageDomainName}.dll加载失败!!!!!"); } #endif Debug.Log($"UnityEvo:dll: Assembly.Load加载后是否为空:{hotUpdateAss == null}"); if (hotUpdateAss != null) { var type = hotUpdateAss.GetType(fullClassName); if (type == null) { Debug.LogError($"UnityEvo:热更类不存在!程序集: {hotUpdateAss.FullName}\n" + $"期望类名: {fullClassName}\n" + $"可用类型列表:{string.Join("\n", hotUpdateAss.GetTypes().Select(t => t.FullName))}"); return; } // 添加方法存在性检查 Debug.Log("UnityEvo:dll:开始MethodInfo检查!!"); var onEnterMethod = type.GetMethod("OnEnter"); var onEnterAsyncMethod = type.GetMethod("OnEnterAsync"); if (onEnterMethod == null || onEnterAsyncMethod == null) { Debug.LogError("UnityEvo:热更类进入方法缺失!\n" + $"存在方法:{string.Join(", ", type.GetMethods().Select(m => m.Name))}"); return; } Debug.Log("UnityEvo:dll:OnEnter检查成功!!"); var onExitMethod = type.GetMethod("OnExit"); var onExitAsyncMethod = type.GetMethod("OnExitAsync"); if (onExitMethod == null || onExitAsyncMethod == null) { Debug.LogError("UnityEvo:热更类退出方法缺失!\n" + $"存在方法:{string.Join(", ", type.GetMethods().Select(m => m.Name))}"); return; } Debug.Log("UnityEvo:dll:OnExit检查成功!!"); // AppConfig.SetDefaultHotfixType(type); FsmSystem.SetCurState(nameof(ResStartState), domainConfig, type); // // 创建热更类实例 // DomainBase hotfixInstance = AppConfig.HOTFIXBASE.AddComponent(type) as DomainBase; // // if (hotfixInstance == null) // { // Debug.LogError($"热更类{fullClassName}实例创建失败!必须继承MonoBehaviour"); // return; // } // // // // 原有调用逻辑修改为使用实例 // onEnterMethod.Invoke(hotfixInstance, new object[] { "" }); // 第一个参数改为实例对象 // onEnterAsyncMethod.Invoke(hotfixInstance, new object[] { "" }); } else { Debug.LogError("UnityEvo:热更类不存在!程序集: hotUpdateAss 不存在\n" + $"期望类名: {fullClassName}\n" + $"可用类型列表:{string.Join("\n", hotUpdateAss.GetTypes().Select(t => t.FullName))}"); } } private Type IsAssetLoaded(string assemblyName) { var assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (var assembly in assemblies) { var assemblyType = assembly.GetType(assemblyName); if (assemblyType != null) { Debug.Log("type:" + assemblyType); return assemblyType; } } return null; } #region 补充元数据 private readonly List _sAssetDatas = new(); /// /// 为aot assembly加载原始metadata, 这个代码放aot或者热更新都行。 /// 一旦加载后,如果AOT泛型函数对应native实现不存在,则自动替换为解释模式执行 /// private void LoadMetadataForAOTAssemblies() { #if !UNITY_WEBGL var mode = HomologousImageMode.SuperSet; // foreach (var aotDllName in AOTGenericReferences.PatchedAOTAssemblyList) foreach (var aotDll in _sAssetDatas) // var aotName = $"Android_{aotDllName}"; // // byte[] dllBytes = ReadBytesFromStreamingAssets(aotName); if (aotDll != null) { var dllBytes = aotDll.bytes; // 添加元数据加载校验 if (dllBytes == null || dllBytes.Length == 0) { Debug.LogError($"AOT元数据加载失败:{aotDll.name}"); continue; } var err = RuntimeApi.LoadMetadataForAOTAssembly(dllBytes, mode); Debug.Log($"UnityEvo:【补元】{aotDll.name} 加载结果: {err} 字节数: {dllBytes.Length}"); } #endif } #endregion } }