2025-06-12 18:00:06 +08:00
using HybridCLR.Editor.UnityBinFileReader ;
using System ;
2025-03-31 14:55:24 +08:00
using System.Collections.Generic ;
using System.IO ;
using System.Linq ;
using System.Text ;
using System.Threading.Tasks ;
using UnityEditor ;
using UnityEditor.Android ;
using UnityEditor.Build ;
using UnityEditor.Build.Reporting ;
using UnityEditor.UnityLinker ;
using UnityEngine ;
2025-06-12 18:00:06 +08:00
using UnityFS ;
#if ! UNITY_2023_1_OR_NEWER
using UnityEditor.Il2Cpp ;
#endif
2025-03-31 14:55:24 +08:00
namespace HybridCLR.Editor.BuildProcessors
{
public class PatchScriptingAssemblyList :
#if UNITY_ANDROID
IPostGenerateGradleAndroidProject ,
2025-06-12 18:00:06 +08:00
#elif UNITY_OPENHARMONY
UnityEditor . OpenHarmony . IPostGenerateOpenHarmonyProject ,
2025-03-31 14:55:24 +08:00
#endif
IPostprocessBuildWithReport
#if ! UNITY_2021_1_OR_NEWER && UNITY_WEBGL
, IIl2CppProcessor
#endif
#if UNITY_PS5
, IUnityLinkerProcessor
#endif
{
public int callbackOrder => 0 ;
public void OnPostGenerateGradleAndroidProject ( string path )
{
// 如果直接打包apk,没有机会在PostprocessBuild中修改ScriptingAssemblies.json。
// 因此需要在这个时机处理
// Unity有bug,偶然情况下会传入apk的路径,导致替换失败
if ( Directory . Exists ( path ))
{
PathScriptingAssembilesFile ( path );
}
else
{
PathScriptingAssembilesFile ( $"{SettingsUtil.ProjectDir}/Library" );
}
}
2025-06-12 18:00:06 +08:00
#if UNITY_OPENHARMONY
public void OnPostGenerateOpenHarmonyProject ( string path )
{
OnPostGenerateGradleAndroidProject ( path );
}
#endif
2025-03-31 14:55:24 +08:00
public void OnPostprocessBuild ( BuildReport report )
{
// 如果target为Android,由于已经在OnPostGenerateGradelAndroidProject中处理过,
// 这里不再重复处理
2025-06-12 18:00:06 +08:00
#if ! UNITY_ANDROID && ! UNITY_WEBGL && ! UNITY_OPENHARMONY
2025-03-31 14:55:24 +08:00
PathScriptingAssembilesFile ( report . summary . outputPath );
#endif
}
#if UNITY_PS5
/// <summary>
/// 打包模式如果是 Package 需要在这个阶段提前处理 .json , PC Hosted 和 GP5 模式不受影响
/// </summary>
public string GenerateAdditionalLinkXmlFile ( UnityEditor . Build . Reporting . BuildReport report , UnityEditor . UnityLinker . UnityLinkerBuildPipelineData data )
{
string path = $"{SettingsUtil.ProjectDir}/Library/PlayerDataCache/PS5/Data" ;
PathScriptingAssembilesFile ( path );
return null ;
}
#endif
public void PathScriptingAssembilesFile ( string path )
{
if (! SettingsUtil . Enable )
{
Debug . Log ( $"[PatchScriptingAssemblyList] disabled" );
return ;
}
Debug . Log ( $"[PatchScriptingAssemblyList]. path:{path}" );
if (! Directory . Exists ( path ))
{
path = Path . GetDirectoryName ( path );
Debug . Log ( $"[PatchScriptingAssemblyList] get path parent:{path}" );
}
2025-06-12 18:00:06 +08:00
#if UNITY_2020_1_OR_NEWER
2025-03-31 14:55:24 +08:00
AddHotFixAssembliesToScriptingAssembliesJson ( path );
2025-06-12 18:00:06 +08:00
#else
AddHotFixAssembliesToBinFile ( path );
#endif
2025-03-31 14:55:24 +08:00
}
private void AddHotFixAssembliesToScriptingAssembliesJson ( string path )
{
Debug . Log ( $"[PatchScriptingAssemblyList]. path:{path}" );
/*
* ScriptingAssemblies.json 文件中记录了所有的dll名称,此列表在游戏启动时自动加载,
* 不在此列表中的dll在资源反序列化时无法被找到其类型
* 因此 OnFilterAssemblies 中移除的条目需要再加回来
*/
string [] jsonFiles = Directory . GetFiles ( path , SettingsUtil . ScriptingAssembliesJsonFile , SearchOption . AllDirectories );
if ( jsonFiles . Length == 0 )
{
Debug . LogWarning ( $"can not find file {SettingsUtil.ScriptingAssembliesJsonFile}" );
return ;
}
foreach ( string file in jsonFiles )
{
var patcher = new ScriptingAssembliesJsonPatcher ();
patcher . Load ( file );
patcher . AddScriptingAssemblies ( SettingsUtil . HotUpdateAssemblyFilesIncludePreserved );
patcher . Save ( file );
}
}
2025-06-12 18:00:06 +08:00
private void AddHotFixAssembliesToBinFile ( string path )
{
#if UNITY_STANDALONE_OSX
path = Path . GetDirectoryName ( path );
#endif
if ( AddHotFixAssembliesToGlobalgamemanagers ( path ))
{
return ;
}
if ( AddHotFixAssembliesTodataunity3d ( path ))
{
return ;
}
Debug . LogError ( $"[PatchScriptingAssemblyList] can not find file '{SettingsUtil.GlobalgamemanagersBinFile}' or '{SettingsUtil.Dataunity3dBinFile}' in '{path}'" );
}
private bool AddHotFixAssembliesToGlobalgamemanagers ( string path )
{
string [] binFiles = Directory . GetFiles ( path , SettingsUtil . GlobalgamemanagersBinFile , SearchOption . AllDirectories );
if ( binFiles . Length == 0 )
{
return false ;
}
foreach ( string binPath in binFiles )
{
var binFile = new UnityBinFile ();
binFile . Load ( binPath );
binFile . AddScriptingAssemblies ( SettingsUtil . HotUpdateAssemblyFilesIncludePreserved );
binFile . Save ( binPath );
Debug . Log ( $"[PatchScriptingAssemblyList] patch {binPath}" );
}
return true ;
}
private bool AddHotFixAssembliesTodataunity3d ( string path )
{
string [] binFiles = Directory . GetFiles ( path , SettingsUtil . Dataunity3dBinFile , SearchOption . AllDirectories );
if ( binFiles . Length == 0 )
{
return false ;
}
foreach ( string binPath in binFiles )
{
var patcher = new Dataunity3dPatcher ();
patcher . ApplyPatch ( binPath , SettingsUtil . HotUpdateAssemblyFilesIncludePreserved );
Debug . Log ( $"[PatchScriptingAssemblyList] patch {binPath}" );
}
return true ;
}
2025-03-31 14:55:24 +08:00
2025-06-12 18:00:06 +08:00
#if UNITY_WEBGL && ! UNITY_2022_3_OR_NEWER
2025-03-31 14:55:24 +08:00
public void OnBeforeConvertRun ( BuildReport report , Il2CppBuildPipelineData data )
{
PathScriptingAssembilesFile ( $"{SettingsUtil.ProjectDir}/Temp/StagingArea/Data" );
}
#endif
}
}