Files
5.24BuYu/Assets/MyGame/Editor/AOTMetadataStreamingAssetsSync.cs
T
2026-10-20 23:36:47 +08:00

93 lines
3.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.IO;
using HybridCLR;
using UnityEditor;
using UnityEditor.Build;
using UnityEditor.Build.Reporting;
using UnityEngine;
/// <summary>
/// 打包后把这次构建裁剪出来的 AOT 补充元数据 dll 刷进 StreamingAssets/HybridCLR/AOT。
///
/// 为什么要它:运行时 Launcher 会去 StreamingAssets/HybridCLR/AOT 读这些 dll 做"补充元数据"
/// (HybridCLR 的 LoadMetadataForAOTAssembly)。它们是构建过程裁剪出来的,HybridCLR 不会自动
/// 替你放进 StreamingAssets —— 漏了这一步,一旦改到 AOT 代码(GameFramework / Launcher /
/// Assembly-CSharp 这类),就会出现类型/函数缺失甚至黑屏。
///
/// 同步范围:只刷新 StreamingAssets/HybridCLR/AOT 里**已经存在**的那些 *.dll.bytes
/// (用它的文件名去裁剪产物目录里找同名 dll)。所以要在元数据列表里增减程序集,
/// 只需在 StreamingAssets/HybridCLR/AOT 下增删对应的 *.dll.bytes 文件即可。
///
/// ⚠ 时序:AOT dll 是"这次构建"才产出的,所以这一步只能在构建结束(Postprocess)后执行,
/// 也就是说这次构建用的仍是上一次同步的结果,**下一次构建**才会带上最新元数据。
/// 所以:改了 AOT 代码 → 连续打两次包(或打完第一次后手动再打一次)。
///
/// 想临时关掉自动同步,把 AutoSyncOnBuild 改成 false;也可以手动执行菜单
/// Tools/刷新AOT元数据到StreamingAssets。
/// </summary>
public class AOTMetadataStreamingAssetsSync : IPostprocessBuildWithReport
{
/// <summary>打包后是否自动同步 AOT 补充元数据</summary>
private const bool AutoSyncOnBuild = true;
/// <summary>运行时读取补充元数据的目录(相对项目根)</summary>
private const string StreamingAOTDir = "Assets/StreamingAssets/HybridCLR/AOT";
private const string BytesSuffix = ".bytes";
public int callbackOrder => 0;
public void OnPostprocessBuild(BuildReport report)
{
if (!AutoSyncOnBuild) return;
Sync(report.summary.platform);
}
[MenuItem("Tools/刷新AOT元数据到StreamingAssets")]
public static void SyncActive()
{
Sync(EditorUserBuildSettings.activeBuildTarget);
EditorUtility.DisplayDialog("AOT 元数据",
"已把最新的 AOT 补充元数据刷进 StreamingAssets/HybridCLR/AOT", "好");
}
/// <summary>按 StreamingAssets 里现有的 *.dll.bytes,从本次构建的裁剪产物目录刷新同名 dll。</summary>
private static void Sync(BuildTarget target)
{
string srcDir = SettingsUtil.GetAssembliesPostIl2CppStripDir(target);
if (!Directory.Exists(srcDir))
{
Debug.LogWarning($"[AOTMeta] 找不到裁剪后的 AOT dll 目录: {srcDir}(还没构建过?)");
return;
}
if (!Directory.Exists(StreamingAOTDir))
{
Debug.LogWarning($"[AOTMeta] 目录不存在: {StreamingAOTDir}");
return;
}
int copied = 0;
foreach (var dst in Directory.GetFiles(StreamingAOTDir))
{
if (!dst.EndsWith(".dll" + BytesSuffix)) continue;
// 磁盘文件形如 "GameFramework.dll.bytes" → 源文件名 "GameFramework.dll"
string dllName = Path.GetFileName(dst);
dllName = dllName.Substring(0, dllName.Length - BytesSuffix.Length);
string src = Path.Combine(srcDir, dllName);
if (!File.Exists(src))
{
Debug.LogWarning($"[AOTMeta] 裁剪产物里没有 {dllName},跳过({src})");
continue;
}
File.Copy(src, dst, true);
copied++;
}
AssetDatabase.Refresh();
Debug.Log($"[AOTMeta] 已同步 {copied} 个 AOT 补充元数据 dll 到 {StreamingAOTDir}(下次打包生效)");
}
}