69 lines
2.9 KiB
C#
69 lines
2.9 KiB
C#
using System;
|
||
using System.IO;
|
||
using System.Reflection;
|
||
using UnityEngine;
|
||
using XWorld.Framework;
|
||
|
||
namespace XGame.MiniGame
|
||
{
|
||
// 从代码 AB(manifest.CodeAb)取出 Core/Client 热更 DLL 字节并加载,反射出 IGameClient 入口工厂
|
||
public sealed class MiniGameAssemblyLoader
|
||
{
|
||
public Func<IGameClient> CreateClient { get; private set; }
|
||
public string Error { get; private set; }
|
||
|
||
// localDir: MiniGameDownloader.LocalDir;manifest: 解析好的 game.json
|
||
public bool Load(string localDir, MiniGameManifest manifest)
|
||
{
|
||
string abPath = localDir + manifest.CodeAb;
|
||
if (!File.Exists(abPath))
|
||
{ Error = $"缺少代码 AB: {abPath}(需要 codeAb 统一 AB 格式,旧 .bytes 包不再支持)"; return false; }
|
||
|
||
AssetBundle ab = null;
|
||
try
|
||
{
|
||
ab = MiniGamePlatform.LoadAssetBundle(abPath);
|
||
if (ab == null) { Error = "代码 AB 打开失败: " + abPath; return false; }
|
||
|
||
byte[] coreBytes = LoadDllBytes(ab, manifest.CoreDll);
|
||
byte[] clientBytes = LoadDllBytes(ab, manifest.ClientDll);
|
||
if (coreBytes == null || clientBytes == null)
|
||
{
|
||
Error = $"代码 AB 内缺少 {manifest.CoreDll}/{manifest.ClientDll} 的 .bytes(AB 内资产: {string.Join(", ", ab.GetAllAssetNames())})";
|
||
return false;
|
||
}
|
||
|
||
// Core 先于 Client 加载(Client 依赖 Core)
|
||
Assembly.Load(coreBytes);
|
||
Assembly clientAsm = Assembly.Load(clientBytes);
|
||
|
||
Type entry = clientAsm.GetType(manifest.ClientEntryType);
|
||
if (entry == null) { Error = "找不到入口类型 " + manifest.ClientEntryType; return false; }
|
||
if (!typeof(IGameClient).IsAssignableFrom(entry))
|
||
{ Error = manifest.ClientEntryType + " 未实现 IGameClient"; return false; }
|
||
|
||
CreateClient = () => (IGameClient)Activator.CreateInstance(entry);
|
||
return true;
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Error = "加载小游戏程序集失败: " + e;
|
||
Debug.LogError("[MiniGameAssemblyLoader] " + Error);
|
||
return false;
|
||
}
|
||
finally
|
||
{
|
||
// DLL 字节已复制进托管内存,AB 本体可卸;false=不销毁已取出的对象
|
||
if (ab != null) ab.Unload(false);
|
||
}
|
||
}
|
||
|
||
// "X.dll.bytes" 导入后资产名为 "X.dll"(Unity 剥最后一个扩展名);两种写法都试
|
||
private static byte[] LoadDllBytes(AssetBundle ab, string dllName)
|
||
{
|
||
TextAsset ta = ab.LoadAsset<TextAsset>(dllName) ?? ab.LoadAsset<TextAsset>(dllName + ".bytes");
|
||
return ta != null ? ta.bytes : null;
|
||
}
|
||
}
|
||
}
|