tanghai 3 rokov pred
rodič
commit
606edcd1a1
100 zmenil súbory, kde vykonal 4952 pridanie a 10 odobranie
  1. 10 1
      .gitignore
  2. 54 1
      Unity/Assets/Plugins/CommandLine.dll.meta
  3. 1 1
      Unity/Assets/Plugins/MongoDB/System.Buffers.dll.meta
  4. 54 1
      Unity/Assets/Plugins/NLog.dll.meta
  5. 6 2
      Unity/Assets/Scripts/Core/Module/Config/ConfigSingleton.cs
  6. 6 2
      Unity/Assets/Scripts/Core/Singleton/Singleton.cs
  7. 14 1
      Unity/Assets/Scripts/Editor/BuildEditor/BuildEditor.cs
  8. 1 0
      Unity/Assets/Scripts/Editor/BuildEditor/BuildHelper.cs
  9. 8 0
      Unity/Assets/Scripts/Editor/HybridCLR.meta
  10. 124 0
      Unity/Assets/Scripts/Editor/HybridCLR/AssetBundleBuildHelper.cs
  11. 11 0
      Unity/Assets/Scripts/Editor/HybridCLR/AssetBundleBuildHelper.cs.meta
  12. 82 0
      Unity/Assets/Scripts/Editor/HybridCLR/BuildConfig.cs
  13. 11 0
      Unity/Assets/Scripts/Editor/HybridCLR/BuildConfig.cs.meta
  14. 45 0
      Unity/Assets/Scripts/Editor/HybridCLR/BuildConfig_Custom.cs
  15. 11 0
      Unity/Assets/Scripts/Editor/HybridCLR/BuildConfig_Custom.cs.meta
  16. 192 0
      Unity/Assets/Scripts/Editor/HybridCLR/BuildPlayerHelper.cs
  17. 11 0
      Unity/Assets/Scripts/Editor/HybridCLR/BuildPlayerHelper.cs.meta
  18. 8 0
      Unity/Assets/Scripts/Editor/HybridCLR/BuildProcessors.meta
  19. 84 0
      Unity/Assets/Scripts/Editor/HybridCLR/BuildProcessors/BPCopyStrippedAOTAssemblies.cs
  20. 11 0
      Unity/Assets/Scripts/Editor/HybridCLR/BuildProcessors/BPCopyStrippedAOTAssemblies.cs.meta
  21. 47 0
      Unity/Assets/Scripts/Editor/HybridCLR/BuildProcessors/BPFilterHotFixAssemblies.cs
  22. 11 0
      Unity/Assets/Scripts/Editor/HybridCLR/BuildProcessors/BPFilterHotFixAssemblies.cs.meta
  23. 148 0
      Unity/Assets/Scripts/Editor/HybridCLR/BuildProcessors/BPPatchScriptAssembliesJson.cs
  24. 11 0
      Unity/Assets/Scripts/Editor/HybridCLR/BuildProcessors/BPPatchScriptAssembliesJson.cs.meta
  25. 8 0
      Unity/Assets/Scripts/Editor/HybridCLR/BuildProcessors/UnityBinFileReader.meta
  26. 107 0
      Unity/Assets/Scripts/Editor/HybridCLR/BuildProcessors/UnityBinFileReader/UnityBinFile.cs
  27. 11 0
      Unity/Assets/Scripts/Editor/HybridCLR/BuildProcessors/UnityBinFileReader/UnityBinFile.cs.meta
  28. 397 0
      Unity/Assets/Scripts/Editor/HybridCLR/BuildProcessors/UnityBinFileReader/UnityBinFileDefines.cs
  29. 11 0
      Unity/Assets/Scripts/Editor/HybridCLR/BuildProcessors/UnityBinFileReader/UnityBinFileDefines.cs.meta
  30. 78 0
      Unity/Assets/Scripts/Editor/HybridCLR/BuildProcessors/UnityBinFileReader/UnityBinUtils.cs
  31. 11 0
      Unity/Assets/Scripts/Editor/HybridCLR/BuildProcessors/UnityBinFileReader/UnityBinUtils.cs.meta
  32. 65 0
      Unity/Assets/Scripts/Editor/HybridCLR/CompileDllHelper.cs
  33. 11 0
      Unity/Assets/Scripts/Editor/HybridCLR/CompileDllHelper.cs.meta
  34. 8 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators.meta
  35. 13 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/ConstStrings.cs
  36. 11 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/ConstStrings.cs.meta
  37. 40 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/FileRegionReplace.cs
  38. 11 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/FileRegionReplace.cs.meta
  39. 71 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/GeneratorConfig.cs
  40. 11 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/GeneratorConfig.cs.meta
  41. 8 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge.meta
  42. 28 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/IPlatformAdaptor.cs
  43. 11 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/IPlatformAdaptor.cs.meta
  44. 353 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/MethodBridgeGenerator.cs
  45. 11 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/MethodBridgeGenerator.cs.meta
  46. 156 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/MethodBridgeSig.cs
  47. 11 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/MethodBridgeSig.cs.meta
  48. 44 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/ParamInfo.cs
  49. 11 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/ParamInfo.cs.meta
  50. 38 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/ParamOrReturnType.cs
  51. 11 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/ParamOrReturnType.cs.meta
  52. 9 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/PlatformABI.cs
  53. 11 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/PlatformABI.cs.meta
  54. 160 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/PlatformAdaptorBase.cs
  55. 11 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/PlatformAdaptorBase.cs.meta
  56. 208 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/PlatformAdaptor_Arm64.cs
  57. 11 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/PlatformAdaptor_Arm64.cs.meta
  58. 96 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/PlatformAdaptor_Universal32.cs
  59. 11 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/PlatformAdaptor_Universal32.cs.meta
  60. 189 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/PlatformAdaptor_Universal64.cs
  61. 11 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/PlatformAdaptor_Universal64.cs.meta
  62. 19 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/SignatureProviderAttribute.cs
  63. 11 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/SignatureProviderAttribute.cs.meta
  64. 132 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/TypeInfo.cs
  65. 11 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/TypeInfo.cs.meta
  66. 148 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/ValueTypeSizeAligmentCalculator.cs
  67. 11 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/ValueTypeSizeAligmentCalculator.cs.meta
  68. 38 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/TemplateUtil.cs
  69. 11 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/TemplateUtil.cs.meta
  70. 8 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/Templates.meta
  71. 22 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/Templates/MethodBridge_Arm64.cpp
  72. 27 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/Templates/MethodBridge_Arm64.cpp.meta
  73. 22 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/Templates/MethodBridge_Universal32.cpp
  74. 27 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/Templates/MethodBridge_Universal32.cpp.meta
  75. 22 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/Templates/MethodBridge_Universal64.cpp
  76. 27 0
      Unity/Assets/Scripts/Editor/HybridCLR/Generators/Templates/MethodBridge_Universal64.cpp.meta
  77. 8 0
      Unity/Assets/Scripts/Editor/HybridCLR/Installer.meta
  78. 295 0
      Unity/Assets/Scripts/Editor/HybridCLR/Installer/InstallerController.cs
  79. 11 0
      Unity/Assets/Scripts/Editor/HybridCLR/Installer/InstallerController.cs.meta
  80. 116 0
      Unity/Assets/Scripts/Editor/HybridCLR/Installer/InstallerWindow.cs
  81. 11 0
      Unity/Assets/Scripts/Editor/HybridCLR/Installer/InstallerWindow.cs.meta
  82. 131 0
      Unity/Assets/Scripts/Editor/HybridCLR/MethodBridgeHelper.cs
  83. 11 0
      Unity/Assets/Scripts/Editor/HybridCLR/MethodBridgeHelper.cs.meta
  84. 19 0
      Unity/Assets/Scripts/Mono/CodeLoader.cs
  85. 8 0
      Unity/Assets/Scripts/Mono/HybridCLR.meta
  86. 272 0
      Unity/Assets/Scripts/Mono/HybridCLR/RefTypes.cs
  87. 11 0
      Unity/Assets/Scripts/Mono/HybridCLR/RefTypes.cs.meta
  88. 36 0
      Unity/Assets/Scripts/Mono/HybridCLR/RuntimeApi.cs
  89. 11 0
      Unity/Assets/Scripts/Mono/HybridCLR/RuntimeApi.cs.meta
  90. 12 1
      Unity/Assets/link.xml
  91. BIN
      Unity/HybridCLRData/ModifiedUnityAssemblies/2019.4.40/Unity.IL2CPP.dll
  92. BIN
      Unity/HybridCLRData/ModifiedUnityAssemblies/2021.3.1/UnityEditor.CoreModule-Mac.dll
  93. BIN
      Unity/HybridCLRData/ModifiedUnityAssemblies/2021.3.1/UnityEditor.CoreModule-Win.dll
  94. BIN
      Unity/HybridCLRData/ModifiedUnityAssemblies/2021.3.6/UnityEditor.CoreModule-Mac.dll
  95. BIN
      Unity/HybridCLRData/ModifiedUnityAssemblies/2021.3.6/UnityEditor.CoreModule-Win.dll
  96. 22 0
      Unity/HybridCLRData/README.md
  97. 88 0
      Unity/HybridCLRData/iOSBuild/CMakeLists.txt
  98. 19 0
      Unity/HybridCLRData/iOSBuild/build_libil2cpp.sh
  99. 47 0
      Unity/HybridCLRData/iOSBuild/external/CMakeLists.txt
  100. 64 0
      Unity/HybridCLRData/iOSBuild/gen_lump.sh

+ 10 - 1
.gitignore

@@ -69,4 +69,13 @@ Server/.DS_Store
 /Unity/UserSettings
 /Unity/Unity.Codes.csproj
 /Unity/Unity.Ignore.csproj
-Publish/
+Publish/
+/Unity/HybridCLRData/LocalIl2CppData
+/Unity/HybridCLRData/hybridclr_repo
+/Unity/HybridCLRData/il2cpp_plus_repo
+/Unity/HybridCLRData/AssembliesPostIl2CppStrip
+/Unity/HybridCLRData/HotFixDlls
+/Unity/Assets/Bundles/AssetBundleOutput.meta
+/Unity/Assets/Bundles/AssetBundleOutput
+/Unity/Assets/Bundles/AssetBundleSourceData
+/Unity/Assets/Bundles/AssetBundleSourceData.meta

+ 54 - 1
Unity/Assets/Plugins/CommandLine.dll.meta

@@ -11,6 +11,24 @@ PluginImporter:
   isExplicitlyReferenced: 0
   validateReferences: 1
   platformData:
+  - first:
+      : Any
+    second:
+      enabled: 0
+      settings:
+        Exclude Android: 0
+        Exclude Editor: 0
+        Exclude Linux64: 0
+        Exclude OSXUniversal: 0
+        Exclude Win: 0
+        Exclude Win64: 0
+        Exclude iOS: 0
+  - first:
+      Android: Android
+    second:
+      enabled: 1
+      settings:
+        CPU: ARMv7
   - first:
       Any: 
     second:
@@ -19,15 +37,50 @@ PluginImporter:
   - first:
       Editor: Editor
     second:
-      enabled: 0
+      enabled: 1
       settings:
+        CPU: AnyCPU
         DefaultValueInitialized: true
+        OS: AnyOS
+  - first:
+      Standalone: Linux64
+    second:
+      enabled: 1
+      settings:
+        CPU: x86_64
+  - first:
+      Standalone: OSXUniversal
+    second:
+      enabled: 1
+      settings:
+        CPU: None
+  - first:
+      Standalone: Win
+    second:
+      enabled: 1
+      settings:
+        CPU: x86
+  - first:
+      Standalone: Win64
+    second:
+      enabled: 1
+      settings:
+        CPU: x86_64
   - first:
       Windows Store Apps: WindowsStoreApps
     second:
       enabled: 0
       settings:
         CPU: AnyCPU
+  - first:
+      iPhone: iOS
+    second:
+      enabled: 1
+      settings:
+        AddToEmbeddedBinaries: false
+        CPU: AnyCPU
+        CompileFlags: 
+        FrameworkDependencies: 
   userData: 
   assetBundleName: 
   assetBundleVariant: 

+ 1 - 1
Unity/Assets/Plugins/MongoDB/System.Buffers.dll.meta

@@ -47,7 +47,7 @@ PluginImporter:
     second:
       enabled: 1
       settings:
-        CPU: x86_64
+        CPU: AnyCPU
   - first:
       Standalone: OSXUniversal
     second:

+ 54 - 1
Unity/Assets/Plugins/NLog.dll.meta

@@ -11,6 +11,24 @@ PluginImporter:
   isExplicitlyReferenced: 0
   validateReferences: 1
   platformData:
+  - first:
+      : Any
+    second:
+      enabled: 0
+      settings:
+        Exclude Android: 0
+        Exclude Editor: 0
+        Exclude Linux64: 0
+        Exclude OSXUniversal: 0
+        Exclude Win: 0
+        Exclude Win64: 0
+        Exclude iOS: 0
+  - first:
+      Android: Android
+    second:
+      enabled: 1
+      settings:
+        CPU: ARMv7
   - first:
       Any: 
     second:
@@ -19,15 +37,50 @@ PluginImporter:
   - first:
       Editor: Editor
     second:
-      enabled: 0
+      enabled: 1
       settings:
+        CPU: AnyCPU
         DefaultValueInitialized: true
+        OS: AnyOS
+  - first:
+      Standalone: Linux64
+    second:
+      enabled: 1
+      settings:
+        CPU: None
+  - first:
+      Standalone: OSXUniversal
+    second:
+      enabled: 1
+      settings:
+        CPU: None
+  - first:
+      Standalone: Win
+    second:
+      enabled: 1
+      settings:
+        CPU: None
+  - first:
+      Standalone: Win64
+    second:
+      enabled: 1
+      settings:
+        CPU: None
   - first:
       Windows Store Apps: WindowsStoreApps
     second:
       enabled: 0
       settings:
         CPU: AnyCPU
+  - first:
+      iPhone: iOS
+    second:
+      enabled: 1
+      settings:
+        AddToEmbeddedBinaries: false
+        CPU: AnyCPU
+        CompileFlags: 
+        FrameworkDependencies: 
   userData: 
   assetBundleName: 
   assetBundleVariant: 

+ 6 - 2
Unity/Assets/Scripts/Core/Module/Config/ConfigSingleton.cs

@@ -2,7 +2,7 @@
 
 namespace ET
 {
-    public abstract class ConfigSingleton<T>: DisposeObject, ISingleton where T: ConfigSingleton<T>, new()
+    public abstract class ConfigSingleton<T>: ProtoObject, ISingleton where T: ConfigSingleton<T>, new()
     {
         [StaticField]
         private static T instance;
@@ -36,7 +36,11 @@ namespace ET
             throw new NotImplementedException();
         }
 
-        public virtual void AfterEndInit()
+        public override void AfterEndInit()
+        {
+        }
+
+        public virtual void Dispose()
         {
         }
     }

+ 6 - 2
Unity/Assets/Scripts/Core/Singleton/Singleton.cs

@@ -2,14 +2,14 @@
 
 namespace ET
 {
-    public interface ISingleton
+    public interface ISingleton: IDisposable
     {
         void Register();
         void Destroy();
         bool IsDisposed();
     }
     
-    public abstract class Singleton<T>: DisposeObject, ISingleton where T: Singleton<T>, new()
+    public abstract class Singleton<T>: ISingleton where T: Singleton<T>, new()
     {
         private bool isDisposed;
         [StaticField]
@@ -49,5 +49,9 @@ namespace ET
         {
             return this.isDisposed;
         }
+
+        public virtual void Dispose()
+        {
+        }
     }
 }

+ 14 - 1
Unity/Assets/Scripts/Editor/BuildEditor/BuildEditor.cs

@@ -3,7 +3,7 @@ using System.Collections.Generic;
 using System.Diagnostics;
 using System.IO;
 using System.Linq;
-
+using HybridCLR.Editor;
 using UnityEditor;
 using UnityEditor.Compilation;
 using UnityEngine;
@@ -85,6 +85,19 @@ namespace ET
 			}
 
 			GUILayout.Space(5);
+
+			if (GUILayout.Button("BuildWolongMetaDll"))
+			{
+				const string wolongMetaDir = "Assets/Bundles/AssetBundleSourceData";
+				if (Directory.Exists(wolongMetaDir))
+				{
+					Directory.Delete(wolongMetaDir, true);
+				}
+				AssetBundleBuildHelper.BuildSceneAssetBundleActiveBuildTarget();
+				AssetImporter assetImporter = AssetImporter.GetAtPath(wolongMetaDir);
+				assetImporter.assetBundleName = "assetbundlesourcedata.unity3d";
+				AssetDatabase.SaveAssets();
+			}
 			
 			if (GUILayout.Button("BuildPackage"))
 			{

+ 1 - 0
Unity/Assets/Scripts/Editor/BuildEditor/BuildHelper.cs

@@ -1,5 +1,6 @@
 using System.IO;
 using System.Linq;
+using HybridCLR.Editor;
 using UnityEditor;
 using UnityEditor.Build;
 using UnityEngine;

+ 8 - 0
Unity/Assets/Scripts/Editor/HybridCLR.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 95bc250a1ce8e9d488de0a911e315301
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 124 - 0
Unity/Assets/Scripts/Editor/HybridCLR/AssetBundleBuildHelper.cs

@@ -0,0 +1,124 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using UnityEditor;
+using UnityEngine;
+
+namespace HybridCLR.Editor
+{
+    public static class AssetBundleBuildHelper
+    {
+
+        public static string ToRelativeAssetPath(string s)
+        {
+            return s.Substring(s.IndexOf("Assets/"));
+        }
+
+        /// <summary>
+        /// 将HotFix.dll和HotUpdatePrefab.prefab打入common包.
+        /// 将HotUpdateScene.unity打入scene包.
+        /// </summary>
+        /// <param name="tempDir"></param>
+        /// <param name="outputDir"></param>
+        /// <param name="target"></param>
+        private static void BuildAssetBundles(string tempDir, string outputDir, BuildTarget target)
+        {
+            Directory.CreateDirectory(tempDir);
+            Directory.CreateDirectory(outputDir);
+            CompileDllHelper.CompileDll(target);
+
+
+            List<string> notSceneAssets = new List<string>();
+
+            string hotfixDllSrcDir = BuildConfig.GetHotFixDllsOutputDirByTarget(target);
+            foreach (var dll in BuildConfig.HotUpdateAssemblies)
+            {
+                string dllPath = $"{hotfixDllSrcDir}/{dll}";
+                string dllBytesPath = $"{tempDir}/{dll}.bytes";
+                File.Copy(dllPath, dllBytesPath, true);
+                notSceneAssets.Add(dllBytesPath);
+            }
+
+            string aotDllDir = BuildConfig.GetAssembliesPostIl2CppStripDir(target);
+            foreach (var dll in BuildConfig.AOTMetaAssemblies)
+            {
+                string dllPath = $"{aotDllDir}/{dll}";
+                if (!File.Exists(dllPath))
+                {
+                    Debug.LogError($"ab中添加AOT补充元数据dll:{dllPath} 时发生错误,文件不存在。裁剪后的AOT dll在BuildPlayer时才能生成,因此需要你先构建一次游戏App后再打包。");
+                    continue;
+                }
+                string dllBytesPath = $"{tempDir}/{dll}.bytes";
+                File.Copy(dllPath, dllBytesPath, true);
+                notSceneAssets.Add(dllBytesPath);
+            }
+
+            string testPrefab = $"{Application.dataPath}/Prefabs/HotUpdatePrefab.prefab";
+            notSceneAssets.Add(testPrefab);
+            AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
+
+            List<AssetBundleBuild> abs = new List<AssetBundleBuild>();
+            AssetBundleBuild notSceneAb = new AssetBundleBuild
+            {
+                assetBundleName = "common",
+                assetNames = notSceneAssets.Select(s => ToRelativeAssetPath(s)).ToArray(),
+            };
+            abs.Add(notSceneAb);
+
+            UnityEditor.BuildPipeline.BuildAssetBundles(outputDir, abs.ToArray(), BuildAssetBundleOptions.None, target);
+
+            AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
+
+            string streamingAssetPathDst = $"{Application.streamingAssetsPath}";
+            Directory.CreateDirectory(streamingAssetPathDst);
+
+            foreach (var ab in abs)
+            {
+                AssetDatabase.CopyAsset(ToRelativeAssetPath($"{outputDir}/{ab.assetBundleName}"),
+                    ToRelativeAssetPath($"{streamingAssetPathDst}/{ab.assetBundleName}"));
+            }
+        }
+
+        public static void BuildAssetBundleByTarget(BuildTarget target)
+        {
+            BuildAssetBundles(BuildConfig.GetAssetBundleTempDirByTarget(target), BuildConfig.GetAssetBundleOutputDirByTarget(target), target);
+        }
+
+        //[MenuItem("HybridCLR/BuildBundles/ActiveBuildTarget")]
+        public static void BuildSceneAssetBundleActiveBuildTarget()
+        {
+            BuildAssetBundleByTarget(EditorUserBuildSettings.activeBuildTarget);
+        }
+
+        //[MenuItem("HybridCLR/BuildBundles/Win64")]
+        public static void BuildSceneAssetBundleWin64()
+        {
+            var target = BuildTarget.StandaloneWindows64;
+            BuildAssetBundleByTarget(target);
+        }
+
+        //[MenuItem("HybridCLR/BuildBundles/Win32")]
+        public static void BuildSceneAssetBundleWin32()
+        {
+            var target = BuildTarget.StandaloneWindows;
+            BuildAssetBundleByTarget(target);
+        }
+
+        //[MenuItem("HybridCLR/BuildBundles/Android")]
+        public static void BuildSceneAssetBundleAndroid()
+        {
+            var target = BuildTarget.Android;
+            BuildAssetBundleByTarget(target);
+        }
+
+        //[MenuItem("HybridCLR/BuildBundles/IOS")]
+        public static void BuildSceneAssetBundleIOS()
+        {
+            var target = BuildTarget.iOS;
+            BuildAssetBundleByTarget(target);
+        }
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/Editor/HybridCLR/AssetBundleBuildHelper.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 1a8357532218e6f49a9bb9401382d6d4
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 82 - 0
Unity/Assets/Scripts/Editor/HybridCLR/BuildConfig.cs

@@ -0,0 +1,82 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using UnityEditor;
+using UnityEngine;
+
+namespace HybridCLR.Editor
+{
+    public static partial class BuildConfig
+    {
+#if !UNITY_IOS
+        [InitializeOnLoadMethod]
+        private static void Setup()
+        {
+            ///
+            /// unity允许使用UNITY_IL2CPP_PATH环境变量指定il2cpp的位置,因此我们不再直接修改安装位置的il2cpp,
+            /// 而是在本地目录
+            ///
+            var installerController = new Installer.InstallerController();
+            var localIl2cppDir = LocalIl2CppDir;
+            if (!installerController.HasInstalledHybridCLR())
+            {
+                if (installerController.CheckValidIl2CppInstallDirectory(installerController.Il2CppBranch, installerController.Il2CppInstallDirectory) == Installer.InstallErrorCode.Ok)
+                {
+                    installerController.InitHybridCLR(installerController.Il2CppBranch, installerController.Il2CppInstallDirectory);
+                }
+                if (!installerController.HasInstalledHybridCLR())
+                {
+                    Debug.LogError($"未安装本地il2cpp。请在菜单 HybridCLR/Installer 中执行安装");
+                }
+            }
+            Environment.SetEnvironmentVariable("UNITY_IL2CPP_PATH", localIl2cppDir);
+        }
+#endif
+
+        public static string ProjectDir => Directory.GetParent(Application.dataPath).ToString();
+
+        public static string ScriptingAssembliesJsonFile { get; } = "ScriptingAssemblies.json";
+
+        public static string HybridCLRBuildCacheDir => Application.dataPath + "/Bundles";
+
+        public static string HotFixDllsOutputDir => $"{HybridCLRDataDir}/HotFixDlls";
+
+        public static string AssetBundleOutputDir => $"{HybridCLRBuildCacheDir}/AssetBundleOutput";
+
+        public static string AssetBundleSourceDataTempDir => $"{HybridCLRBuildCacheDir}/AssetBundleSourceData";
+
+        public static string HybridCLRDataDir { get; } = $"{ProjectDir}/HybridCLRData";
+
+        public static string AssembliesPostIl2CppStripDir => $"{HybridCLRDataDir}/AssembliesPostIl2CppStrip";
+
+        public static string LocalIl2CppDir => $"{HybridCLRDataDir}/LocalIl2CppData/il2cpp";
+
+        public static string MethodBridgeCppDir => $"{LocalIl2CppDir}/libil2cpp/hybridclr/interpreter";
+
+        public static string Il2CppBuildCacheDir { get; } = $"{ProjectDir}/Library/Il2cppBuildCache";
+
+        public static string GetHotFixDllsOutputDirByTarget(BuildTarget target)
+        {
+            return $"{HotFixDllsOutputDir}/{target}";
+        }
+
+        public static string GetAssembliesPostIl2CppStripDir(BuildTarget target)
+        {
+            return $"{AssembliesPostIl2CppStripDir}/{target}";
+        }
+
+        public static string GetAssetBundleOutputDirByTarget(BuildTarget target)
+        {
+            return $"{AssetBundleOutputDir}/{target}";
+        }
+
+        public static string GetAssetBundleTempDirByTarget(BuildTarget target)
+        {
+            return $"{AssetBundleSourceDataTempDir}/{target}";
+        }
+
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/Editor/HybridCLR/BuildConfig.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: bf7714fc37515834382cd5836b503a9f
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 45 - 0
Unity/Assets/Scripts/Editor/HybridCLR/BuildConfig_Custom.cs

@@ -0,0 +1,45 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using UnityEditor;
+using UnityEngine;
+
+namespace HybridCLR.Editor
+{
+    public static partial class BuildConfig
+    {
+
+        /// <summary>
+        /// 所有热更新dll列表。放到此列表中的dll在打包时OnFilterAssemblies回调中被过滤。
+        /// </summary>
+        public static List<string> HotUpdateAssemblies { get; } = new List<string>
+        {
+        };
+
+        public static List<string> AOTMetaAssemblies { get; } = new List<string>()
+        {
+            "mscorlib.dll",
+            "System.dll",
+            "System.Core.dll", // 如果使用了Linq,需要这个
+            "Unity.Core.dll",
+            "Unity.Mono.dll",
+            "Unity.ThirdParty.dll",
+            "MongoDB.Bson.dll",
+            "CommandLine.dll",
+            "NLog.dll",
+
+            //
+            // 注意!修改这个列表请同步修改HotFix2模块中App.cs文件中的 LoadMetadataForAOTAssembly函数中aotDllList列表。
+            // 两者需要完全一致
+            //
+        };
+
+        public static List<string> AssetBundleFiles { get; } = new List<string>
+        {
+            //"common",
+        };
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/Editor/HybridCLR/BuildConfig_Custom.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 33c09b498146d144a947ed6d8ff104f3
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 192 - 0
Unity/Assets/Scripts/Editor/HybridCLR/BuildPlayerHelper.cs

@@ -0,0 +1,192 @@
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using UnityEditor;
+using UnityEngine;
+
+namespace HybridCLR.Editor
+{
+    public class BuildPlayerHelper
+    {
+        public static void CopyAssetBundles(string outputDir)
+        {
+            Directory.CreateDirectory(outputDir);
+
+            foreach(var ab in BuildConfig.AssetBundleFiles)
+            {
+                string srcFile = $"{Application.streamingAssetsPath}/{ab}";
+                string dstFile = $"{outputDir}/{Path.GetFileName(ab)}";
+                File.Copy(srcFile, dstFile, true);
+            }
+        }
+
+        //[MenuItem("HybridCLR/Build/Win64")]
+        public static void Build_Win64()
+        {
+            BuildTarget target = BuildTarget.StandaloneWindows64;
+            BuildTarget activeTarget = EditorUserBuildSettings.activeBuildTarget;
+            if (activeTarget != BuildTarget.StandaloneWindows64 && activeTarget != BuildTarget.StandaloneWindows)
+            {
+                Debug.LogError("请先切到Win平台再打包");
+                return;
+            }
+            // Get filename.
+            string outputPath = $"{BuildConfig.ProjectDir}/Release-Win64";
+
+            var buildOptions = BuildOptions.None;
+
+            string location = $"{outputPath}/HybridCLRTrial.exe";
+
+            Debug.Log("====> Build App");
+            BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions()
+            {
+                scenes = new string[] { "Assets/Scenes/Init.unity" },
+                locationPathName = location,
+                options = buildOptions,
+                target = target,
+                targetGroup = BuildTargetGroup.Standalone,
+            };
+
+            var report = BuildPipeline.BuildPlayer(buildPlayerOptions);
+            if (report.summary.result != UnityEditor.Build.Reporting.BuildResult.Succeeded)
+            {
+                Debug.LogError("打包失败");
+                return;
+            }
+
+            Debug.Log("====> Build AssetBundle");
+            AssetBundleBuildHelper.BuildAssetBundleByTarget(target);
+            Debug.Log("====> 复制 AssetBundle");
+            CopyAssetBundles($"{outputPath}/HybridCLRTrial_Data/StreamingAssets");
+
+#if UNITY_EDITOR
+            Application.OpenURL($"file:///{location}");
+#endif
+        }
+
+        //[MenuItem("HybridCLR/Build/Win32")]
+        public static void Build_Win32()
+        {
+            BuildTarget target = BuildTarget.StandaloneWindows;
+            BuildTarget activeTarget = EditorUserBuildSettings.activeBuildTarget;
+            if (activeTarget != BuildTarget.StandaloneWindows64 && activeTarget != BuildTarget.StandaloneWindows)
+            {
+                Debug.LogError("请先切到Win平台再打包");
+                return;
+            }
+            // Get filename.
+            string outputPath = $"{BuildConfig.ProjectDir}/Release-Win32";
+
+            var buildOptions = BuildOptions.None;
+
+            string location = $"{outputPath}/HybridCLRTrial.exe";
+
+            Debug.Log("====> Build App");
+            BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions()
+            {
+                scenes = new string[] { "Assets/Scenes/main.unity" },
+                locationPathName = location,
+                options = buildOptions,
+                target = target,
+                targetGroup = BuildTargetGroup.Standalone,
+            };
+
+            var report = BuildPipeline.BuildPlayer(buildPlayerOptions);
+            if (report.summary.result != UnityEditor.Build.Reporting.BuildResult.Succeeded)
+            {
+                Debug.LogError("打包失败");
+                return;
+            }
+
+            Debug.Log("====> Build AssetBundle");
+            AssetBundleBuildHelper.BuildAssetBundleByTarget(target);
+            Debug.Log("====> 复制 AssetBundle");
+            CopyAssetBundles($"{outputPath}/HybridCLRTrial_Data/StreamingAssets");
+
+#if UNITY_EDITOR
+            Application.OpenURL($"file:///{outputPath}");
+#endif
+        }
+        
+        //[MenuItem("HybridCLR/Build/OSX")]
+        public static void Build_OSX()
+        {
+            BuildTarget target = BuildTarget.StandaloneWindows;
+            BuildTarget activeTarget = EditorUserBuildSettings.activeBuildTarget;
+            if (activeTarget != BuildTarget.StandaloneOSX)
+            {
+                Debug.LogError("请先切到Mac平台再打包");
+                return;
+            }
+            // Get filename.
+            string outputPath = $"{BuildConfig.ProjectDir}/Release-OSX";
+
+            var buildOptions = BuildOptions.None;
+
+            string location = $"{outputPath}/HybridCLRTrial.app";
+
+            Debug.Log("====> Build App");
+            BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions()
+            {
+                scenes = new string[] { "Assets/Scenes/main.unity" },
+                locationPathName = location,
+                options = buildOptions,
+                target = target,
+                targetGroup = BuildTargetGroup.Standalone,
+            };
+
+            var report = BuildPipeline.BuildPlayer(buildPlayerOptions);
+            if (report.summary.result != UnityEditor.Build.Reporting.BuildResult.Succeeded)
+            {
+                Debug.LogError("打包失败");
+                return;
+            }
+
+            Debug.Log("====> Build AssetBundle");
+            AssetBundleBuildHelper.BuildAssetBundleByTarget(target);
+            Debug.Log("====> 复制 AssetBundle");
+            CopyAssetBundles($"{outputPath}/HybridCLRTrial_Data/StreamingAssets");
+
+#if UNITY_EDITOR
+            Application.OpenURL($"file:///{outputPath}");
+#endif
+        }
+
+        //[MenuItem("HybridCLR/Build/Android64")]
+        public static void Build_Android64()
+        {
+            BuildTarget target = BuildTarget.Android;
+            BuildTarget activeTarget = EditorUserBuildSettings.activeBuildTarget;
+            if (activeTarget != BuildTarget.Android)
+            {
+                Debug.LogError("请先切到Android平台再打包");
+                return;
+            }
+            // Get filename.
+            string outputPath = $"{BuildConfig.ProjectDir}/Release-Android";
+
+            var buildOptions = BuildOptions.None;
+
+            string location = outputPath + "/HybridCLRTrial.apk";
+            BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions()
+            {
+                scenes = new string[] { "Assets/Scenes/main.unity" },
+                locationPathName = location,
+                options = buildOptions,
+                target = target,
+                targetGroup = BuildTargetGroup.Android,
+            };
+
+            Debug.Log("====> 第1次 Build App(为了生成补充AOT元数据dll)");
+            BuildPipeline.BuildPlayer(buildPlayerOptions);
+            Debug.Log("====> Build AssetBundle");
+            AssetBundleBuildHelper.BuildAssetBundleByTarget(target);
+
+            Debug.Log("====> 第2次打包");
+            BuildPipeline.BuildPlayer(buildPlayerOptions);
+#if UNITY_EDITOR
+            Application.OpenURL($"file:///{outputPath}");
+#endif
+        }
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/Editor/HybridCLR/BuildPlayerHelper.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 7796c8df856ac4a4a9d644329c1f0958
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Unity/Assets/Scripts/Editor/HybridCLR/BuildProcessors.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 5d7e4bb1668e0b341b9613b967e27f88
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 84 - 0
Unity/Assets/Scripts/Editor/HybridCLR/BuildProcessors/BPCopyStrippedAOTAssemblies.cs

@@ -0,0 +1,84 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using UnityEditor;
+using UnityEditor.Build;
+using UnityEditor.Build.Reporting;
+using UnityEditor.Il2Cpp;
+using UnityEditor.UnityLinker;
+using UnityEngine;
+
+namespace HybridCLR.Editor.BuildProcessors
+{
+    internal class BPCopyStrippedAOTAssemblies : IPostprocessBuildWithReport
+#if !UNITY_2021_1_OR_NEWER
+     , IIl2CppProcessor
+#endif
+    {
+
+        public int callbackOrder => 0;
+
+#if UNITY_2021_1_OR_NEWER
+        public static string GetStripAssembliesDir2021(BuildTarget target)
+        {
+            string projectDir = BuildConfig.ProjectDir;
+#if UNITY_STANDALONE_WIN
+            return $"{projectDir}/Library/Bee/artifacts/WinPlayerBuildProgram/ManagedStripped";
+#elif UNITY_ANDROID
+            return $"{projectDir}/Library/Bee/artifacts/Android/ManagedStripped";
+#elif UNITY_IOS
+            return $"{projectDir}/Temp/StagingArea/Data/Managed/tempStrip";
+#elif UNITY_WEBGL
+            return $"{projectDir}/Library/Bee/artifacts/WebGL/ManagedStripped";
+#elif UNITY_EDITOR_OSX
+            return $"{projectDir}/Library/Bee/artifacts/MacStandalonePlayerBuildProgram/ManagedStripped";
+#else
+            throw new NotSupportedException("GetOriginBuildStripAssembliesDir");
+#endif
+        }
+#else
+        private string GetStripAssembliesDir2020(BuildTarget target)
+        {
+            string subPath = target == BuildTarget.Android ?
+                "assets/bin/Data/Managed" :
+                "Data/Managed/";
+            return $"{BuildConfig.ProjectDir}/Temp/StagingArea/{subPath}";
+        }
+
+        public void OnBeforeConvertRun(BuildReport report, Il2CppBuildPipelineData data)
+        {            
+            // 此回调只在 2020中调用
+            CopyStripDlls(GetStripAssembliesDir2020(data.target), data.target);
+        }
+#endif
+
+        public static void CopyStripDlls(string srcStripDllPath, BuildTarget target)
+        {
+            Debug.Log($"[BPCopyStrippedAOTAssemblies] CopyScripDlls. src:{srcStripDllPath} target:{target}");
+
+            var dstPath = BuildConfig.GetAssembliesPostIl2CppStripDir(target);
+
+            Directory.CreateDirectory(dstPath);
+
+            //string srcStripDllPath = BuildConfig.GetOriginBuildStripAssembliesDir(target);
+
+            foreach (var fileFullPath in Directory.GetFiles(srcStripDllPath, "*.dll"))
+            {
+                var file = Path.GetFileName(fileFullPath);
+                Debug.Log($"[BPCopyStrippedAOTAssemblies] copy strip dll {fileFullPath} ==> {dstPath}/{file}");
+                File.Copy($"{fileFullPath}", $"{dstPath}/{file}", true);
+            }
+        }
+
+        public void OnPostprocessBuild(BuildReport report)
+        {
+#if UNITY_2021_1_OR_NEWER && !UNITY_IOS
+            BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
+            CopyStripDlls(GetStripAssembliesDir2021(target), target);
+#endif
+        }
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/Editor/HybridCLR/BuildProcessors/BPCopyStrippedAOTAssemblies.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: f7884710ec2f8e545b3fe9aa05def5a8
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 47 - 0
Unity/Assets/Scripts/Editor/HybridCLR/BuildProcessors/BPFilterHotFixAssemblies.cs

@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using UnityEditor;
+using UnityEditor.Build;
+using UnityEngine;
+
+namespace HybridCLR.Editor.BuildProcessors
+{
+    /// <summary>
+    /// 将热更新dll从Build过程中过滤,防止打包到主工程中
+    /// </summary>
+    internal class BPFilterHotFixAssemblies : IFilterBuildAssemblies
+    {
+        public int callbackOrder => 0;
+
+        public string[] OnFilterAssemblies(BuildOptions buildOptions, string[] assemblies)
+        {
+            List<string> allHotUpdateDllNames = BuildConfig.HotUpdateAssemblies;
+
+            // 检查是否重复填写
+            var hotUpdateDllSet = new HashSet<string>();
+            foreach(var hotUpdateDll in allHotUpdateDllNames)
+            {
+                if (!hotUpdateDllSet.Add(hotUpdateDll))
+                {
+                    throw new Exception($"热更新 assembly:{hotUpdateDll} 在列表中重复,请除去重复条目");
+                }
+            }
+
+            // 检查是否填写了正确的dll名称
+            foreach (var hotUpdateDll in BuildConfig.HotUpdateAssemblies)
+            {
+                if (assemblies.All(ass => !ass.EndsWith(hotUpdateDll)))
+                {
+                    throw new Exception($"热更新 assembly:{hotUpdateDll} 不存在,请检查拼写错误");
+                }
+                Debug.Log($"[BPFilterHotFixAssemblies] 过滤热更新assembly:{hotUpdateDll}");
+            }
+            
+            // 将热更dll从打包列表中移除
+            return assemblies.Where(ass => BuildConfig.HotUpdateAssemblies.All(dll => !ass.EndsWith(dll, StringComparison.OrdinalIgnoreCase))).ToArray();
+        }
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/Editor/HybridCLR/BuildProcessors/BPFilterHotFixAssemblies.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 9dec2922e3df5464aa047b636eb19e0d
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 148 - 0
Unity/Assets/Scripts/Editor/HybridCLR/BuildProcessors/BPPatchScriptAssembliesJson.cs

@@ -0,0 +1,148 @@
+using HybridCLR.Editor.GlobalManagers;
+using System;
+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.Il2Cpp;
+using UnityEditor.UnityLinker;
+using UnityEngine;
+
+namespace HybridCLR.Editor.BuildProcessors
+{
+    public class BPPatchScriptAssembliesJson : IPreprocessBuildWithReport,
+#if UNITY_ANDROID
+        IPostGenerateGradleAndroidProject,
+#endif
+        IPostprocessBuildWithReport
+    {
+        public int callbackOrder => 0;
+
+
+        [Serializable]
+        private class ScriptingAssemblies
+        {
+            public List<string> names;
+            public List<int> types;
+        }
+
+        public void OnPostGenerateGradleAndroidProject(string path)
+        {
+            // 如果直接打包apk,没有机会在PostprocessBuild中修改ScriptingAssemblies.json。
+            // 因此需要在这个时机处理
+            PathScriptingAssembilesFile(path);
+        }
+
+        public void OnPostprocessBuild(BuildReport report)
+        {
+            // 如果target为Android,由于已经在OnPostGenerateGradelAndroidProject中处理过,
+            // 这里不再重复处理
+#if !UNITY_ANDROID
+
+            PathScriptingAssembilesFile(report.summary.outputPath);
+#endif
+        }
+
+        private void PathScriptingAssembilesFile(string path)
+        {
+#if UNITY_2020_1_OR_NEWER
+            AddHotFixAssembliesToScriptingAssembliesJson(path);
+#else
+            AddBackHotFixAssembliesToBinFile(path);
+#endif
+        }
+
+        private void AddHotFixAssembliesToScriptingAssembliesJson(string path)
+        {
+            Debug.Log($"AddBackHotFixAssembliesToJson. path:{path}");
+            if (!Directory.Exists(path))
+            {
+                path = Directory.GetParent(path).ToString();
+            }
+            /*
+             * ScriptingAssemblies.json 文件中记录了所有的dll名称,此列表在游戏启动时自动加载,
+             * 不在此列表中的dll在资源反序列化时无法被找到其类型
+             * 因此 OnFilterAssemblies 中移除的条目需要再加回来
+             */
+            string[] jsonFiles = Directory.GetFiles(path, BuildConfig.ScriptingAssembliesJsonFile, SearchOption.AllDirectories);
+
+            if (jsonFiles.Length == 0)
+            {
+                Debug.LogError($"can not find file {BuildConfig.ScriptingAssembliesJsonFile}");
+                return;
+            }
+
+            foreach (string file in jsonFiles)
+            {
+                string content = File.ReadAllText(file);
+                ScriptingAssemblies scriptingAssemblies = JsonUtility.FromJson<ScriptingAssemblies>(content);
+                foreach (string name in BuildConfig.HotUpdateAssemblies)
+                {
+                    if (!scriptingAssemblies.names.Contains(name))
+                    {
+                        scriptingAssemblies.names.Add(name);
+                        scriptingAssemblies.types.Add(16); // user dll type
+                        Debug.Log($"[PatchScriptAssembliesJson] add hotfix assembly:{name} to {file}");
+                    }
+                }
+                content = JsonUtility.ToJson(scriptingAssemblies);
+
+                File.WriteAllText(file, content);
+            }
+        }
+
+        private void AddBackHotFixAssembliesToBinFile(string path)
+        {
+            /*
+             * Unity2019 中 dll 加载列表存储在 globalgamemanagers 文件中,此列表在游戏启动时自动加载,
+             * 不在此列表中的dll在资源反序列化时无法被找到其类型
+             * 因此 OnFilterAssemblies 中移除的条目需要再加回来
+             */
+#if UNITY_ANDROID
+            string[] binFiles = new string[] { "Temp/gradleOut/unityLibrary/src/main/assets/bin/Data/globalgamemanagers" }; // report.files 不包含 Temp/gradleOut 等目录
+#else
+            // 直接出包和输出vs工程时路径不同,report.summary.outputPath 记录的是前者路径
+            string[] binFiles = Directory.GetFiles(Path.GetDirectoryName(path), "globalgamemanagers", SearchOption.AllDirectories);
+#endif
+
+            if (binFiles.Length == 0)
+            {
+                Debug.LogError("can not find file ScriptingAssemblies.json");
+                return;
+            }
+
+            foreach (string binPath in binFiles)
+            {
+                var binFile = new UnityBinFile();
+                binFile.LoadFromFile(binPath);
+
+                ScriptsData scriptsData = binFile.scriptsData;
+                foreach (string name in BuildConfig.HotUpdateAssemblies)
+                {
+                    if (!scriptsData.dllNames.Contains(name))
+                    {
+                        scriptsData.dllNames.Add(name);
+                        scriptsData.dllTypes.Add(16); // user dll type
+                    }
+                }
+                binFile.scriptsData = scriptsData;
+
+                binFile.RebuildAndFlushToFile(binPath);
+            }
+        }
+
+#region useless
+
+        public void OnPreprocessBuild(BuildReport report)
+        {
+
+        }
+
+#endregion
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/Editor/HybridCLR/BuildProcessors/BPPatchScriptAssembliesJson.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 9bb6e2908d8948648979c9ff6bb7937d
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Unity/Assets/Scripts/Editor/HybridCLR/BuildProcessors/UnityBinFileReader.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: e52fb09e14efee949ae80ae8aa9f9d44
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 107 - 0
Unity/Assets/Scripts/Editor/HybridCLR/BuildProcessors/UnityBinFileReader/UnityBinFile.cs

@@ -0,0 +1,107 @@
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using UnityEngine;
+using System.Text;
+using System.Reflection;
+using System;
+using System.Linq;
+
+namespace HybridCLR.Editor.GlobalManagers
+{
+    /// <summary>
+    /// Unity 生成的二进制文件(本代码不支持5.x之前的版本)
+    /// </summary>
+    public unsafe class UnityBinFile
+    {
+        /*
+         * MonoManager: idx: 6;
+         * type: metaData.types[objects[6].typeID]
+         */
+        public const int kMonoManagerIdx = 6;
+
+        public string path { get; private set; }
+
+        public FileHeader header;
+        public MetaData metaData;
+        public ScriptsData scriptsData;
+
+        public void LoadFromFile(string path)
+        {
+            this.path = path;
+
+            var fs = new FileStream(path, FileMode.Open, FileAccess.Read);
+            var br = new BinaryReader(fs, Encoding.UTF8, true);
+            
+            header.LoadFromStream(br);
+            // 按理说 metaData 应该新开一个buffer来避免加载时的对齐逻辑问题,但由于 sizeof(Header) = 20,已经对齐到4了,所以可以连续读
+            metaData.LoadFromStream(br, header.dataOffset);
+            scriptsData = metaData.GetScriptData(br);
+
+            br.Close();
+            fs.Close();
+        }
+
+        public void RebuildAndFlushToFile(string newPath)
+        {
+            var fsR = new FileStream(path, FileMode.Open, FileAccess.Read);
+            var brR = new BinaryReader(fsR, Encoding.UTF8, true);
+
+            var ms = new MemoryStream((int)(header.fileSize * 1.5f));
+            var bw = new BinaryWriter(ms, Encoding.UTF8, true);
+
+            /*
+             * 开始写入data
+             * dll名称列表存储于 data 区段,修改其数据并不会影响 MetaData 大小,因此 dataOffset 不会改变
+             */
+            ms.Position = header.dataOffset;
+
+            Dictionary<long, ObjectInfo> newObjInfos = new Dictionary<long, ObjectInfo>();
+            foreach (var kv in metaData.objects)
+            {
+                long objID = kv.Key;
+                ObjectInfo objInfo = kv.Value;
+
+                byte[] buff = new byte[objInfo.size];
+                fsR.Position = objInfo.realPos;
+                brR.Read(buff, 0, buff.Length);
+
+
+                {// unity 的数据偏移貌似会对齐到 8
+                    int newPos = (((int)ms.Position + 7) >> 3) << 3;
+                    int gapSize = newPos - (int)ms.Position;
+                    
+                    for (int i = 0; i < gapSize; i++)
+                        bw.Write((byte)0);
+                    
+                    objInfo.dataPos = (uint)ms.Position - header.dataOffset; // 重定位数据偏移
+                }
+
+                if (objID != kMonoManagerIdx)
+                    bw.Write(buff, 0, buff.Length);
+                else
+                    objInfo.size = (uint)scriptsData.SaveToStream(bw);
+
+                newObjInfos.Add(objID, objInfo);
+            }
+
+            metaData.objects = newObjInfos;
+            header.fileSize = (uint)ms.Position;
+
+            ms.Position = 0;
+            header.SaveToStream(bw);
+            metaData.SaveToStream(bw);
+
+            brR.Close();
+            fsR.Close();
+
+            // 写入新文件
+            ms.Position = 0;
+            File.WriteAllBytes(newPath, ms.ToArray());
+            
+            bw.Close();
+            ms.Close();
+        }
+    }
+
+}

+ 11 - 0
Unity/Assets/Scripts/Editor/HybridCLR/BuildProcessors/UnityBinFileReader/UnityBinFile.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: ae7ec6e3674077d46898fe821d24bf85
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 397 - 0
Unity/Assets/Scripts/Editor/HybridCLR/BuildProcessors/UnityBinFileReader/UnityBinFileDefines.cs

@@ -0,0 +1,397 @@
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using UnityEngine;
+using static HybridCLR.Editor.GlobalManagers.UnityBinUtils;
+
+namespace HybridCLR.Editor.GlobalManagers
+{
+    public struct FileHeader
+    {
+        public const int kSize = 20;
+
+        public uint dataSize => fileSize - metadataSize;
+
+        public uint metadataSize;
+        public uint fileSize;
+        public uint version;
+        public uint dataOffset;
+        public byte endianess;
+
+        public void LoadFromStream(BinaryReader br)
+        {
+            long startPos = br.BaseStream.Position;
+            metadataSize = br.ReadUInt32();
+            fileSize = br.ReadUInt32();
+            version = br.ReadUInt32();
+            dataOffset = br.ReadUInt32();
+            endianess = br.ReadByte();
+            br.BaseStream.Position = startPos + kSize;
+
+            SwapEndianess();
+        }
+
+        public long SaveToStream(BinaryWriter bw)
+        {
+            SwapEndianess();
+
+            long startPos = bw.BaseStream.Position;
+            bw.Write(metadataSize);
+            bw.Write(fileSize);
+            bw.Write(version);
+            bw.Write(dataOffset);
+            bw.Write(endianess);
+            bw.BaseStream.Position = startPos + kSize;
+            return kSize;
+        }
+
+        void SwapEndianess()
+        {
+            SwapUInt(ref metadataSize);
+            SwapUInt(ref fileSize);
+            SwapUInt(ref version);
+            SwapUInt(ref dataOffset);
+        }
+    }
+
+    public struct MetaData
+    {
+        public long dataStartPos;
+
+        public string version;
+        public uint platform;
+        public bool enableTypeTree;
+        public int typeCount;
+        public ObjectType[] types;
+        public int objectCount;
+        public Dictionary<long, ObjectInfo> objects;
+        public int scriptTypeCount;
+        public ScriptType[] scriptTypes;
+        public int externalsCount;
+        public ExternalInfo[] externals;
+
+#if UNITY_2019_2_OR_NEWER
+        public int refTypeCount;
+        public ObjectType[] refTypes;
+#endif
+        public string dummyStr;
+
+        public void LoadFromStream(BinaryReader br, uint dataOffset)
+        {
+            long startPos = br.BaseStream.Position;
+            dataStartPos = startPos;
+
+            version = br.ReadRawString();
+            platform = br.ReadUInt32();
+            enableTypeTree = br.ReadBoolean();
+            typeCount = br.ReadInt32();
+            types = new ObjectType[typeCount];
+
+            for (int i = 0; i < typeCount; i++)
+            {
+                types[i].LoadFromStream(br);
+            }
+
+            objectCount = br.ReadInt32();
+            objects = new Dictionary<long, ObjectInfo>();
+            for(int i = 0; i < objectCount; i++)
+            {
+                long id = br.AlignedReadInt64();
+                ObjectInfo objInfo = new ObjectInfo();
+                objInfo.LoadFromStream(br);
+                objInfo.realPos = objInfo.dataPos + dataOffset;
+
+                objects.Add(id, objInfo);
+            }
+
+            scriptTypeCount = br.ReadInt32();
+            scriptTypes = new ScriptType[scriptTypeCount];
+            for(int i = 0; i < scriptTypeCount; i++)
+            {
+                scriptTypes[i].LoadFromStream(br);
+            }
+
+            externalsCount = br.ReadInt32();
+            externals = new ExternalInfo[externalsCount];
+            for(int i = 0; i < externalsCount; i++)
+            {
+                externals[i].LoadFromStream(br);
+            }
+
+#if UNITY_2019_2_OR_NEWER
+            refTypeCount = br.ReadInt32();
+            refTypes = new ObjectType[refTypeCount];
+            for(int i = 0; i < refTypeCount; i++)
+            {
+                refTypes[i].LoadFromStream(br);
+            }
+#endif
+            dummyStr = br.ReadRawString();
+        }
+
+        public long SaveToStream(BinaryWriter bw)
+        {
+            long startPos = bw.BaseStream.Position;
+            bw.WriteRawString(version);
+            bw.Write(platform);
+            bw.Write(enableTypeTree);
+            
+            bw.Write(typeCount);
+            foreach(var type in types)
+                type.SaveToStream(bw);
+
+            bw.Write(objectCount);
+            foreach (var kv in objects)
+            {
+                bw.AlignedWriteInt64(kv.Key);
+                kv.Value.SaveToStream(bw);
+            }
+                
+            bw.Write(scriptTypeCount);
+            foreach(var st in scriptTypes)
+                st.SaveToStream(bw);
+
+            bw.Write(externalsCount);
+            foreach(var external in externals)
+                external.SaveToStream(bw);
+
+#if UNITY_2019_2_OR_NEWER
+            bw.Write(refTypeCount);
+            foreach(var refT in refTypes)
+                refT.SaveToStream(bw);
+#endif
+
+            bw.WriteRawString(dummyStr);
+
+            return bw.BaseStream.Position - startPos;
+        }
+
+        public ScriptsData GetScriptData(BinaryReader br)
+        {
+            ObjectInfo objInfo = objects[UnityBinFile.kMonoManagerIdx];
+            br.BaseStream.Seek(objInfo.realPos, SeekOrigin.Begin);
+
+            ScriptsData data = new ScriptsData();
+            data.LoadFromStream(br);
+            return data;
+        }
+    }
+
+    public struct ObjectType
+    {
+        public int typeID;
+        public bool isStriped;
+        public short scriptTypeIndex;
+
+        public bool needReadScriptHash; // dont save
+
+        public Hash scriptSigHash;
+        public Hash typeHash;
+
+        public void LoadFromStream(BinaryReader br)
+        {
+            typeID = br.ReadInt32();
+            isStriped = br.ReadBoolean();
+            scriptTypeIndex = br.ReadInt16();
+
+            needReadScriptHash = typeID == -1 || typeID == 0x72;
+            if(needReadScriptHash)
+                scriptSigHash.LoadFromStream(br);
+
+            typeHash.LoadFromStream(br);
+
+            // GlobalManagers does not has TypeTrees
+        }
+
+        public long SaveToStream(BinaryWriter bw)
+        {
+            long startPos = bw.BaseStream.Position;
+            bw.Write(typeID);
+            bw.Write(isStriped);
+            bw.Write(scriptTypeIndex);
+            
+            if(needReadScriptHash)
+                scriptSigHash.SaveToStream(bw);
+
+            typeHash.SaveToStream(bw);
+            return bw.BaseStream.Position - startPos;
+        }
+
+        public int Size()
+        {
+            int ret = 0;
+            ret += sizeof(int);
+            ret += sizeof(bool);
+            ret += sizeof(short);
+
+            if (needReadScriptHash)
+                ret += Hash.kSize;
+
+            ret += Hash.kSize;
+            return ret;
+        }
+    }
+
+    public struct ObjectInfo
+    {
+        public const int kSize = 12;
+
+        public uint dataPos;
+        public uint size;
+        public uint typeID;
+
+        public uint realPos; // dataPos + Header.dataOffset; // dont save
+
+        public void LoadFromStream(BinaryReader br)
+        {
+            dataPos = br.ReadUInt32();
+            size = br.ReadUInt32();
+            typeID = br.ReadUInt32();
+        }
+
+        public long SaveToStream(BinaryWriter bw)
+        {
+            bw.Write(dataPos);
+            bw.Write(size);
+            bw.Write(typeID);
+            return kSize;
+        }
+    }
+
+    public struct ScriptType
+    {
+        public int localFileIndex;
+        public long localIdentifierOfBin;
+
+        public void LoadFromStream(BinaryReader br)
+        {
+            localFileIndex = br.ReadInt32();
+            localIdentifierOfBin = br.AlignedReadInt64();
+        }
+
+        public long SaveToStream(BinaryWriter bw)
+        {
+            long startPos = bw.BaseStream.Position;
+            bw.Write(localFileIndex);
+            bw.AlignedWriteInt64(localIdentifierOfBin);
+            return bw.BaseStream.Position - startPos;
+        }
+    }
+
+    public struct ExternalInfo
+    {
+        public string dummy;
+        public Hash guid;
+        public int type;
+        public string name;
+        
+        public void LoadFromStream(BinaryReader br)
+        {
+            dummy = br.ReadRawString();
+            guid.LoadFromStream(br);
+            type = br.ReadInt32();
+            name = br.ReadRawString();
+        }
+
+        public long SaveToStream(BinaryWriter bw)
+        {
+            long startPos = bw.BaseStream.Position;
+            bw.WriteRawString(dummy);
+            guid.SaveToStream(bw);
+            bw.Write(type);
+            bw.WriteRawString(name);
+            return bw.BaseStream.Position - startPos;
+        }
+    }
+
+    public struct ScriptsData
+    {
+        public ScriptID[] scriptIDs;
+        public List<string> dllNames;
+        public List<int> dllTypes; // 16 is user type
+
+        public void LoadFromStream(BinaryReader br)
+        {
+            {
+                int count = br.ReadInt32();
+                scriptIDs = new ScriptID[count];
+                for(int i = 0; i < count; i++)
+                    scriptIDs[i].LoadFromStream(br);
+            }
+            {
+                int count = br.ReadInt32();
+                dllNames = new List<string>(count);
+                for (var i = 0; i < count; i++)
+                    dllNames.Add(br.ReadSizeString());
+            }
+            {
+                int count = br.ReadInt32();
+                dllTypes = new List<int>(count);
+                for(var i = 0; i < count; i++)
+                    dllTypes.Add(br.ReadInt32());
+            }
+        }
+
+        public long SaveToStream(BinaryWriter bw)
+        {
+            long startPos = bw.BaseStream.Position;
+            bw.Write(scriptIDs.Length);
+            for(int i = 0; i < scriptIDs.Length; i++)
+                scriptIDs[i].SaveToStream(bw);
+
+            bw.Write(dllNames.Count);
+            for(int i = 0, imax = dllNames.Count; i < imax; i++)
+                bw.WriteSizeString(dllNames[i]);
+
+            bw.Write(dllTypes.Count);
+            for(int i = 0, imax = dllTypes.Count; i < imax; i++)
+                bw.Write(dllTypes[i]);
+
+            return bw.BaseStream.Position - startPos;
+        }
+    }
+
+    public struct ScriptID
+    {
+        public int fileID;
+        public long pathID; // localIdentifier
+
+        public void LoadFromStream(BinaryReader br)
+        {
+            fileID = br.ReadInt32();
+            pathID = br.ReadInt64();
+        }
+
+        public long SaveToStream(BinaryWriter bw)
+        {
+            bw.Write(fileID);
+            bw.Write(pathID);
+            return 4 + 8;
+        }
+    }
+
+    public struct Hash
+    {
+        public const int kSize = 16;
+
+        public int[] data;
+
+        public void LoadFromStream(BinaryReader br)
+        {
+            data = new int[4];
+            for(int i = 0; i < data.Length; i++)
+            {
+                data[i] = br.ReadInt32();
+            }
+        }
+
+        public long SaveToStream(BinaryWriter bw)
+        {
+            for(int i = 0; i < data.Length; i++)
+            {
+                bw.Write(data[i]);
+            }
+            return kSize;
+        }
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/Editor/HybridCLR/BuildProcessors/UnityBinFileReader/UnityBinFileDefines.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 96788c7fe08d5d54d95a87cfbdcb643a
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 78 - 0
Unity/Assets/Scripts/Editor/HybridCLR/BuildProcessors/UnityBinFileReader/UnityBinUtils.cs

@@ -0,0 +1,78 @@
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using UnityEngine;
+using System.Text;
+
+namespace HybridCLR.Editor.GlobalManagers
+{
+    public static class UnityBinUtils
+    {
+        public static void SwapUInt(ref uint val)
+        {
+            val = (val >> 24) | ((val >> 8) & 0x0000ff00) | ((val << 8) & 0x00ff0000) | (val << 24);
+        }
+
+        public static string ReadRawString(this BinaryReader br)
+        {
+            long startPos = br.BaseStream.Position;
+            while (true)
+            {
+                byte val = br.ReadByte();
+                if(val == 0)
+                    break;
+            }
+            int size = (int)(br.BaseStream.Position - startPos);
+            br.BaseStream.Position = startPos;
+
+            byte[] buffer = br.ReadBytes(size);
+            string ret = Encoding.UTF8.GetString(buffer, 0, size - 1);
+
+            return ret;
+        }
+
+        public static void WriteRawString(this BinaryWriter bw, string str)
+        {
+            byte[] buffer = Encoding.UTF8.GetBytes(str);
+            bw.Write(buffer, 0, buffer.Length);
+            bw.Write((byte)0);
+        }
+
+        public static string ReadSizeString(this BinaryReader br)
+        {
+            int size = br.ReadInt32();
+            byte[] buff = br.ReadBytes(size);
+            br.BaseStream.AlignOffset4();
+
+            string ret = Encoding.UTF8.GetString(buff);
+            return ret;
+        }
+
+        public static void WriteSizeString(this BinaryWriter bw, string str)
+        {
+            byte[] buff = Encoding.UTF8.GetBytes(str);
+            bw.Write(buff.Length);
+            bw.Write(buff, 0, buff.Length);
+            bw.BaseStream.AlignOffset4();
+        }
+
+        public static void AlignOffset4(this Stream stream)
+        {
+            int offset = (((int)stream.Position + 3) >> 2) << 2;
+            stream.Position = offset;
+        }
+
+        public static long AlignedReadInt64(this BinaryReader br)
+        {
+            br.BaseStream.AlignOffset4();
+            return br.ReadInt64();
+        }
+
+        public static void AlignedWriteInt64(this BinaryWriter bw, long val)
+        {
+            bw.BaseStream.AlignOffset4();
+            bw.Write(val);
+        }
+    }
+}
+

+ 11 - 0
Unity/Assets/Scripts/Editor/HybridCLR/BuildProcessors/UnityBinFileReader/UnityBinUtils.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: bf7c4cf970660614fb54d838ec6e7eda
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 65 - 0
Unity/Assets/Scripts/Editor/HybridCLR/CompileDllHelper.cs

@@ -0,0 +1,65 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using UnityEditor;
+using UnityEditor.Build.Player;
+using UnityEngine;
+
+namespace HybridCLR.Editor
+{
+    internal class CompileDllHelper
+    {
+        public static void CompileDll(string buildDir, BuildTarget target)
+        {
+            var group = BuildPipeline.GetBuildTargetGroup(target);
+
+            ScriptCompilationSettings scriptCompilationSettings = new ScriptCompilationSettings();
+            scriptCompilationSettings.group = group;
+            scriptCompilationSettings.target = target;
+            Directory.CreateDirectory(buildDir);
+            ScriptCompilationResult scriptCompilationResult = PlayerBuildInterface.CompilePlayerScripts(scriptCompilationSettings, buildDir);
+            foreach (var ass in scriptCompilationResult.assemblies)
+            {
+                Debug.LogFormat("compile assemblies:{1}/{0}", ass, buildDir);
+            }
+        }
+
+        public static void CompileDll(BuildTarget target)
+        {
+            CompileDll(BuildConfig.GetHotFixDllsOutputDirByTarget(target), target);
+        }
+
+        //[MenuItem("HybridCLR/CompileDll/ActiveBuildTarget")]
+        public static void CompileDllActiveBuildTarget()
+        {
+            CompileDll(EditorUserBuildSettings.activeBuildTarget);
+        }
+
+        //[MenuItem("HybridCLR/CompileDll/Win32")]
+        public static void CompileDllWin32()
+        {
+            CompileDll(BuildTarget.StandaloneWindows);
+        }
+
+        //[MenuItem("HybridCLR/CompileDll/Win64")]
+        public static void CompileDllWin64()
+        {
+            CompileDll(BuildTarget.StandaloneWindows64);
+        }
+
+        //[MenuItem("HybridCLR/CompileDll/Android")]
+        public static void CompileDllAndroid()
+        {
+            CompileDll(BuildTarget.Android);
+        }
+
+        //[MenuItem("HybridCLR/CompileDll/IOS")]
+        public static void CompileDllIOS()
+        {
+            CompileDll(BuildTarget.iOS);
+        }
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/Editor/HybridCLR/CompileDllHelper.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 91aca02079207d746b74aeea1b595127
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: f85b93bff3478c045ae862a7cc216b18
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 13 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/ConstStrings.cs

@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HybridCLR.Editor.Generators
+{
+    internal static class ConstStrings
+    {
+        public const string typeObjectPtr = "Il2CppObject*";
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/ConstStrings.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: e1465458aaad6884d95af7c4fc2de7a1
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 40 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/FileRegionReplace.cs

@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HybridCLR.Editor.Generators
+{
+    public class FileRegionReplace
+    {
+        private readonly string _tplFile;
+
+        private readonly Dictionary<string, string> _regionReplaceContents = new Dictionary<string, string>();
+
+        public FileRegionReplace(string tplFile)
+        {
+            _tplFile = tplFile;
+        }
+
+        public void Replace(string regionName, string regionContent)
+        {
+            _regionReplaceContents.Add(regionName, regionContent);
+        }
+
+        public void Commit(string outputFile)
+        {
+            string originContent = File.ReadAllText(_tplFile, Encoding.UTF8);
+
+            string resultContent = originContent;
+
+            foreach (var c in _regionReplaceContents)
+            {
+                resultContent = TemplateUtil.ReplaceRegion(resultContent, c.Key, c.Value);
+            }
+            var utf8WithoutBOM = new System.Text.UTF8Encoding(false);
+            File.WriteAllText(outputFile, resultContent, utf8WithoutBOM);
+        }
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/FileRegionReplace.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: e5aa6559bd1b1e4488aa6746eda8202b
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 71 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/GeneratorConfig.cs

@@ -0,0 +1,71 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using UnityEngine;
+
+namespace HybridCLR.Editor.Generators
+{
+    internal class GeneratorConfig
+    {
+        /// <summary>
+        /// 目前已经根据热更新dll的依赖自动计算需要扫描哪些dll来收集桥接函数。
+        /// 只要你的热更新以assembly def形式放到项目中,是不需要改这个的
+        /// </summary>
+        /// <returns></returns>
+        public static List<string> GetExtraAssembiles()
+        {
+            return new List<string>
+            {
+                "mscorlib",
+                "CommandLine"
+            };
+        }
+
+        /// <summary>
+        /// 暂时没有仔细扫描泛型,如果运行时发现有生成缺失,先手动在此添加类
+        /// </summary>
+        /// <returns></returns>
+        public static List<Type> PrepareCustomGenericTypes()
+        {
+            return new List<Type>
+            {
+                typeof(Action<int, string, Vector3>),
+            };
+        }
+
+        /// <summary>
+        /// 如果提示缺失桥接函数,将提示缺失的签名加入到下列列表是简单的做法。
+        /// 这里添加64位App缺失的桥接函数签名
+        /// </summary>
+        /// <returns></returns>
+        public static List<string> PrepareCustomMethodSignatures64()
+        {
+            return new List<string>
+            {
+                "vi8i8",
+                "i4i8i8i4i4i8i8",
+                "i8i8S12",
+                "S12i8S12",
+                "S12i8S12S12",
+                "i16i8i16i16",
+            };
+        }
+
+        /// <summary>
+        /// 如果提示缺失桥接函数,将提示缺失的签名加入到下列列表是简单的做法。
+        /// 这里添加32位App缺失的桥接函数签名
+        /// </summary>
+        /// <returns></returns>
+        public static List<string> PrepareCustomMethodSignatures32()
+        {
+            return new List<string>
+            {
+                "vi4i4",
+                "S12i4S12S12",
+            };
+        }
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/GeneratorConfig.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: d1d14f8f858560948ae1dfa0fa572e51
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 4aa66b41c89ed7742ad067898725f7ff
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 28 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/IPlatformAdaptor.cs

@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HybridCLR.Editor.Generators.MethodBridge
+{
+    public interface IPlatformAdaptor
+    {
+        bool IsArch32 { get; }
+
+        TypeInfo CreateTypeInfo(Type type, bool returnValue);
+
+        void GenerateManaged2NativeMethod(MethodBridgeSig method, List<string> outputLines);
+
+        void GenerateManaged2NativeStub(List<MethodBridgeSig> methods, List<string> lines);
+
+        void GenerateNative2ManagedMethod(MethodBridgeSig method, List<string> outputLines);
+
+        void GenerateNative2ManagedStub(List<MethodBridgeSig> methods, List<string> lines);
+
+        void GenerateAdjustThunkMethod(MethodBridgeSig method, List<string> outputLines);
+
+        void GenerateAdjustThunkStub(List<MethodBridgeSig> methods, List<string> lines);
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/IPlatformAdaptor.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 983dbdeb1fb7d0b43a863c6b22160ace
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 353 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/MethodBridgeGenerator.cs

@@ -0,0 +1,353 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using UnityEditor;
+using UnityEngine;
+
+namespace HybridCLR.Editor.Generators.MethodBridge
+{
+
+    public class TypeGenInfo
+    {
+        public Type Type { get; set; }
+
+        public List<MethodInfo> GenericMethods { get; set; }
+    }
+
+    public class MethodBridgeGeneratorOptions
+    {
+        public List<Assembly> HotfixAssemblies { get; set; }
+
+        public List<Assembly> AllAssemblies { get; set; }
+
+        public PlatformABI CallConvention { get; set; }
+
+        public string OutputFile { get; set; }
+
+        public bool Optimized { get; set; }
+    }
+
+    public class MethodBridgeGenerator
+    {
+        private readonly HashSet<Assembly> _hotfixAssemblies;
+
+        private readonly List<Assembly> _assemblies;
+
+        private readonly PlatformABI _callConvention;
+
+        private readonly string _outputFile;
+
+        public readonly bool _optimized;
+
+        private readonly IPlatformAdaptor _platformAdaptor;
+
+        private readonly HashSet<MethodBridgeSig> _managed2nativeMethodSet = new HashSet<MethodBridgeSig>();
+
+        private List<MethodBridgeSig> _managed2nativeMethodList;
+
+        private readonly HashSet<MethodBridgeSig> _native2managedMethodSet = new HashSet<MethodBridgeSig>();
+
+        private List<MethodBridgeSig> _native2managedMethodList;
+
+        private readonly HashSet<MethodBridgeSig> _adjustThunkMethodSet = new HashSet<MethodBridgeSig>();
+
+        private List<MethodBridgeSig> _adjustThunkMethodList;
+
+        public bool IsHotFixType(Type type)
+        {
+            return _hotfixAssemblies.Contains(type.Assembly);
+        }
+
+        public MethodBridgeGenerator(MethodBridgeGeneratorOptions options)
+        {
+            _hotfixAssemblies = new HashSet<Assembly>(options.HotfixAssemblies);
+            _assemblies = options.AllAssemblies;
+            _callConvention = options.CallConvention;
+            _outputFile = options.OutputFile;
+            _platformAdaptor = CreatePlatformAdaptor(options.CallConvention);
+            _optimized = options.Optimized;
+        }
+
+        private static IPlatformAdaptor CreatePlatformAdaptor(PlatformABI type)
+        {
+            switch (type)
+            {
+                case PlatformABI.Universal32: return new PlatformAdaptor_Universal32();
+                case PlatformABI.Universal64: return new PlatformAdaptor_Universal64();
+                case PlatformABI.Arm64: return new PlatformAdaptor_Arm64();
+                default: throw new NotSupportedException();
+            }
+        }
+
+        private string GetTemplateFile()
+        {
+            string tplFile;
+
+            switch (_callConvention)
+            {
+                case PlatformABI.Universal32: tplFile = "Universal32"; break;
+                case PlatformABI.Universal64: tplFile = "Universal64"; break;
+                case PlatformABI.Arm64: tplFile = "Arm64"; break;
+                default: throw new NotSupportedException();
+            };
+            return $"{Application.dataPath}/Scripts/Editor/HybridCLR/Generators/Templates/MethodBridge_{tplFile}.cpp";
+        }
+
+        public IEnumerable<TypeGenInfo> GetGenerateTypes()
+        {
+            return new List<TypeGenInfo>();
+        }
+
+        private MethodBridgeSig CreateMethodBridgeSig(bool isStatic, ParameterInfo returnType, ParameterInfo[] parameters)
+        {
+            var paramInfos = new List<ParamInfo>();
+            if (!isStatic)
+            {
+                // FIXME arm32 is s_i4u4
+                paramInfos.Add(new ParamInfo() { Type = _platformAdaptor.IsArch32 ? TypeInfo.s_i4u4 : TypeInfo.s_i8u8 });
+            }
+            foreach (var paramInfo in parameters)
+            {
+                paramInfos.Add(new ParamInfo() { Type = _platformAdaptor.CreateTypeInfo(paramInfo.ParameterType, false) });
+            }
+            var mbs = new MethodBridgeSig()
+            {
+                ReturnInfo = new ReturnInfo() { Type = returnType != null ? _platformAdaptor.CreateTypeInfo(returnType.ParameterType, true) : TypeInfo.s_void },
+                ParamInfos = paramInfos,
+            };
+            return mbs;
+        }
+
+        private void AddManaged2NativeMethod(MethodBridgeSig method)
+        {
+            if (_managed2nativeMethodSet.Add(method))
+            {
+                method.Init();
+            }
+        }
+
+        private void AddNative2ManagedMethod(MethodBridgeSig method)
+        {
+            if (_native2managedMethodSet.Add(method))
+            {
+                method.Init();
+            }
+        }
+
+        private void AddAdjustThunkMethod(MethodBridgeSig method)
+        {
+            if (_adjustThunkMethodSet.Add(method))
+            {
+                method.Init();
+            }
+        }
+
+        private void ScanType(Type type)
+        {
+            if (type.IsGenericTypeDefinition)
+            {
+                return;
+            }
+            if (_optimized)
+            {
+                if (!type.IsNested)
+                {
+                    if (!type.IsPublic)
+                    {
+                        return;
+                    }
+                }
+                else
+                {
+                    if (type.IsNestedPrivate)
+                    {
+                        return;
+                    }
+                }
+            }
+            var typeDel = typeof(MulticastDelegate);
+            if (typeDel.IsAssignableFrom(type))
+            {
+                var method = type.GetMethod("Invoke");
+                if (method == null)
+                {
+                    //Debug.LogError($"delegate:{typeDel.FullName} Invoke not exists");
+                    return;
+                }
+                // Debug.Log($"== delegate:{type}");
+                var instanceCallMethod = CreateMethodBridgeSig(false, method.ReturnParameter, method.GetParameters());
+                AddManaged2NativeMethod(instanceCallMethod);
+                AddNative2ManagedMethod(instanceCallMethod);
+
+                var staticCallMethod = CreateMethodBridgeSig(true, method.ReturnParameter, method.GetParameters());
+                AddManaged2NativeMethod(staticCallMethod);
+                AddNative2ManagedMethod(staticCallMethod);
+                return;
+            }
+            foreach (var method in type.GetMethods(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public
+| BindingFlags.NonPublic | BindingFlags.CreateInstance | BindingFlags.InvokeMethod | BindingFlags.FlattenHierarchy))
+            {
+                if (method.IsGenericMethodDefinition)
+                {
+                    continue;
+                }
+
+                if (_optimized && (method.IsPrivate || (method.IsAssembly && !method.IsPublic && !method.IsFamily)))
+                {
+                    continue;
+                }
+
+                if (!_optimized || (method.IsFamily || method.IsPublic))
+                {
+                    var m2nMethod = CreateMethodBridgeSig(method.IsStatic, method.ReturnParameter, method.GetParameters());
+                    AddManaged2NativeMethod(m2nMethod);
+
+                    if (type.IsValueType && !method.IsStatic)
+                    {
+                        var adjustThunkMethod = CreateMethodBridgeSig(false, method.ReturnParameter, method.GetParameters());
+                        AddAdjustThunkMethod(adjustThunkMethod);
+                    }
+
+                    if (method.IsVirtual)
+                    {
+                        AddNative2ManagedMethod(m2nMethod);
+                    }
+                }
+            }
+
+            foreach (var method in type.GetConstructors(BindingFlags.Instance | BindingFlags.Public
+| BindingFlags.NonPublic | BindingFlags.CreateInstance | BindingFlags.InvokeMethod | BindingFlags.FlattenHierarchy))
+            {
+                if (_optimized && (method.IsPrivate || (method.IsAssembly && !method.IsPublic && !method.IsFamily)))
+                {
+                    continue;
+                }
+
+                if (!_optimized || (method.IsFamily || method.IsPublic))
+                {
+                    var callMethod = CreateMethodBridgeSig(false, null, method.GetParameters());
+                    AddManaged2NativeMethod(callMethod);
+
+                    if (type.IsValueType && !method.IsStatic)
+                    {
+                        var invokeMethod = CreateMethodBridgeSig(false, null, method.GetParameters());
+                        AddAdjustThunkMethod(invokeMethod);
+                    }
+                }
+            }
+
+            foreach (var subType in type.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic))
+            {
+                ScanType(subType);
+            }
+        }
+
+        public void PrepareFromAssemblies()
+        {
+            foreach (var ass in _assemblies)
+            {
+                if (_hotfixAssemblies.Contains(ass))
+                {
+                    continue;
+                }
+                //Debug.Log("prepare assembly:" + ass.FullName);
+                foreach (var type in ass.GetTypes())
+                {
+                    ScanType(type);
+                }
+            }
+        }
+
+        private void PrepareMethodsFromCustomeGenericTypes()
+        {
+            foreach (var type in GeneratorConfig.PrepareCustomGenericTypes())
+            {
+                ScanType(type);
+            }
+        }
+
+        public void PrepareMethods()
+        {
+            PrepareMethodsFromCustomeGenericTypes();
+
+
+            foreach(var methodSig in _platformAdaptor.IsArch32 ? GeneratorConfig.PrepareCustomMethodSignatures32() : GeneratorConfig.PrepareCustomMethodSignatures64())
+            {
+                var method = MethodBridgeSig.CreateBySignatuer(methodSig);
+                AddManaged2NativeMethod(method);
+                AddAdjustThunkMethod(method);
+            }
+            PrepareFromAssemblies();
+
+            {
+                var sortedMethods = new SortedDictionary<string, MethodBridgeSig>();
+                foreach (var method in _managed2nativeMethodSet)
+                {
+                    sortedMethods.Add(method.CreateCallSigName(), method);
+                }
+                _managed2nativeMethodList = sortedMethods.Values.ToList();
+            }
+            {
+                var sortedMethods = new SortedDictionary<string, MethodBridgeSig>();
+                foreach (var method in _native2managedMethodSet)
+                {
+                    sortedMethods.Add(method.CreateCallSigName(), method);
+                }
+                _native2managedMethodList = sortedMethods.Values.ToList();
+            }
+            {
+                var sortedMethods = new SortedDictionary<string, MethodBridgeSig>();
+                foreach (var method in _adjustThunkMethodSet)
+                {
+                    sortedMethods.Add(method.CreateCallSigName(), method);
+                }
+                _adjustThunkMethodList = sortedMethods.Values.ToList();
+            }
+        }
+
+        public void Generate()
+        {
+            var frr = new FileRegionReplace(GetTemplateFile());
+
+            List<string> lines = new List<string>(20_0000);
+
+            Debug.LogFormat("== managed2native method count:{0}", _managed2nativeMethodList.Count);
+
+            foreach(var method in _managed2nativeMethodList)
+            {
+                _platformAdaptor.GenerateManaged2NativeMethod(method, lines);
+            }
+
+            _platformAdaptor.GenerateManaged2NativeStub(_managed2nativeMethodList, lines);
+
+            Debug.LogFormat("== native2managed method count:{0}", _native2managedMethodList.Count);
+
+            foreach (var method in _native2managedMethodList)
+            {
+                _platformAdaptor.GenerateNative2ManagedMethod(method, lines);
+            }
+
+            _platformAdaptor.GenerateNative2ManagedStub(_native2managedMethodList, lines);
+
+            Debug.LogFormat("== adjustThunk method count:{0}", _adjustThunkMethodList.Count);
+
+            foreach (var method in _adjustThunkMethodList)
+            {
+                _platformAdaptor.GenerateAdjustThunkMethod(method, lines);
+            }
+
+            _platformAdaptor.GenerateAdjustThunkStub(_adjustThunkMethodList, lines);
+
+            frr.Replace("INVOKE_STUB", string.Join("\n", lines));
+
+            Directory.CreateDirectory(Path.GetDirectoryName(_outputFile));
+
+            frr.Commit(_outputFile);
+        }
+
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/MethodBridgeGenerator.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 3171ed79d43e06c4b8c889b0a3f38969
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 156 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/MethodBridgeSig.cs

@@ -0,0 +1,156 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+
+namespace HybridCLR.Editor.Generators.MethodBridge
+{
+    public class MethodBridgeSig : IEquatable<MethodBridgeSig>
+    {
+
+        private readonly static Regex s_sigPattern = new Regex(@"^(v|i1|i2|i4|i8|r4|r8|i16|sr|vf2|vf3|vf4|vd2|vd3|vd4|S\d+|A\d+|B\d+|C\d+)+$");
+
+        public static MethodBridgeSig CreateBySignatuer(string sigName)
+        {
+            var re = s_sigPattern.Match(sigName);
+            if (!re.Success)
+            {
+                throw new ArgumentException($"{sigName} is not valid signature");
+            }
+            
+            var mbs = new MethodBridgeSig() { ParamInfos = new List<ParamInfo>()};
+            var sigs = re.Groups[1].Captures;
+            mbs.ReturnInfo = new ReturnInfo() { Type = CreateTypeInfoBySignature(sigs[0].Value)};
+            for(int i = 1; i < sigs.Count; i++)
+            {
+                mbs.ParamInfos.Add(new ParamInfo() { Type = CreateTypeInfoBySignature(sigs[i].Value)});
+            }
+            return mbs;
+        }
+
+
+        private static TypeInfo CreateTypeInfoBySignature(string sigName)
+        {
+            switch(sigName)
+            {
+                case "v": return new TypeInfo(typeof(void), ParamOrReturnType.VOID);
+                case "i1": return new TypeInfo(typeof(sbyte), ParamOrReturnType.I1_U1);
+                case "i2": return new TypeInfo(typeof(short), ParamOrReturnType.I2_U2);
+                case "i4": return new TypeInfo(typeof(int), ParamOrReturnType.I4_U4);
+                case "i8": return new TypeInfo(typeof(long), ParamOrReturnType.I8_U8);
+                case "r4": return new TypeInfo(typeof(float), ParamOrReturnType.R4);
+                case "r8": return new TypeInfo(typeof(double), ParamOrReturnType.R8);
+                case "i16": return TypeInfo.s_i16;
+                case "sr": return TypeInfo.s_ref;
+                case "vf2": return new TypeInfo(null, ParamOrReturnType.ARM64_HFA_FLOAT_2);
+                case "vf3": return new TypeInfo(null, ParamOrReturnType.ARM64_HFA_FLOAT_3);
+                case "vf4": return new TypeInfo(null, ParamOrReturnType.ARM64_HFA_FLOAT_4);
+                case "vd2": return new TypeInfo(null, ParamOrReturnType.ARM64_HFA_DOUBLE_2);
+                case "vd3": return new TypeInfo(null, ParamOrReturnType.ARM64_HFA_DOUBLE_3);
+                case "vd4": return new TypeInfo(null, ParamOrReturnType.ARM64_HFA_DOUBLE_4);
+                default:
+                    {
+                        if (sigName.StartsWith("S"))
+                        {
+                            return new TypeInfo(null, ParamOrReturnType.STRUCTURE_ALIGN1, int.Parse(sigName.Substring(1)));
+                        }
+                        if (sigName.StartsWith("A"))
+                        {
+                            return new TypeInfo(null, ParamOrReturnType.STRUCTURE_ALIGN2, int.Parse(sigName.Substring(1)));
+                        }
+                        if (sigName.StartsWith("B"))
+                        {
+                            return new TypeInfo(null, ParamOrReturnType.STRUCTURE_ALIGN4, int.Parse(sigName.Substring(1)));
+                        }
+                        if (sigName.StartsWith("C"))
+                        {
+                            return new TypeInfo(null, ParamOrReturnType.STRUCTURE_ALIGN8, int.Parse(sigName.Substring(1)));
+                        }
+                        throw new ArgumentException($"invalid signature:{sigName}");
+                    }
+            }
+        }
+
+
+        public ReturnInfo ReturnInfo { get; set; }
+
+        public List<ParamInfo> ParamInfos { get; set; }
+
+        public void Init()
+        {
+            for(int i = 0; i < ParamInfos.Count; i++)
+            {
+                ParamInfos[i].Index = i;
+            }
+        }
+
+        public string CreateCallSigName()
+        {
+            var n = new StringBuilder();
+            n.Append(ReturnInfo.Type.CreateSigName());
+            foreach(var param in ParamInfos)
+            {
+                n.Append(param.Type.CreateSigName());
+            }
+            return n.ToString();
+        }
+
+        public string CreateInvokeSigName()
+        {
+            var n = new StringBuilder();
+            n.Append(ReturnInfo.Type.CreateSigName());
+            foreach (var param in ParamInfos)
+            {
+                n.Append(param.Type.CreateSigName());
+            }
+            return n.ToString();
+        }
+
+        public override bool Equals(object obj)
+        {
+            return Equals((MethodBridgeSig)obj);
+        }
+
+        public bool Equals(MethodBridgeSig other)
+        {
+            if (other == null)
+            {
+                return false;
+            }
+
+            if (!ReturnInfo.Type.Equals(other.ReturnInfo.Type))
+            {
+                return false;
+            }
+            if (ParamInfos.Count != other.ParamInfos.Count)
+            {
+                return false;
+            }
+            for(int i = 0; i < ParamInfos.Count; i++)
+            {
+                if (!ParamInfos[i].Type.Equals(other.ParamInfos[i].Type))
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        public override int GetHashCode()
+        {
+            int hash = 17;
+
+            hash = hash * 23  + ReturnInfo.Type.GetHashCode();
+
+            foreach(var p in ParamInfos)
+            {
+                hash = hash * 23 + p.Type.GetHashCode();
+            }
+
+            return hash;
+        }
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/MethodBridgeSig.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: cbe63fb39b5bdcc448f3589b475fb5d8
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 44 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/ParamInfo.cs

@@ -0,0 +1,44 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HybridCLR.Editor.Generators.MethodBridge
+{
+
+    public class ParamInfo
+    {
+        public TypeInfo Type { get; set; }
+
+        public int Index { get; set; }
+
+        //public bool IsNative2ManagedByAddress => Type.PorType >= ParamOrReturnType.STRUCT_NOT_PASS_AS_VALUE;
+        public bool IsPassToManagedByAddress => Type.GetParamSlotNum() > 1;
+
+        public bool IsPassToNativeByAddress => Type.PorType == ParamOrReturnType.STRUCTURE_AS_REF_PARAM;
+
+        public string Native2ManagedParamValue(PlatformABI canv)
+        {
+            return IsPassToManagedByAddress ? $"(uint64_t)&__arg{Index}" : $"*(uint64_t*)&__arg{Index}";
+        }
+
+        public string Managed2NativeParamValue(PlatformABI canv)
+        {
+            return IsPassToNativeByAddress ? $"(uint64_t)(localVarBase+argVarIndexs[{Index}])" : $"*({Type.GetTypeName()}*)(localVarBase+argVarIndexs[{Index}])";
+        }
+    }
+
+    public class ReturnInfo
+    {
+        public TypeInfo Type { get; set; }
+
+        public bool IsVoid => Type.PorType == ParamOrReturnType.VOID;
+
+        public int GetParamSlotNum(PlatformABI canv)
+        {
+            return Type.GetParamSlotNum();
+        }
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/ParamInfo.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: c04e163336b93af44b4b565d0ab195e2
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 38 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/ParamOrReturnType.cs

@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HybridCLR.Editor.Generators.MethodBridge
+{
+    public enum ParamOrReturnType
+    {
+        VOID,
+        I1_U1,
+        //U1,
+        I2_U2,
+        //U2,
+        I4_U4,
+        I8_U8,
+        //I_U,
+        R4,
+        R8,
+        ARM64_HFA_FLOAT_2,
+        VALUE_TYPE_SIZE_LESS_EQUAL_8,
+        I16, // 8 < size <= 16
+        STRUCT_NOT_PASS_AS_VALUE, // struct  pass not as value
+        STRUCTURE_AS_REF_PARAM, // size > 16
+        ARM64_HFA_FLOAT_3,
+        ARM64_HFA_FLOAT_4,
+        ARM64_HFA_DOUBLE_2,
+        ARM64_HFA_DOUBLE_3,
+        ARM64_HFA_DOUBLE_4,
+        ARM64_HVA_8,
+        ARM64_HVA_16,
+        STRUCTURE_ALIGN1, // size > 16
+        STRUCTURE_ALIGN2,
+        STRUCTURE_ALIGN4,
+        STRUCTURE_ALIGN8,
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/ParamOrReturnType.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 7886905937fafb64999dc4e358565982
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 9 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/PlatformABI.cs

@@ -0,0 +1,9 @@
+namespace HybridCLR.Editor.Generators.MethodBridge
+{
+    public enum PlatformABI
+    {
+        Universal32,
+        Universal64,
+        Arm64,
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/PlatformABI.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: deee8d06a7f05bf4d9ab4b78f0a8a47c
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 160 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/PlatformAdaptorBase.cs

@@ -0,0 +1,160 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Text;
+using System.Threading.Tasks;
+using UnityEngine;
+
+namespace HybridCLR.Editor.Generators.MethodBridge
+{
+    internal abstract class PlatformAdaptorBase : IPlatformAdaptor
+    {
+        public abstract bool IsArch32 { get; }
+
+        public abstract TypeInfo PointerType { get; }
+
+        protected abstract Dictionary<Type, TypeInfo> CacheTypes { get; }
+
+        protected abstract TypeInfo CreateValueType(Type type, bool returnValue);
+
+        public abstract void GenerateManaged2NativeMethod(MethodBridgeSig method, List<string> lines);
+
+        public abstract void GenerateNative2ManagedMethod(MethodBridgeSig method, List<string> lines);
+
+        public abstract void GenerateAdjustThunkMethod(MethodBridgeSig method, List<string> outputLines);
+
+        private static Dictionary<Type, (int, int)> _typeSizeCache64 = new Dictionary<Type, (int, int)>();
+
+        private static Dictionary<Type, (int, int)> _typeSizeCache32 = new Dictionary<Type, (int, int)>();
+
+        private static ValueTypeSizeAligmentCalculator s_calculator64 = new ValueTypeSizeAligmentCalculator(false);
+
+        private static ValueTypeSizeAligmentCalculator s_calculator32 = new ValueTypeSizeAligmentCalculator(true);
+
+        public static (int Size, int Aligment) ComputeSizeAndAligmentOfArch64(Type t)
+        {
+            if (_typeSizeCache64.TryGetValue(t, out var sizeAndAligment))
+            {
+                return sizeAndAligment;
+            }
+            // all this just to invoke one opcode with no arguments!
+            var method = new DynamicMethod("ComputeSizeOfImpl", typeof(int), Type.EmptyTypes, typeof(PlatformAdaptorBase), false);
+            var gen = method.GetILGenerator();
+            gen.Emit(OpCodes.Sizeof, t);
+            gen.Emit(OpCodes.Ret);
+            int clrSize = ((Func<int>)method.CreateDelegate(typeof(Func<int>)))();
+
+            sizeAndAligment = s_calculator64.SizeAndAligmentOf(t);
+            int customSize = sizeAndAligment.Item1;
+            if (customSize != clrSize)
+            {
+                s_calculator64.SizeAndAligmentOf(t);
+                Debug.LogError($"type:{t} size calculate error. HybridCLR Comput:{sizeAndAligment} CLR:{clrSize}");
+            }
+            _typeSizeCache64.Add(t, sizeAndAligment);
+            return sizeAndAligment;
+        }
+
+        protected static (int Size, int Aligment) ComputeSizeAndAligmentOfArch32(Type t)
+        {
+            if (_typeSizeCache32.TryGetValue(t, out var sa))
+            {
+                return sa;
+            }
+            // all this just to invoke one opcode with no arguments!
+            sa = s_calculator32.SizeAndAligmentOf(t);
+            _typeSizeCache32.Add(t, sa);
+            return sa;
+        }
+
+        public TypeInfo CreateTypeInfo(Type type, bool returnValue)
+        {
+            if (type.IsByRef)
+            {
+                return PointerType;
+            }
+            if (type == typeof(void))
+            {
+                return TypeInfo.s_void;
+            }
+            if (!type.IsValueType)
+            {
+                return PointerType;
+            }
+            if (CacheTypes.TryGetValue(type, out var cache))
+            {
+                return cache;
+            }
+            if (type.IsEnum)
+            {
+                return CreateTypeInfo(type.GetEnumUnderlyingType(), returnValue);
+            }
+            var ti = CreateValueType(type, returnValue);
+            // s_typeInfoCaches.Add(type, ti);
+            return ti;
+        }
+
+        protected static TypeInfo CreateGeneralValueType(Type type, int size, int aligment)
+        {
+            Debug.Assert(size % aligment == 0);
+            switch (aligment)
+            {
+                case 1: return new TypeInfo(type, ParamOrReturnType.STRUCTURE_ALIGN1, size);
+                case 2: return new TypeInfo(type, ParamOrReturnType.STRUCTURE_ALIGN2, size);
+                case 4: return new TypeInfo(type, ParamOrReturnType.STRUCTURE_ALIGN4, size);
+                case 8: return new TypeInfo(type, ParamOrReturnType.STRUCTURE_ALIGN8, size);
+                default: throw new NotSupportedException($"type:{type} not support aligment:{aligment}");
+            }
+        }
+
+        public void GenerateManaged2NativeStub(List<MethodBridgeSig> methods, List<string> lines)
+        {
+            lines.Add($@"
+Managed2NativeMethodInfo hybridclr::interpreter::g_managed2nativeStub[] = 
+{{
+");
+
+            foreach (var method in methods)
+            {
+                lines.Add($"\t{{\"{method.CreateInvokeSigName()}\", __M2N_{method.CreateInvokeSigName()}}},");
+            }
+
+            lines.Add($"\t{{nullptr, nullptr}},");
+            lines.Add("};");
+        }
+
+        public void GenerateNative2ManagedStub(List<MethodBridgeSig> methods, List<string> lines)
+        {
+            lines.Add($@"
+Native2ManagedMethodInfo hybridclr::interpreter::g_native2managedStub[] = 
+{{
+");
+
+            foreach (var method in methods)
+            {
+                lines.Add($"\t{{\"{method.CreateInvokeSigName()}\", (Il2CppMethodPointer)__N2M_{method.CreateInvokeSigName()}}},");
+            }
+
+            lines.Add($"\t{{nullptr, nullptr}},");
+            lines.Add("};");
+        }
+
+        public void GenerateAdjustThunkStub(List<MethodBridgeSig> methods, List<string> lines)
+        {
+            lines.Add($@"
+NativeAdjustThunkMethodInfo hybridclr::interpreter::g_adjustThunkStub[] = 
+{{
+");
+
+            foreach (var method in methods)
+            {
+                lines.Add($"\t{{\"{method.CreateInvokeSigName()}\", (Il2CppMethodPointer)__N2M_AdjustorThunk_{method.CreateCallSigName()}}},");
+            }
+
+            lines.Add($"\t{{nullptr, nullptr}},");
+            lines.Add("};");
+        }
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/PlatformAdaptorBase.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: ebf14107fd82b364cb7d61276d444829
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 208 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/PlatformAdaptor_Arm64.cs

@@ -0,0 +1,208 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using UnityEngine;
+
+namespace HybridCLR.Editor.Generators.MethodBridge
+{
+    internal class PlatformAdaptor_Arm64 : PlatformAdaptorBase
+    {
+
+        private static readonly Dictionary<Type, TypeInfo> s_typeInfoCaches = new Dictionary<Type, TypeInfo>()
+        {
+            { typeof(void), new TypeInfo(typeof(void), ParamOrReturnType.VOID)},
+            { typeof(bool), new TypeInfo(typeof(bool), ParamOrReturnType.I1_U1)},
+            { typeof(byte), new TypeInfo(typeof(byte), ParamOrReturnType.I1_U1)},
+            { typeof(sbyte), new TypeInfo(typeof(sbyte), ParamOrReturnType.I1_U1) },
+            { typeof(short), new TypeInfo(typeof(short), ParamOrReturnType.I2_U2) },
+            { typeof(ushort), new TypeInfo(typeof(ushort), ParamOrReturnType.I2_U2) },
+            { typeof(char), new TypeInfo(typeof(char), ParamOrReturnType.I2_U2) },
+            { typeof(int), new TypeInfo(typeof(int), ParamOrReturnType.I4_U4) },
+            { typeof(uint), new TypeInfo(typeof(uint), ParamOrReturnType.I4_U4) },
+            { typeof(long), new TypeInfo(typeof(long), ParamOrReturnType.I8_U8) },
+            { typeof(ulong), new TypeInfo(typeof(ulong), ParamOrReturnType.I8_U8)},
+            { typeof(float), new TypeInfo(typeof(float), ParamOrReturnType.R4)},
+            { typeof(double), new TypeInfo(typeof(double), ParamOrReturnType.R8)},
+            { typeof(IntPtr), new TypeInfo(null, ParamOrReturnType.I8_U8)},
+            { typeof(UIntPtr), new TypeInfo(null, ParamOrReturnType.I8_U8)},
+            { typeof(Vector2), new TypeInfo(typeof(Vector2), ParamOrReturnType.ARM64_HFA_FLOAT_2) },
+            { typeof(Vector3), new TypeInfo(typeof(Vector3), ParamOrReturnType.ARM64_HFA_FLOAT_3) },
+            { typeof(Vector4), new TypeInfo(typeof(Vector4), ParamOrReturnType.ARM64_HFA_FLOAT_4) },
+            { typeof(System.Numerics.Vector2), new TypeInfo(typeof(System.Numerics.Vector2), ParamOrReturnType.ARM64_HFA_FLOAT_2) },
+            { typeof(System.Numerics.Vector3), new TypeInfo(typeof(System.Numerics.Vector3), ParamOrReturnType.ARM64_HFA_FLOAT_3) },
+            { typeof(System.Numerics.Vector4), new TypeInfo(typeof(System.Numerics.Vector4), ParamOrReturnType.ARM64_HFA_FLOAT_4) },
+        };
+
+        public PlatformABI CallConventionType { get; } = PlatformABI.Universal64;
+
+        public override bool IsArch32 => false;
+
+        public override TypeInfo PointerType => TypeInfo.s_i8u8;
+
+        protected override Dictionary<Type, TypeInfo> CacheTypes => s_typeInfoCaches;
+
+        public class HFATypeInfo
+        {
+            public Type Type { get; set; }
+
+            public int Count { get; set; }
+        }
+
+        private static bool IsNotHFAFastCheck(int typeSize)
+        {
+            return typeSize != 8 && typeSize != 12 && typeSize != 16 && typeSize != 24 && typeSize != 32;
+        }
+
+        private static bool ComputHFATypeInfo0(Type type, HFATypeInfo typeInfo)
+        {
+            var fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
+            foreach (var field in fields)
+            {
+                Type ftype = field.FieldType;
+                if (ftype != typeof(float) && ftype != typeof(double))
+                {
+                    if (!ftype.IsPrimitive && ftype.IsValueType)
+                    {
+                        if (!ComputHFATypeInfo0(ftype, typeInfo))
+                        {
+                            return false;
+                        }
+                    }
+                    else
+                    {
+                        return false;
+                    }
+                }
+                else if (ftype == typeInfo.Type || typeInfo.Type == null)
+                {
+                    typeInfo.Type = ftype;
+                    ++typeInfo.Count;
+                }
+                else
+                {
+                    return false;
+                }
+            }
+            return typeInfo.Count <= 4;
+        }
+
+        public static bool ComputHFATypeInfo(Type type, int typeSize, out HFATypeInfo typeInfo)
+        {
+            typeInfo = new HFATypeInfo();
+            if (IsNotHFAFastCheck(typeSize))
+            {
+                return false;
+            }
+            bool ok = ComputHFATypeInfo0(type, typeInfo);
+            if (ok && typeInfo.Count >= 2 && typeInfo.Count <= 4)
+            {
+                int fieldSize = typeInfo.Type == typeof(float) ? 4 : 8;
+                return typeSize == fieldSize * typeInfo.Count;
+            }
+            return false;
+        }
+
+        protected override TypeInfo CreateValueType(Type type, bool returnValue)
+        {
+            (int typeSize, int typeAligment) = ComputeSizeAndAligmentOfArch64(type);
+            if (ComputHFATypeInfo(type, typeSize, out HFATypeInfo hfaTypeInfo))
+            {
+                if (hfaTypeInfo.Type == typeof(float))
+                {
+                    switch (hfaTypeInfo.Count)
+                    {
+                        case 2: return new TypeInfo(type, ParamOrReturnType.ARM64_HFA_FLOAT_2);
+                        case 3: return new TypeInfo(type, ParamOrReturnType.ARM64_HFA_FLOAT_3);
+                        case 4: return new TypeInfo(type, ParamOrReturnType.ARM64_HFA_FLOAT_4);
+                        default: throw new NotSupportedException();
+                    }
+                }
+                else
+                {
+                    Debug.Assert(hfaTypeInfo.Type == typeof(double));
+                    switch (hfaTypeInfo.Count)
+                    {
+                        case 2: return new TypeInfo(type, ParamOrReturnType.ARM64_HFA_DOUBLE_2);
+                        case 3: return new TypeInfo(type, ParamOrReturnType.ARM64_HFA_DOUBLE_3);
+                        case 4: return new TypeInfo(type, ParamOrReturnType.ARM64_HFA_DOUBLE_4);
+                        default: throw new NotSupportedException();
+                    }
+                }
+            }
+            else
+            {
+                // 64位下结构体内存对齐规则是一样的
+                return CreateArm64GeneralValueType(type, typeSize,returnValue);
+            }
+
+        }
+
+        private TypeInfo CreateArm64GeneralValueType(Type type, int typeSize, bool returnValue)
+        {
+            if (typeSize <= 8)
+            {
+                return TypeInfo.s_i8u8;
+            }
+            if (typeSize <= 16)
+            {
+                return TypeInfo.s_i16;
+            }
+            if (returnValue)
+            {
+                return new TypeInfo(type, ParamOrReturnType.STRUCTURE_ALIGN1, typeSize);
+            }
+            return TypeInfo.s_ref;
+        }
+
+        public override void GenerateManaged2NativeMethod(MethodBridgeSig method, List<string> lines)
+        {
+            int totalQuadWordNum = method.ParamInfos.Count + method.ReturnInfo.GetParamSlotNum(this.CallConventionType);
+            string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" }));
+            string paramNameListStr = string.Join(", ", method.ParamInfos.Select(p => p.Managed2NativeParamValue(this.CallConventionType)).Concat(new string[] { "method" }));
+
+            lines.Add($@"
+static void __M2N_{method.CreateCallSigName()}(const MethodInfo* method, uint16_t* argVarIndexs, StackObject* localVarBase, void* ret)
+{{
+    typedef {method.ReturnInfo.Type.GetTypeName()} (*NativeMethod)({paramListStr});
+    {(!method.ReturnInfo.IsVoid ? $"*({method.ReturnInfo.Type.GetTypeName()}*)ret = " : "")}((NativeMethod)(GetInterpreterDirectlyCallMethodPointer(method)))({paramNameListStr});
+}}
+");
+        }
+
+        public override void GenerateNative2ManagedMethod(MethodBridgeSig method, List<string> lines)
+        {
+            int totalQuadWordNum = method.ParamInfos.Count + method.ReturnInfo.GetParamSlotNum(this.CallConventionType);
+            string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" }));
+            
+            lines.Add($@"
+static {method.ReturnInfo.Type.GetTypeName()} __N2M_{method.CreateCallSigName()}({paramListStr})
+{{
+    StackObject args[{Math.Max(totalQuadWordNum, 1)}] = {{{string.Join(", ", method.ParamInfos.Select(p => p.Native2ManagedParamValue(this.CallConventionType)))} }};
+    StackObject* ret = {(method.ReturnInfo.IsVoid ? "nullptr" : "args + " + method.ParamInfos.Count)};
+    Interpreter::Execute(method, args, ret);
+    {(!method.ReturnInfo.IsVoid ? $"return *({method.ReturnInfo.Type.GetTypeName()}*)ret;" : "")}
+}}
+");
+        }
+
+        public override void GenerateAdjustThunkMethod(MethodBridgeSig method, List<string> lines)
+        {
+            int totalQuadWordNum = method.ParamInfos.Count + method.ReturnInfo.GetParamSlotNum(this.CallConventionType);
+
+            string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" }));
+
+            lines.Add($@"
+static {method.ReturnInfo.Type.GetTypeName()} __N2M_AdjustorThunk_{method.CreateCallSigName()}({paramListStr})
+{{
+    StackObject args[{Math.Max(totalQuadWordNum, 1)}] = {{{string.Join(", ", method.ParamInfos.Select(p => (p.Index == 0 ? $"(uint64_t)(*(uint8_t**)&__arg{p.Index} + sizeof(Il2CppObject))" : p.Native2ManagedParamValue(this.CallConventionType))))} }};
+    StackObject* ret = {(method.ReturnInfo.IsVoid ? "nullptr" : "args + " + method.ParamInfos.Count)};
+    Interpreter::Execute(method, args, ret);
+    {(!method.ReturnInfo.IsVoid ? $"return *({method.ReturnInfo.Type.GetTypeName()}*)ret;" : "")}
+}}
+");
+        }
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/PlatformAdaptor_Arm64.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: bff17a6e8ee060c4eb9ac97fcf30bf78
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 96 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/PlatformAdaptor_Universal32.cs

@@ -0,0 +1,96 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using UnityEngine;
+
+namespace HybridCLR.Editor.Generators.MethodBridge
+{
+    internal class PlatformAdaptor_Universal32 : PlatformAdaptorBase
+    {
+
+        private static readonly Dictionary<Type, TypeInfo> s_typeInfoCaches = new Dictionary<Type, TypeInfo>()
+        {
+            { typeof(void), new TypeInfo(typeof(void), ParamOrReturnType.VOID)},
+            { typeof(bool), new TypeInfo(typeof(bool), ParamOrReturnType.I1_U1)},
+            { typeof(byte), new TypeInfo(typeof(byte), ParamOrReturnType.I1_U1)},
+            { typeof(sbyte), new TypeInfo(typeof(sbyte), ParamOrReturnType.I1_U1) },
+            { typeof(short), new TypeInfo(typeof(short), ParamOrReturnType.I2_U2) },
+            { typeof(ushort), new TypeInfo(typeof(ushort), ParamOrReturnType.I2_U2) },
+            { typeof(char), new TypeInfo(typeof(char), ParamOrReturnType.I2_U2) },
+            { typeof(int), new TypeInfo(typeof(int), ParamOrReturnType.I4_U4) },
+            { typeof(uint), new TypeInfo(typeof(uint), ParamOrReturnType.I4_U4) },
+            { typeof(long), new TypeInfo(typeof(long), ParamOrReturnType.I8_U8) },
+            { typeof(ulong), new TypeInfo(typeof(ulong), ParamOrReturnType.I8_U8)},
+            { typeof(float), new TypeInfo(typeof(float), ParamOrReturnType.R4)},
+            { typeof(double), new TypeInfo(typeof(double), ParamOrReturnType.R8)},
+            { typeof(IntPtr), new TypeInfo(null, ParamOrReturnType.I4_U4)},
+            { typeof(UIntPtr), new TypeInfo(null, ParamOrReturnType.I4_U4)},
+        };
+
+
+        public PlatformABI CallConventionType { get; } = PlatformABI.Universal32;
+
+        public override bool IsArch32 => true;
+
+        public override TypeInfo PointerType => TypeInfo.s_i4u4;
+
+        protected override Dictionary<Type, TypeInfo> CacheTypes => s_typeInfoCaches;
+
+        protected override TypeInfo CreateValueType(Type type, bool returnValue)
+        {
+            (int typeSize, int typeAligment) = ComputeSizeAndAligmentOfArch32(type);
+            int actualAliment = typeAligment <= 4 ? 1 : 8;
+            return CreateGeneralValueType(type, typeSize, actualAliment);
+        }
+
+        public override void GenerateManaged2NativeMethod(MethodBridgeSig method, List<string> lines)
+        {
+            string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" }));
+            string paramNameListStr = string.Join(", ", method.ParamInfos.Select(p => p.Managed2NativeParamValue(this.CallConventionType)).Concat(new string[] { "method" }));
+
+            lines.Add($@"
+static void __M2N_{method.CreateCallSigName()}(const MethodInfo* method, uint16_t* argVarIndexs, StackObject* localVarBase, void* ret)
+{{
+    typedef {method.ReturnInfo.Type.GetTypeName()} (*NativeMethod)({paramListStr});
+    {(!method.ReturnInfo.IsVoid ? $"*({method.ReturnInfo.Type.GetTypeName()}*)ret = " : "")}((NativeMethod)(GetInterpreterDirectlyCallMethodPointer(method)))({paramNameListStr});
+}}
+");
+        }
+        public override void GenerateNative2ManagedMethod(MethodBridgeSig method, List<string> lines)
+        {
+            int totalQuadWordNum = method.ParamInfos.Count + method.ReturnInfo.GetParamSlotNum(this.CallConventionType);
+            string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" }));
+            
+            lines.Add($@"
+static {method.ReturnInfo.Type.GetTypeName()} __N2M_{method.CreateCallSigName()}({paramListStr})
+{{
+    StackObject args[{Math.Max(totalQuadWordNum, 1)}] = {{{string.Join(", ", method.ParamInfos.Select(p => p.Native2ManagedParamValue(this.CallConventionType)))} }};
+    StackObject* ret = {(method.ReturnInfo.IsVoid ? "nullptr" : "args + " + method.ParamInfos.Count)};
+    Interpreter::Execute(method, args, ret);
+    {(!method.ReturnInfo.IsVoid ? $"return *({method.ReturnInfo.Type.GetTypeName()}*)ret;" : "")}
+}}
+");
+        }
+        public override void GenerateAdjustThunkMethod(MethodBridgeSig method, List<string> lines)
+        {
+            int totalQuadWordNum = method.ParamInfos.Count + method.ReturnInfo.GetParamSlotNum(this.CallConventionType);
+
+            string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" }));
+
+            lines.Add($@"
+static {method.ReturnInfo.Type.GetTypeName()} __N2M_AdjustorThunk_{method.CreateCallSigName()}({paramListStr})
+{{
+    StackObject args[{Math.Max(totalQuadWordNum, 1)}] = {{{string.Join(", ", method.ParamInfos.Select(p => (p.Index == 0 ? $"(uint64_t)(*(uint8_t**)&__arg{p.Index} + sizeof(Il2CppObject))" : p.Native2ManagedParamValue(this.CallConventionType))))} }};
+    StackObject* ret = {(method.ReturnInfo.IsVoid ? "nullptr" : "args + " + method.ParamInfos.Count)};
+    Interpreter::Execute(method, args, ret);
+    {(!method.ReturnInfo.IsVoid ? $"return *({method.ReturnInfo.Type.GetTypeName()}*)ret;" : "")}
+}}
+");
+
+        }
+    }
+
+}

+ 11 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/PlatformAdaptor_Universal32.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: fb741900113b22443a2054ddba6b131b
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 189 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/PlatformAdaptor_Universal64.cs

@@ -0,0 +1,189 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using UnityEngine;
+
+namespace HybridCLR.Editor.Generators.MethodBridge
+{
+    internal class PlatformAdaptor_Universal64 : PlatformAdaptorBase
+    {
+
+        private static readonly Dictionary<Type, TypeInfo> s_typeInfoCaches = new Dictionary<Type, TypeInfo>()
+        {
+            { typeof(void), new TypeInfo(typeof(void), ParamOrReturnType.VOID)},
+            { typeof(bool), new TypeInfo(typeof(bool), ParamOrReturnType.I1_U1)},
+            { typeof(byte), new TypeInfo(typeof(byte), ParamOrReturnType.I1_U1)},
+            { typeof(sbyte), new TypeInfo(typeof(sbyte), ParamOrReturnType.I1_U1) },
+            { typeof(short), new TypeInfo(typeof(short), ParamOrReturnType.I2_U2) },
+            { typeof(ushort), new TypeInfo(typeof(ushort), ParamOrReturnType.I2_U2) },
+            { typeof(char), new TypeInfo(typeof(char), ParamOrReturnType.I2_U2) },
+            { typeof(int), new TypeInfo(typeof(int), ParamOrReturnType.I4_U4) },
+            { typeof(uint), new TypeInfo(typeof(uint), ParamOrReturnType.I4_U4) },
+            { typeof(long), new TypeInfo(typeof(long), ParamOrReturnType.I8_U8) },
+            { typeof(ulong), new TypeInfo(typeof(ulong), ParamOrReturnType.I8_U8)},
+            { typeof(float), new TypeInfo(typeof(float), ParamOrReturnType.R4)},
+            { typeof(double), new TypeInfo(typeof(double), ParamOrReturnType.R8)},
+            { typeof(IntPtr), new TypeInfo(null, ParamOrReturnType.I8_U8)},
+            { typeof(UIntPtr), new TypeInfo(null, ParamOrReturnType.I8_U8)},
+            { typeof(Vector2), new TypeInfo(typeof(Vector2), ParamOrReturnType.ARM64_HFA_FLOAT_2) },
+            { typeof(Vector3), new TypeInfo(typeof(Vector3), ParamOrReturnType.ARM64_HFA_FLOAT_3) },
+            { typeof(Vector4), new TypeInfo(typeof(Vector4), ParamOrReturnType.ARM64_HFA_FLOAT_4) },
+            { typeof(System.Numerics.Vector2), new TypeInfo(typeof(System.Numerics.Vector2), ParamOrReturnType.ARM64_HFA_FLOAT_2) },
+            { typeof(System.Numerics.Vector3), new TypeInfo(typeof(System.Numerics.Vector3), ParamOrReturnType.ARM64_HFA_FLOAT_3) },
+            { typeof(System.Numerics.Vector4), new TypeInfo(typeof(System.Numerics.Vector4), ParamOrReturnType.ARM64_HFA_FLOAT_4) },
+        };
+
+        public PlatformABI CallConventionType { get; } = PlatformABI.Universal64;
+
+        public override bool IsArch32 => false;
+
+        public override TypeInfo PointerType => TypeInfo.s_i8u8;
+
+        protected override Dictionary<Type, TypeInfo> CacheTypes => s_typeInfoCaches;
+
+        public class HFATypeInfo
+        {
+            public Type Type { get; set; }
+
+            public int Count { get; set; }
+        }
+
+        private static bool IsNotHFAFastCheck(int typeSize)
+        {
+            return typeSize != 8 && typeSize != 12 && typeSize != 16 && typeSize != 24 && typeSize != 32;
+        }
+
+        private static bool ComputHFATypeInfo0(Type type, HFATypeInfo typeInfo)
+        {
+            var fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
+            foreach (var field in fields)
+            {
+                Type ftype = field.FieldType;
+                if (ftype != typeof(float) && ftype != typeof(double))
+                {
+                    if (!ftype.IsPrimitive && ftype.IsValueType)
+                    {
+                        if (!ComputHFATypeInfo0(ftype, typeInfo))
+                        {
+                            return false;
+                        }
+                    }
+                    else
+                    {
+                        return false;
+                    }
+                }
+                else if (ftype == typeInfo.Type || typeInfo.Type == null)
+                {
+                    typeInfo.Type = ftype;
+                    ++typeInfo.Count;
+                }
+                else
+                {
+                    return false;
+                }
+            }
+            return typeInfo.Count <= 4;
+        }
+
+        public static bool ComputHFATypeInfo(Type type, int typeSize, out HFATypeInfo typeInfo)
+        {
+            typeInfo = new HFATypeInfo();
+            if (IsNotHFAFastCheck(typeSize))
+            {
+                return false;
+            }
+            bool ok = ComputHFATypeInfo0(type, typeInfo);
+            if (ok && typeInfo.Count >= 2 && typeInfo.Count <= 4)
+            {
+                int fieldSize = typeInfo.Type == typeof(float) ? 4 : 8;
+                return typeSize == fieldSize * typeInfo.Count;
+            }
+            return false;
+        }
+
+        protected override TypeInfo CreateValueType(Type type, bool returnValue)
+        {
+            (int typeSize, int typeAligment) = ComputeSizeAndAligmentOfArch64(type);
+            if (ComputHFATypeInfo(type, typeSize, out HFATypeInfo hfaTypeInfo))
+            {
+                if (hfaTypeInfo.Type == typeof(float))
+                {
+                    switch (hfaTypeInfo.Count)
+                    {
+                        case 2: return new TypeInfo(type, ParamOrReturnType.ARM64_HFA_FLOAT_2);
+                        case 3: return new TypeInfo(type, ParamOrReturnType.ARM64_HFA_FLOAT_3);
+                        case 4: return new TypeInfo(type, ParamOrReturnType.ARM64_HFA_FLOAT_4);
+                        default: throw new NotSupportedException();
+                    }
+                }
+                else
+                {
+                    Debug.Assert(hfaTypeInfo.Type == typeof(double));
+                    switch (hfaTypeInfo.Count)
+                    {
+                        case 2: return new TypeInfo(type, ParamOrReturnType.ARM64_HFA_DOUBLE_2);
+                        case 3: return new TypeInfo(type, ParamOrReturnType.ARM64_HFA_DOUBLE_3);
+                        case 4: return new TypeInfo(type, ParamOrReturnType.ARM64_HFA_DOUBLE_4);
+                        default: throw new NotSupportedException();
+                    }
+                }
+            }
+            else
+            {
+                // 64位下结构体内存对齐规则是一样的
+                return CreateGeneralValueType(type, typeSize, 1 /*typeAligment*/);
+            }
+
+        }
+
+        public override void GenerateManaged2NativeMethod(MethodBridgeSig method, List<string> lines)
+        {
+            int totalQuadWordNum = method.ParamInfos.Count + method.ReturnInfo.GetParamSlotNum(this.CallConventionType);
+
+            string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" }));
+            string paramTypeListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()}").Concat(new string[] { "const MethodInfo*" })); ;
+            string paramNameListStr = string.Join(", ", method.ParamInfos.Select(p => p.Managed2NativeParamValue(this.CallConventionType)).Concat(new string[] { "method" }));
+
+            lines.Add($@"
+static void __M2N_{method.CreateCallSigName()}(const MethodInfo* method, uint16_t* argVarIndexs, StackObject* localVarBase, void* ret)
+{{
+    typedef {method.ReturnInfo.Type.GetTypeName()} (*NativeMethod)({paramListStr});
+    {(!method.ReturnInfo.IsVoid ? $"*({method.ReturnInfo.Type.GetTypeName()}*)ret = " : "")}((NativeMethod)(GetInterpreterDirectlyCallMethodPointer(method)))({paramNameListStr});
+}}
+");
+        }
+        public override void GenerateNative2ManagedMethod(MethodBridgeSig method, List<string> lines)
+        {
+            int totalQuadWordNum = method.ParamInfos.Count + method.ReturnInfo.GetParamSlotNum(this.CallConventionType);
+            string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" }));
+            lines.Add($@"
+static {method.ReturnInfo.Type.GetTypeName()} __N2M_{method.CreateCallSigName()}({paramListStr})
+{{
+    StackObject args[{Math.Max(totalQuadWordNum, 1)}] = {{{string.Join(", ", method.ParamInfos.Select(p => p.Native2ManagedParamValue(this.CallConventionType)))} }};
+    StackObject* ret = {(method.ReturnInfo.IsVoid ? "nullptr" : "args + " + method.ParamInfos.Count)};
+    Interpreter::Execute(method, args, ret);
+    {(!method.ReturnInfo.IsVoid ? $"return *({method.ReturnInfo.Type.GetTypeName()}*)ret;" : "")}
+}}
+");
+        }
+
+        public override void GenerateAdjustThunkMethod(MethodBridgeSig method, List<string> lines)
+        {
+            int totalQuadWordNum = method.ParamInfos.Count + method.ReturnInfo.GetParamSlotNum(this.CallConventionType);
+            string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" }));
+            lines.Add($@"
+static {method.ReturnInfo.Type.GetTypeName()} __N2M_AdjustorThunk_{method.CreateCallSigName()}({paramListStr})
+{{
+    StackObject args[{Math.Max(totalQuadWordNum, 1)}] = {{{string.Join(", ", method.ParamInfos.Select(p => (p.Index == 0 ? $"(uint64_t)(*(uint8_t**)&__arg{p.Index} + sizeof(Il2CppObject))" : p.Native2ManagedParamValue(this.CallConventionType))))} }};
+    StackObject* ret = {(method.ReturnInfo.IsVoid ? "nullptr" : "args + " + method.ParamInfos.Count)};
+    Interpreter::Execute(method, args, ret);
+    {(!method.ReturnInfo.IsVoid ? $"return *({method.ReturnInfo.Type.GetTypeName()}*)ret;" : "")}
+}}
+");
+        }
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/PlatformAdaptor_Universal64.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 26324be9505c9f54996bcbb62ba49132
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 19 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/SignatureProviderAttribute.cs

@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HybridCLR.Editor.Generators.MethodBridge
+{
+    [AttributeUsage(AttributeTargets.Method)]
+    public class SignatureProviderAttribute : Attribute
+    {
+        public List<PlatformABI> Platforms { get; }
+
+        public SignatureProviderAttribute(params PlatformABI[] platforms)
+        {
+            Platforms = new List<PlatformABI>(platforms);
+        }
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/SignatureProviderAttribute.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 50c5ec2d43d3fda4a8b8cfa75cb37a74
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 132 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/TypeInfo.cs

@@ -0,0 +1,132 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using UnityEngine;
+
+namespace HybridCLR.Editor.Generators.MethodBridge
+{
+    public class TypeInfo : IEquatable<TypeInfo>
+    {
+
+        public static readonly TypeInfo s_void = new TypeInfo(typeof(void), ParamOrReturnType.VOID);
+        public static readonly TypeInfo s_i4u4 = new TypeInfo(null, ParamOrReturnType.I4_U4);
+        public static readonly TypeInfo s_i8u8 = new TypeInfo(null, ParamOrReturnType.I8_U8);
+        public static readonly TypeInfo s_i16 = new TypeInfo(null, ParamOrReturnType.I16);
+        public static readonly TypeInfo s_ref = new TypeInfo(null, ParamOrReturnType.STRUCTURE_AS_REF_PARAM);
+
+        public TypeInfo(Type type, ParamOrReturnType portype)
+        {
+            this.Type = type;
+            PorType = portype;
+            Size = 0;
+        }
+
+        public TypeInfo(Type type, ParamOrReturnType portype, int size)
+        {
+            this.Type = type;
+            PorType = portype;
+            Size = size;
+        }
+
+        public Type Type { get; }
+
+        public ParamOrReturnType PorType { get; }
+
+        public int Size { get; }
+
+        public bool Equals(TypeInfo other)
+        {
+            return PorType == other.PorType && Size == other.Size;
+        }
+
+        public override bool Equals(object obj)
+        {
+            return Equals((TypeInfo)obj);
+        }
+
+        public override int GetHashCode()
+        {
+            return (int)PorType * 23 + Size;
+        }
+
+        public string CreateSigName()
+        {
+            switch (PorType)
+            {
+                case ParamOrReturnType.VOID: return "v";
+                case ParamOrReturnType.I1_U1: return "i1";
+                case ParamOrReturnType.I2_U2: return "i2";
+                case ParamOrReturnType.I4_U4: return "i4";
+                case ParamOrReturnType.I8_U8: return "i8";
+                case ParamOrReturnType.R4: return "r4";
+                case ParamOrReturnType.R8: return "r8";
+                case ParamOrReturnType.I16: return "i16";
+                case ParamOrReturnType.STRUCTURE_AS_REF_PARAM: return "sr";
+                case ParamOrReturnType.ARM64_HFA_FLOAT_2: return "vf2";
+                case ParamOrReturnType.ARM64_HFA_FLOAT_3: return "vf3";
+                case ParamOrReturnType.ARM64_HFA_FLOAT_4: return "vf4";
+                case ParamOrReturnType.ARM64_HFA_DOUBLE_2: return "vd2";
+                case ParamOrReturnType.ARM64_HFA_DOUBLE_3: return "vd3";
+                case ParamOrReturnType.ARM64_HFA_DOUBLE_4: return "vd4";
+                case ParamOrReturnType.STRUCTURE_ALIGN1: return "S" + Size;
+                case ParamOrReturnType.STRUCTURE_ALIGN2: return "A" + Size;
+                case ParamOrReturnType.STRUCTURE_ALIGN4: return "B" + Size;
+                case ParamOrReturnType.STRUCTURE_ALIGN8: return "C" + Size;
+                default: throw new NotSupportedException(PorType.ToString());
+            };
+        }
+
+        public string GetTypeName()
+        {
+            switch (PorType)
+            {
+                case ParamOrReturnType.VOID: return "void";
+                case ParamOrReturnType.I1_U1: return "int8_t";
+                case ParamOrReturnType.I2_U2: return "int16_t";
+                case ParamOrReturnType.I4_U4: return "int32_t";
+                case ParamOrReturnType.I8_U8: return "int64_t";
+                case ParamOrReturnType.R4: return "float";
+                case ParamOrReturnType.R8: return "double";
+                case ParamOrReturnType.I16: return "ValueTypeSize16";
+                case ParamOrReturnType.STRUCTURE_AS_REF_PARAM: return "uint64_t";
+                case ParamOrReturnType.ARM64_HFA_FLOAT_2: return "HtVector2f";
+                case ParamOrReturnType.ARM64_HFA_FLOAT_3: return "HtVector3f";
+                case ParamOrReturnType.ARM64_HFA_FLOAT_4: return "HtVector4f";
+                case ParamOrReturnType.ARM64_HFA_DOUBLE_2: return "HtVector2d";
+                case ParamOrReturnType.ARM64_HFA_DOUBLE_3: return "HtVector3d";
+                case ParamOrReturnType.ARM64_HFA_DOUBLE_4: return "HtVector4d";
+                case ParamOrReturnType.STRUCTURE_ALIGN1: return $"ValueTypeSize<{Size}>";
+                case ParamOrReturnType.STRUCTURE_ALIGN2: return $"ValueTypeSizeAlign2<{Size}>";
+                case ParamOrReturnType.STRUCTURE_ALIGN4: return $"ValueTypeSizeAlign4<{Size}>";
+                case ParamOrReturnType.STRUCTURE_ALIGN8: return $"ValueTypeSizeAlign8<{Size}>";
+                default: throw new NotImplementedException(PorType.ToString());
+            };
+        }
+        public int GetParamSlotNum()
+        {
+            switch (PorType)
+            {
+                case ParamOrReturnType.VOID: return 0;
+                case ParamOrReturnType.I16: return 2;
+                case ParamOrReturnType.STRUCTURE_AS_REF_PARAM: return 1;
+                case ParamOrReturnType.ARM64_HFA_FLOAT_3: return 2;
+                case ParamOrReturnType.ARM64_HFA_FLOAT_4: return 2;
+                case ParamOrReturnType.ARM64_HFA_DOUBLE_2: return 2;
+                case ParamOrReturnType.ARM64_HFA_DOUBLE_3: return 3;
+                case ParamOrReturnType.ARM64_HFA_DOUBLE_4: return 4;
+                case ParamOrReturnType.ARM64_HVA_8:
+                case ParamOrReturnType.ARM64_HVA_16: throw new NotSupportedException();
+                case ParamOrReturnType.STRUCTURE_ALIGN1:
+                case ParamOrReturnType.STRUCTURE_ALIGN2:
+                case ParamOrReturnType.STRUCTURE_ALIGN4:
+                case ParamOrReturnType.STRUCTURE_ALIGN8: return (Size + 7) / 8;
+                default:
+                    {
+                        Debug.Assert(PorType < ParamOrReturnType.STRUCT_NOT_PASS_AS_VALUE);
+                        Debug.Assert(Size <= 8);
+                        return 1;
+                    }
+            }
+        }
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/TypeInfo.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 5afd7344483678a4abcb56158fd1442d
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 148 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/ValueTypeSizeAligmentCalculator.cs

@@ -0,0 +1,148 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HybridCLR.Editor.Generators.MethodBridge
+{
+
+
+	public class ValueTypeSizeAligmentCalculator
+	{
+		private static Dictionary<string, int> s_primitives = new Dictionary<string, int>(14) {
+			{ "Byte", 1 },
+			{ "SByte", 1 },
+			{ "Boolean", 1 },
+			{ "Int16", 2 },
+			{ "UInt16", 2 },
+			{ "Char", 2 },
+			{ "Int32", 4 },
+			{ "UInt32", 4 },
+			{ "Single", 4 },
+			{ "Int64", 8 },
+			{ "UInt64", 8 },
+			{ "Double", 8 },
+			//{ "IntPtr", _referenceSize },	// so rule return the same results
+			//{ "UIntPtr", _referenceSize },	// on 32 and 64 bits architectures
+		};
+
+		public ValueTypeSizeAligmentCalculator(bool arch32)
+        {
+			_referenceSize = arch32 ? 4 : 8;
+        }
+
+		// actually we should use IntPtr.Size but that would make the rule
+		// return different results on 64 bits systems
+		private readonly int _referenceSize;
+
+		// Note: Needs to be public since this is being tested by our unit tests
+
+
+		private static bool IsIgnoreField(FieldInfo field)
+        {
+			var ignoreAttr = field.GetCustomAttributes().Where(a => a.GetType().Name == "IgnoreAttribute").FirstOrDefault();
+			if (ignoreAttr == null)
+            {
+				return false;
+            }
+
+			var p = ignoreAttr.GetType().GetProperty("DoesNotContributeToSize");
+			return (bool)p.GetValue(ignoreAttr);
+		}
+
+		private (int Size, int Aligment) SizeAndAligmentOfStruct(Type type)
+		{
+			int totalSize = 0;
+			int packAligment = 8;
+			int maxAligment = 1;
+
+			StructLayoutAttribute sa = type.StructLayoutAttribute;
+			if (sa != null && sa.Pack > 0)
+            {
+				packAligment = sa.Pack;
+            }
+			bool useSLSize = true;
+			foreach (FieldInfo field in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
+			{
+				// add size of the type
+				var (fs, fa) = SizeAndAligmentOf(field.FieldType);
+				fa = Math.Min(fa, packAligment);
+				if (fa > maxAligment)
+                {
+					maxAligment = fa;
+				}
+				if (IsIgnoreField(field))
+				{
+					continue;
+				}
+				if (sa != null && sa.Value == LayoutKind.Explicit)
+				{
+					int offset = field.GetCustomAttribute<FieldOffsetAttribute>().Value;
+					totalSize = Math.Max(totalSize, offset + fs);
+					if (offset > sa.Size)
+					{
+						useSLSize = false;
+					}
+                }
+				else
+				{
+					if (totalSize % fa != 0)
+					{
+						totalSize = (totalSize + fa - 1) / fa * fa;
+					}
+					totalSize += fs;
+					if (sa != null && sa.Value == LayoutKind.Sequential && totalSize > sa.Size)
+                    {
+						useSLSize = false;
+                    }
+				}
+			}
+			if (totalSize == 0)
+            {
+				totalSize = maxAligment;
+			}
+			if (totalSize % maxAligment != 0)
+			{
+				totalSize = (totalSize + maxAligment - 1) / maxAligment * maxAligment;
+			}
+			if (sa != null && sa.Size > 0)
+			{
+				if (/*sa.Value == LayoutKind.Explicit &&*/ useSLSize)
+				{
+					totalSize = sa.Size;
+					while(totalSize % maxAligment != 0)
+                    {
+						maxAligment /= 2;
+                    }
+				}
+			}
+			return (totalSize, maxAligment);
+		}
+
+		public (int Size, int Aligment) SizeAndAligmentOf(Type type)
+		{
+			if (type.IsByRef || !type.IsValueType || type.IsArray)
+				return (_referenceSize, _referenceSize);
+
+			// list based on Type.IsPrimitive
+			if (type.Namespace == "System")
+			{
+				if (s_primitives.TryGetValue(type.Name, out var size))
+				{
+					return (size, size);
+				}
+				if (type.Name == "IntPtr" || type.Name == "UIntPtr")
+                {
+					return (_referenceSize, _referenceSize);
+                }
+			}
+			if (type.IsEnum)
+				return SizeAndAligmentOf(type.GetEnumUnderlyingType());
+
+			return SizeAndAligmentOfStruct(type);
+		}
+	}
+}

+ 11 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/MethodBridge/ValueTypeSizeAligmentCalculator.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 49b3dbcebadb1b543a42e01afec07ed1
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 38 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/TemplateUtil.cs

@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HybridCLR.Editor.Generators
+{
+    public static class TemplateUtil
+    {
+        public static string EscapeIntegerName(int i)
+        {
+            return i >= 0 ? i.ToString() : "minus" + (-i);
+        }
+
+        public static string ReplaceRegion(string resultText, string region, string replaceContent)
+        {
+            int startIndex = resultText.IndexOf("//!!!{{" + region);
+            if (startIndex == -1)
+            {
+                throw new Exception($"region:{region} start not find");
+            }
+            int endIndex = resultText.IndexOf("//!!!}}" + region);
+            if (endIndex == -1)
+            {
+                throw new Exception($"region:{region} end not find");
+            }
+            int replaceStart = resultText.IndexOf('\n', startIndex);
+            int replaceEnd = resultText.LastIndexOf('\n', endIndex);
+            if (replaceStart == -1 || replaceEnd == -1)
+            {
+                throw new Exception($"region:{region} not find");
+            }
+            resultText = resultText.Substring(0, replaceStart) + "\n" + replaceContent + "\n" + resultText.Substring(replaceEnd);
+            return resultText;
+        }
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/TemplateUtil.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 32ec2cc1cf5c468468308fa6308fba19
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/Templates.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 3a1563e7820e5b648a6a6691677f564c
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 22 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/Templates/MethodBridge_Arm64.cpp

@@ -0,0 +1,22 @@
+#include "MethodBridge.h"
+
+#include <codegen/il2cpp-codegen-metadata.h>
+#include "vm/ClassInlines.h"
+#include "vm/Object.h"
+#include "vm/Class.h"
+
+#include "../metadata/MetadataModule.h"
+#include "../metadata/MetadataUtil.h"
+
+#include "Interpreter.h"
+#include "MemoryUtil.h"
+#include "InstrinctDef.h"
+
+using namespace hybridclr::interpreter;
+using hybridclr::GetInterpreterDirectlyCallMethodPointer;
+
+#if HYBRIDCLR_ABI_ARM_64
+//!!!{{INVOKE_STUB
+
+//!!!}}INVOKE_STUB
+#endif

+ 27 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/Templates/MethodBridge_Arm64.cpp.meta

@@ -0,0 +1,27 @@
+fileFormatVersion: 2
+guid: 7e694feed8374f94380fe48bb70e9be1
+PluginImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  iconMap: {}
+  executionOrder: {}
+  defineConstraints: []
+  isPreloaded: 0
+  isOverridable: 0
+  isExplicitlyReferenced: 0
+  validateReferences: 1
+  platformData:
+  - first:
+      Any: 
+    second:
+      enabled: 0
+      settings: {}
+  - first:
+      Editor: Editor
+    second:
+      enabled: 1
+      settings:
+        DefaultValueInitialized: true
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 22 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/Templates/MethodBridge_Universal32.cpp

@@ -0,0 +1,22 @@
+#include "MethodBridge.h"
+
+#include <codegen/il2cpp-codegen-metadata.h>
+#include "vm/ClassInlines.h"
+#include "vm/Object.h"
+#include "vm/Class.h"
+
+#include "../metadata/MetadataModule.h"
+#include "../metadata/MetadataUtil.h"
+
+#include "Interpreter.h"
+#include "MemoryUtil.h"
+#include "InstrinctDef.h"
+
+using namespace hybridclr::interpreter;
+using hybridclr::GetInterpreterDirectlyCallMethodPointer;
+
+#if HYBRIDCLR_ABI_UNIVERSAL_32
+//!!!{{INVOKE_STUB
+
+//!!!}}INVOKE_STUB
+#endif

+ 27 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/Templates/MethodBridge_Universal32.cpp.meta

@@ -0,0 +1,27 @@
+fileFormatVersion: 2
+guid: 27135a158cd4b5049966f6f46d15ab10
+PluginImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  iconMap: {}
+  executionOrder: {}
+  defineConstraints: []
+  isPreloaded: 0
+  isOverridable: 0
+  isExplicitlyReferenced: 0
+  validateReferences: 1
+  platformData:
+  - first:
+      Any: 
+    second:
+      enabled: 0
+      settings: {}
+  - first:
+      Editor: Editor
+    second:
+      enabled: 1
+      settings:
+        DefaultValueInitialized: true
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 22 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/Templates/MethodBridge_Universal64.cpp

@@ -0,0 +1,22 @@
+#include "MethodBridge.h"
+
+#include <codegen/il2cpp-codegen-metadata.h>
+#include "vm/ClassInlines.h"
+#include "vm/Object.h"
+#include "vm/Class.h"
+
+#include "../metadata/MetadataModule.h"
+#include "../metadata/MetadataUtil.h"
+
+#include "Interpreter.h"
+#include "MemoryUtil.h"
+#include "InstrinctDef.h"
+
+using namespace hybridclr::interpreter;
+using hybridclr::GetInterpreterDirectlyCallMethodPointer;
+
+#if HYBRIDCLR_ABI_UNIVERSAL_64
+//!!!{{INVOKE_STUB
+
+//!!!}}INVOKE_STUB
+#endif

+ 27 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Generators/Templates/MethodBridge_Universal64.cpp.meta

@@ -0,0 +1,27 @@
+fileFormatVersion: 2
+guid: ca76fdf59c873e441aa5043ad00d4537
+PluginImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  iconMap: {}
+  executionOrder: {}
+  defineConstraints: []
+  isPreloaded: 0
+  isOverridable: 0
+  isExplicitlyReferenced: 0
+  validateReferences: 1
+  platformData:
+  - first:
+      Any: 
+    second:
+      enabled: 0
+      settings: {}
+  - first:
+      Editor: Editor
+    second:
+      enabled: 1
+      settings:
+        DefaultValueInitialized: true
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Installer.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: a4a3d499c10d66f43af10a859e276a8f
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 295 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Installer/InstallerController.cs

@@ -0,0 +1,295 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using UnityEditor;
+using UnityEngine;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Diagnostics;
+
+using Debug = UnityEngine.Debug;
+using System.Text.RegularExpressions;
+
+namespace HybridCLR.Editor.Installer
+{
+    public enum InstallErrorCode
+    {
+        Ok,
+        Il2CppInstallPathNotMatchIl2CppBranch,
+        Il2CppInstallPathNotExists,
+        NotIl2CppPath,
+    }
+
+    public partial class InstallerController
+    {
+        private string m_Il2CppInstallDirectory;
+
+        public string Il2CppInstallDirectory
+        {
+            get
+            {
+                return m_Il2CppInstallDirectory;
+            }
+            set
+            {
+                m_Il2CppInstallDirectory = value?.Replace('\\', '/');
+                if (!string.IsNullOrEmpty(m_Il2CppInstallDirectory))
+                {
+                    EditorPrefs.SetString("UnityInstallDirectory", m_Il2CppInstallDirectory);
+                }
+            }
+        }
+
+        private string GetIl2CppPlusBranchByUnityVersion(string unityVersion)
+        {
+            if (unityVersion.Contains("2019."))
+            {
+                return "2019.4.40";
+            }
+            if (unityVersion.Contains("2020."))
+            {
+                return "2020.3.33";
+            }
+            if (unityVersion.Contains("2021."))
+            {
+                return "2021.3.1";
+            }
+            return "not support";
+        }
+
+        public string Il2CppBranch => GetIl2CppPlusBranchByUnityVersion(Application.unityVersion);
+
+        public string InitLocalIl2CppBatFile => Application.dataPath + "/../HybridCLRData/init_local_il2cpp_data.bat";
+
+        public string InitLocalIl2CppBashFile => Application.dataPath + "/../HybridCLRData/init_local_il2cpp_data.sh";
+
+        public InstallerController()
+        {
+            PrepareIl2CppInstallPath();
+        }
+
+        private static readonly Regex s_unityVersionPat = new Regex(@"(\d+)\.(\d+)\.(\d+)");
+
+        public const int min2019_4_CompatibleMinorVersion = 40;
+        public const int min2020_3_CompatibleMinorVersion = 21;
+        public const int min2021_3_CompatibleMinorVersion = 0;
+
+        private bool TryParseMinorVersion(string installDir, out (int Major, int Minor1, int Minor2) unityVersion)
+        {
+            var matches = s_unityVersionPat.Matches(installDir);
+            if (matches.Count != 1)
+            {
+                unityVersion = default;
+                return false;
+            }
+            Match match = matches[0];
+            // Debug.Log($"capture count:{match.Groups.Count} {match.Groups[1].Value} {match.Groups[2].Value}");
+            int major = int.Parse(match.Groups[1].Value);
+            int minor1 = int.Parse(match.Groups[2].Value);
+            int minor2 = int.Parse(match.Groups[3].Value);
+            unityVersion = (major, minor1, minor2);
+            return true;
+        }
+
+        public string GetMinCompatibleVersion(string branch)
+        {
+            switch(branch)
+            {
+                case "2019.4.40": return $"2019.4.{min2019_4_CompatibleMinorVersion}";
+                case "2020.3.33": return $"2020.3.{min2020_3_CompatibleMinorVersion}";
+                case "2021.3.1": return $"2021.3.{min2021_3_CompatibleMinorVersion}";
+                default: throw new Exception($"not support version:{branch}");
+            }
+        }
+
+        private bool IsComaptibleWithIl2CppPlusBranch(string branch, string installDir)
+        {
+            if (!TryParseMinorVersion(installDir, out var unityVersion))
+            {
+                return false;
+            }
+            switch(branch)
+            {
+                case "2019.4.40":
+                    {
+                        if (unityVersion.Major != 2019 || unityVersion.Minor1 != 4)
+                        {
+                            return false;
+                        }
+                        return unityVersion.Minor2 >= min2019_4_CompatibleMinorVersion;
+                    }
+                case "2020.3.33":
+                    {
+                        if (unityVersion.Major != 2020 || unityVersion.Minor1 != 3)
+                        {
+                            return false;
+                        }
+                        return unityVersion.Minor2 >= min2020_3_CompatibleMinorVersion;
+                    }
+                case "2021.3.1":
+                    { 
+                        if (unityVersion.Major != 2021 || unityVersion.Minor1 != 3)
+                        {
+                            return false;
+                        }
+                        return unityVersion.Minor2 >= min2021_3_CompatibleMinorVersion;
+                    }
+                default: throw new Exception($"not support il2cpp_plus branch:{branch}");
+            }
+        }
+
+        void PrepareIl2CppInstallPath()
+        {
+#if UNITY_EDITOR_OSX
+            m_Il2CppInstallDirectory = EditorPrefs.GetString("Il2CppInstallDirectory");
+            if (CheckValidIl2CppInstallDirectory(Il2CppBranch, m_Il2CppInstallDirectory) == InstallErrorCode.Ok)
+            {
+                return;
+            }
+            var il2cppBranch = Il2CppBranch;
+            var curAppInstallPath = EditorApplication.applicationPath;
+            if (IsComaptibleWithIl2CppPlusBranch(il2cppBranch, curAppInstallPath))
+            {
+                Il2CppInstallDirectory = $"{curAppInstallPath}/Contents/il2cpp";
+                return;
+            }
+            string unityHubRootDir = Directory.GetParent(curAppInstallPath).Parent.Parent.ToString();
+            foreach (var unityInstallDir in Directory.GetDirectories(unityHubRootDir, "*", SearchOption.TopDirectoryOnly))
+            {
+                Debug.Log("nity install dir:" + unityInstallDir);
+                if (IsComaptibleWithIl2CppPlusBranch(il2cppBranch, unityInstallDir))
+                {
+                    Il2CppInstallDirectory = $"{unityInstallDir}/Unity.app/Contents/il2cpp";
+                    return;
+                }
+            }
+
+            Il2CppInstallDirectory = $"{curAppInstallPath}/Contents/il2cpp";
+#else
+            m_Il2CppInstallDirectory = EditorPrefs.GetString("Il2CppInstallDirectory");
+            if (CheckValidIl2CppInstallDirectory(Il2CppBranch, m_Il2CppInstallDirectory) == InstallErrorCode.Ok)
+            {
+                return;
+            }
+            var il2cppBranch = Il2CppBranch;
+            var curAppInstallPath = EditorApplication.applicationPath;
+            if (IsComaptibleWithIl2CppPlusBranch(il2cppBranch, curAppInstallPath))
+            {
+                Il2CppInstallDirectory = $"{Directory.GetParent(curAppInstallPath)}/Data/il2cpp";
+                return;
+            }
+            string unityHubRootDir = Directory.GetParent(curAppInstallPath).Parent.Parent.ToString();
+            // Debug.Log("unity hub root dir:" + unityHubRootDir);
+            foreach (var unityInstallDir in Directory.GetDirectories(unityHubRootDir, "*", SearchOption.TopDirectoryOnly))
+            {
+                // Debug.Log("Unity install dir:" + unityInstallDir);
+                if (IsComaptibleWithIl2CppPlusBranch(il2cppBranch, unityInstallDir))
+                {
+                    Il2CppInstallDirectory = $"{unityInstallDir}/Editor/Data/il2cpp";
+                    return;
+                }
+            }
+
+            Il2CppInstallDirectory = $"{Directory.GetParent(curAppInstallPath)}/Data/il2cpp";
+#endif
+        }
+
+        public void InitHybridCLR(string il2cppBranch, string il2cppInstallPath)
+        {
+            if (CheckValidIl2CppInstallDirectory(il2cppBranch, il2cppInstallPath) != InstallErrorCode.Ok)
+            {
+                Debug.LogError($"请正确设置 il2cpp 安装目录");
+                return;
+            }
+
+            if (Application.platform == RuntimePlatform.WindowsEditor)
+            {
+                RunInitLocalIl2CppDataBat(il2cppBranch, il2cppInstallPath);
+            }
+            else
+            {
+                RunInitLocalIl2CppDataBash(il2cppBranch, il2cppInstallPath);
+            }
+        }
+
+        public bool HasInstalledHybridCLR()
+        {
+            return Directory.Exists($"{BuildConfig.LocalIl2CppDir}/libil2cpp/hybridclr");
+        }
+
+        public InstallErrorCode CheckValidIl2CppInstallDirectory(string il2cppBranch, string installDir)
+        {
+            installDir = installDir.Replace('\\', '/');
+            if (!Directory.Exists(installDir))
+            {
+                return InstallErrorCode.Il2CppInstallPathNotExists;
+            }
+
+            if (!IsComaptibleWithIl2CppPlusBranch(il2cppBranch, installDir))
+            {
+                return InstallErrorCode.Il2CppInstallPathNotMatchIl2CppBranch;
+            }
+
+            if (!installDir.EndsWith("/il2cpp"))
+            {
+                return InstallErrorCode.NotIl2CppPath;
+            }
+
+            return InstallErrorCode.Ok;
+        }
+
+        public bool IsUnity2019(string branch)
+        {
+            return branch.Contains("2019.");
+        }
+
+        private void RunInitLocalIl2CppDataBat(string il2cppBranch, string il2cppInstallPath)
+        {
+            using (Process p = new Process())
+            {
+                p.StartInfo.WorkingDirectory = BuildConfig.HybridCLRDataDir;
+                p.StartInfo.FileName = InitLocalIl2CppBatFile;
+                p.StartInfo.UseShellExecute = true;
+                p.StartInfo.Arguments = $"{il2cppBranch} \"{il2cppInstallPath}\"";
+                p.Start();
+                p.WaitForExit();
+                if (IsUnity2019(il2cppBranch))
+                {
+                    string srcIl2CppDll = $"{BuildConfig.HybridCLRDataDir}/ModifiedUnityAssemblies/2019.4.40/Unity.IL2CPP.dll";
+                    string dstIl2CppDll = $"{BuildConfig.LocalIl2CppDir}/build/deploy/net471/Unity.IL2CPP.dll";
+                    File.Copy(srcIl2CppDll, dstIl2CppDll, true);
+                    Debug.Log($"copy {srcIl2CppDll} => {dstIl2CppDll}");
+                }
+                if (p.ExitCode == 0 && HasInstalledHybridCLR())
+                {
+                    Debug.Log("安装成功!!!");
+                }
+            }
+        }
+
+        public void RunInitLocalIl2CppDataBash(string il2cppBranch, string il2cppInstallPath)
+        {
+            using (Process p = new Process())
+            {
+                p.StartInfo.WorkingDirectory = Application.dataPath + "/../HybridCLRData";
+                p.StartInfo.FileName = "/bin/bash";
+                p.StartInfo.UseShellExecute = false;
+                p.StartInfo.CreateNoWindow = true;
+                p.StartInfo.Arguments = $"init_local_il2cpp_data.sh {il2cppBranch} '{il2cppInstallPath}'";
+                p.StartInfo.RedirectStandardOutput = true;
+                p.StartInfo.RedirectStandardError = true;
+                p.Start();
+                string output = p.StandardOutput.ReadToEnd();
+                Debug.Log(output);
+                p.WaitForExit();
+                if (HasInstalledHybridCLR())
+                {
+                    Debug.Log("安装成功!!!");
+                }
+            }
+        }
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Installer/InstallerController.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 44c8627d126b30d4e9560b1f738264ca
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 116 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Installer/InstallerWindow.cs

@@ -0,0 +1,116 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using UnityEditor ;
+using UnityEngine;
+ 
+
+namespace HybridCLR.Editor.Installer
+{
+    public class InstallerWindow : EditorWindow
+    {
+        private InstallerController m_Controller;
+
+        [MenuItem("HybridCLR/Installer...", false, 0)]
+        private static void Open()
+        {
+            InstallerWindow window = GetWindow<InstallerWindow>("HybridCLR Installer", true);
+            window.minSize = new Vector2(800f, 500f);
+        }
+
+        private void OnEnable()
+        {
+            m_Controller = new InstallerController();
+        }
+
+        private void OnGUI()
+        {
+            string minCompatibleVersion = m_Controller.GetMinCompatibleVersion(m_Controller.Il2CppBranch);
+            GUI.enabled = true;
+            GUILayout.Space(10f);
+            EditorGUILayout.LabelField("=======================说明====================");
+            EditorGUILayout.LabelField(
+                $"你所在项目的Unity版本可以与il2cpp_plus版本:{m_Controller.Il2CppBranch} 不一样。\n"
+                + $"如果你的Unity的版本号 >= {minCompatibleVersion}, 可以直接安装。\n"
+                + $"如果你的Unity的版本号 < {minCompatibleVersion}, \n"
+                + $"由于安装HybridCLR时需要从il2cpp_plus对应版本{m_Controller.Il2CppBranch}(而不是你项目版本)拷贝il2cpp目录,\n"
+                + $"你必须同时安装相应版本 {m_Controller.Il2CppBranch} 才能完成安装", EditorStyles.wordWrappedLabel);
+            EditorGUILayout.LabelField("==============================================");
+            GUILayout.Space(10f);
+
+            EditorGUILayout.BeginVertical("box");
+            EditorGUILayout.LabelField($"安装状态:{(m_Controller.HasInstalledHybridCLR() ? "已安装" : "未安装")}", EditorStyles.boldLabel);
+            GUILayout.Space(5f);
+            EditorGUILayout.LabelField($"当前Unity版本: {Application.unityVersion},匹配的il2cpp_plus分支: {m_Controller.Il2CppBranch}");
+            GUISelectUnityDirectory($"il2cpp_plus分支对应Unity版本的il2cpp路径", "Select");
+            GUILayout.Space(10f);
+            GUIInstallButton("安装最新HybridCLR插件代码到本项目", "安装", InitHybridCLR);
+            EditorGUILayout.EndVertical();
+        }
+
+        private void GUIInstallButton(string content, string button, Action onClick)
+        {
+            EditorGUILayout.BeginHorizontal();
+            EditorGUILayout.LabelField(content);
+            GUI.enabled = m_Controller.CheckValidIl2CppInstallDirectory(m_Controller.Il2CppBranch, m_Controller.Il2CppInstallDirectory) == InstallErrorCode.Ok;
+            if (GUILayout.Button(button, GUILayout.Width(100)))
+            {
+                onClick?.Invoke();
+                GUIUtility.ExitGUI();
+            }
+            GUI.enabled = true;
+            EditorGUILayout.EndHorizontal();
+            
+        }
+
+
+        private void GUISelectUnityDirectory(string content, string selectButton)
+        {
+            EditorGUILayout.BeginHorizontal();
+            EditorGUILayout.LabelField(content, GUILayout.MaxWidth(300));
+            string il2cppInstallDirectory = m_Controller.Il2CppInstallDirectory = EditorGUILayout.TextField(m_Controller.Il2CppInstallDirectory);
+            if (GUILayout.Button(selectButton, GUILayout.Width(100)))
+            {
+                string temp = EditorUtility.OpenFolderPanel(content, m_Controller.Il2CppInstallDirectory, string.Empty);
+                if (!string.IsNullOrEmpty(temp))
+                {
+                    il2cppInstallDirectory = m_Controller.Il2CppInstallDirectory = temp;
+                }
+            }
+            EditorGUILayout.EndHorizontal();
+
+            InstallErrorCode err = m_Controller.CheckValidIl2CppInstallDirectory(m_Controller.Il2CppBranch, il2cppInstallDirectory);
+            switch (err)
+            {
+                case InstallErrorCode.Ok:
+                    {
+                        break;
+                    }
+                case InstallErrorCode.Il2CppInstallPathNotExists:
+                    {
+                        EditorGUILayout.HelpBox("li2cpp 路径不存在", MessageType.Error);
+                        break;
+                    }
+                case InstallErrorCode.Il2CppInstallPathNotMatchIl2CppBranch:
+                    {
+                        EditorGUILayout.HelpBox($"il2cpp 版本不兼容,最小版本为 {m_Controller.GetMinCompatibleVersion(m_Controller.Il2CppBranch)}", MessageType.Error);
+                        break;
+                    }
+                case InstallErrorCode.NotIl2CppPath:
+                    {
+                        EditorGUILayout.HelpBox($"当前选择的路径不是il2cpp目录(必须类似 xxx/il2cpp)", MessageType.Error);
+                        break;
+                    }
+                default: throw new Exception($"not support {err}");
+            }
+        }
+
+        private void InitHybridCLR()
+        {
+            m_Controller.InitHybridCLR(m_Controller.Il2CppBranch, m_Controller.Il2CppInstallDirectory);
+        }
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/Editor/HybridCLR/Installer/InstallerWindow.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 959fbf0bb06629542969354505189240
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 131 - 0
Unity/Assets/Scripts/Editor/HybridCLR/MethodBridgeHelper.cs

@@ -0,0 +1,131 @@
+using HybridCLR.Editor.Generators;
+using HybridCLR.Editor.Generators.MethodBridge;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using UnityEditor;
+using UnityEngine;
+
+namespace HybridCLR.Editor
+{
+    internal class MethodBridgeHelper
+    {
+
+        private static void CleanIl2CppBuildCache()
+        {
+            string il2cppBuildCachePath = BuildConfig.Il2CppBuildCacheDir;
+            if (!Directory.Exists(il2cppBuildCachePath))
+            {
+                return;
+            }
+            Debug.Log($"clean il2cpp build cache:{il2cppBuildCachePath}");
+            Directory.Delete(il2cppBuildCachePath, true);
+        }
+
+        private static List<Assembly> CollectDependentAssemblies(Dictionary<string, Assembly> allAssByName, List<Assembly> dlls)
+        {
+            for(int i = 0; i < dlls.Count; i++)
+            {
+                Assembly ass = dlls[i];
+                foreach (var depAssName in ass.GetReferencedAssemblies())
+                {
+                    if (!allAssByName.ContainsKey(depAssName.Name))
+                    {
+                        Debug.Log($"ignore ref assembly:{depAssName.Name}");
+                        continue;
+                    }
+                    Assembly depAss = allAssByName[depAssName.Name];
+                    if (!dlls.Contains(depAss))
+                    {
+                        dlls.Add(depAss);
+                    }
+                }
+            }
+            return dlls;
+        }
+
+        private static List<Assembly> GetScanAssembiles()
+        {
+            var allAssByName = new Dictionary<string, Assembly>();
+            foreach(var ass in AppDomain.CurrentDomain.GetAssemblies())
+            {
+                allAssByName[ass.GetName().Name] = ass;
+            }
+            //CompileDllHelper.CompileDllActiveBuildTarget();
+
+            var rootAssemblies = BuildConfig.HotUpdateAssemblies
+                .Select(dll => Path.GetFileNameWithoutExtension(dll)).Concat(GeneratorConfig.GetExtraAssembiles())
+                .Where(name => allAssByName.ContainsKey(name)).Select(name => allAssByName[name]).ToList();
+            //var rootAssemblies = GeneratorConfig.GetExtraAssembiles()
+            //    .Where(name => allAssByName.ContainsKey(name)).Select(name => allAssByName[name]).ToList();
+            CollectDependentAssemblies(allAssByName, rootAssemblies);
+            rootAssemblies.Sort((a, b) => a.GetName().Name.CompareTo(b.GetName().Name));
+            Debug.Log($"assembly count:{rootAssemblies.Count}");
+            foreach(var ass in rootAssemblies)
+            {
+                //Debug.Log($"scan assembly:{ass.GetName().Name}");
+            }
+            return rootAssemblies;
+        }
+
+        private static void GenerateMethodBridgeCppFile(PlatformABI platform, string fileName, bool optimized)
+        {
+            string outputFile = $"{BuildConfig.MethodBridgeCppDir}/{fileName}.cpp";
+            var g = new MethodBridgeGenerator(new MethodBridgeGeneratorOptions()
+            {
+                CallConvention = platform,
+                HotfixAssemblies = BuildConfig.HotUpdateAssemblies.Select(name =>
+                    AppDomain.CurrentDomain.GetAssemblies().First(ass => ass.GetName().Name + ".dll" == name)).ToList(),
+                AllAssemblies = optimized ? GetScanAssembiles() : AppDomain.CurrentDomain.GetAssemblies().ToList(),
+                OutputFile = outputFile,
+                Optimized = optimized,
+            });
+
+            g.PrepareMethods();
+            g.Generate();
+            Debug.LogFormat("== output:{0} ==", outputFile);
+            CleanIl2CppBuildCache();
+        }
+
+        //[MenuItem("HybridCLR/MethodBridge/Arm64")]
+        //public static void MethodBridge_Arm64()
+        //{
+        //    GenerateMethodBridgeCppFile(PlatformABI.Arm64, "MethodBridge_Arm64");
+        //}
+
+        //[MenuItem("HybridCLR/MethodBridge/Universal64")]
+        //public static void MethodBridge_Universal64()
+        //{
+        //    GenerateMethodBridgeCppFile(PlatformABI.Universal64, "MethodBridge_Universal64");
+        //}
+
+        //[MenuItem("HybridCLR/MethodBridge/Universal32")]
+        //public static void MethodBridge_Universal32()
+        //{
+        //    GenerateMethodBridgeCppFile(PlatformABI.Universal32, "MethodBridge_Universal32");
+        //}
+
+        public static void GenerateMethodBridgeAll(bool optimized)
+        {
+            GenerateMethodBridgeCppFile(PlatformABI.Arm64, "MethodBridge_Arm64", optimized);
+            GenerateMethodBridgeCppFile(PlatformABI.Universal64, "MethodBridge_Universal64", optimized);
+            GenerateMethodBridgeCppFile(PlatformABI.Universal32, "MethodBridge_Universal32", optimized);
+        }
+
+        [MenuItem("HybridCLR/MethodBridge/All_高度精简")]
+        public static void MethodBridge_All_Optimized()
+        {
+            GenerateMethodBridgeAll(true);
+        }
+
+        [MenuItem("HybridCLR/MethodBridge/All_完整(新手及开发期推荐)")]
+        public static void MethodBridge_All_Normal()
+        {
+            GenerateMethodBridgeAll(false);
+        }
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/Editor/HybridCLR/MethodBridgeHelper.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 18beea79433bdce44af834574cd9c212
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 19 - 0
Unity/Assets/Scripts/Mono/CodeLoader.cs

@@ -42,7 +42,26 @@ namespace ET
 					
 					assembly = Assembly.Load(assBytes, pdbBytes);
 
+					// wolong补充元数据用
+					if (!Define.IsEditor)
+					{
+						Dictionary<string, UnityEngine.Object> dllMetas = AssetsBundleHelper.LoadBundle("assetbundlesourcedata.unity3d");
+						foreach (var kv in dllMetas)
+						{
+							unsafe
+							{
+								byte[] dllBytes = ((TextAsset)kv.Value).bytes;
+								fixed (byte* ptr = dllBytes)
+								{
+									// 加载assembly对应的dll,会自动为它hook。一旦aot泛型函数的native函数不存在,用解释器版本代码
+									int err = HybridCLR.RuntimeApi.LoadMetadataForAOTAssembly((IntPtr)ptr, dllBytes.Length);
+									Log.Info($"LoadMetadataForAOTAssembly:{kv.Key}. ret:{err}");
+								}
+							}
 
+						}
+					}
+					
 					Dictionary<string, Type> types = AssemblyHelper.GetAssemblyTypes(typeof (Game).Assembly, this.assembly);
 					EventSystem.Instance.Add(types);
 					

+ 8 - 0
Unity/Assets/Scripts/Mono/HybridCLR.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: c207591866a61d640b9cdb82f7d6f58a
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 272 - 0
Unity/Assets/Scripts/Mono/HybridCLR/RefTypes.cs

@@ -0,0 +1,272 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Threading.Tasks;
+using UnityEngine;
+using UnityEngine.Scripting;
+
+[assembly: Preserve]
+enum IntEnum : int
+{
+    A,
+    B,
+}
+
+public class MyComparer<T> : Comparer<T>
+{
+    public override int Compare(T x, T y)
+    {
+        return 0;
+    }
+}
+
+class MyStateMachine : IAsyncStateMachine
+{
+    public void MoveNext()
+    {
+        throw new NotImplementedException();
+    }
+
+    public void SetStateMachine(IAsyncStateMachine stateMachine)
+    {
+        throw new NotImplementedException();
+    }
+}
+
+public class RefTypes : MonoBehaviour
+{
+    List<Type> GetTypes()
+    {
+        return new List<Type>
+        {
+            typeof(Queue<long>)
+        };
+    }
+
+    // Start is called before the first frame update
+    void Start()
+    {
+        Debug.Log(GetTypes());
+        GameObject.Instantiate<GameObject>(null);
+        Instantiate<GameObject>(null, null);
+        Instantiate<GameObject>(null, null, false);
+        Instantiate<GameObject>(null, new Vector3(), new Quaternion());
+        Instantiate<GameObject>(null, new Vector3(), new Quaternion(), null);
+    }
+
+    public void RefNumerics()
+    {
+        var a = new System.Numerics.BigInteger();
+        a.ToString();
+    }
+
+    void RefMisc()
+    {
+
+    }
+
+    void RefComparers()
+    {
+        var a = new object[]
+        {
+            new MyComparer<int>(),
+            new MyComparer<long>(),
+            new MyComparer<float>(),
+            new MyComparer<double>(),
+            new MyComparer<object>(),
+        };
+
+        new MyComparer<int>().Compare(default, default);
+        new MyComparer<long>().Compare(default, default);
+        new MyComparer<float>().Compare(default, default);
+        new MyComparer<double>().Compare(default, default);
+        new MyComparer<object>().Compare(default, default);
+
+        object b = EqualityComparer<int>.Default;
+        b = EqualityComparer<long>.Default;
+        b = EqualityComparer<float>.Default;
+        b = EqualityComparer<double>.Default;
+        b = EqualityComparer<object>.Default;
+    }
+
+
+    void RefNullable()
+    {
+        // nullable
+        object b = null;
+        int? a = 5;
+        b = a;
+        int d = (int?)b ?? 7;
+        int e = (int)b;
+        a = d;
+        b = a;
+        b = Enumerable.Range(0, 1).Reverse().Take(1).TakeWhile(x => true).Skip(1).All(x => true);
+        b = new WaitForSeconds(1f);
+        b = new WaitForSecondsRealtime(1f);
+        b = new WaitForFixedUpdate();
+        b = new WaitForEndOfFrame();
+        b = new WaitWhile(() => true);
+        b = new WaitUntil(() => true);
+    }
+
+    void RefContainer()
+    {
+        //int, long,float,double, IntEnum,object
+        List<object> b = new List<object>()
+        {
+
+        };
+    }
+
+    void RefAsyncMethod()
+    {
+        var stateMachine = new MyStateMachine();
+
+        TaskAwaiter aw = default;
+        var c0 = new AsyncTaskMethodBuilder();
+        c0.Start(ref stateMachine);
+        c0.AwaitUnsafeOnCompleted(ref aw, ref stateMachine);
+        c0.SetException(null);
+        c0.SetResult();
+
+        var c1 = new AsyncTaskMethodBuilder();
+        c1.Start(ref stateMachine);
+        c1.AwaitUnsafeOnCompleted(ref aw, ref stateMachine);
+        c1.SetException(null);
+        c1.SetResult();
+
+        var c2 = new AsyncTaskMethodBuilder<bool>();
+        c2.Start(ref stateMachine);
+        c2.AwaitUnsafeOnCompleted(ref aw, ref stateMachine);
+        c2.SetException(null);
+        c2.SetResult(default);
+
+        var c3 = new AsyncTaskMethodBuilder<int>();
+        c3.Start(ref stateMachine);
+        c3.AwaitUnsafeOnCompleted(ref aw, ref stateMachine);
+        c3.SetException(null);
+        c3.SetResult(default);
+
+        var c4 = new AsyncTaskMethodBuilder<long>();
+        c4.Start(ref stateMachine);
+        c4.AwaitUnsafeOnCompleted(ref aw, ref stateMachine);
+        c4.SetException(null);
+
+        var c5 = new AsyncTaskMethodBuilder<float>();
+        c5.Start(ref stateMachine);
+        c5.AwaitUnsafeOnCompleted(ref aw, ref stateMachine);
+        c5.SetException(null);
+        c5.SetResult(default);
+
+        var c6 = new AsyncTaskMethodBuilder<double>();
+        c6.Start(ref stateMachine);
+        c6.AwaitUnsafeOnCompleted(ref aw, ref stateMachine);
+        c6.SetException(null);
+        c6.SetResult(default);
+
+        var c7 = new AsyncTaskMethodBuilder<object>();
+        c7.Start(ref stateMachine);
+        c7.AwaitUnsafeOnCompleted(ref aw, ref stateMachine);
+        c7.SetException(null);
+        c7.SetResult(default);
+
+        var c8 = new AsyncTaskMethodBuilder<IntEnum>();
+        c8.Start(ref stateMachine);
+        c8.AwaitUnsafeOnCompleted(ref aw, ref stateMachine);
+        c8.SetException(null);
+        c8.SetResult(default);
+
+        var c9 = new AsyncVoidMethodBuilder();
+        var b = AsyncVoidMethodBuilder.Create();
+        c9.Start(ref stateMachine);
+        c9.AwaitUnsafeOnCompleted(ref aw, ref stateMachine);
+        c9.SetException(null);
+        c9.SetResult();
+        Debug.Log(b);
+    }
+
+    void RefNewtonsoftJson()
+    {
+        //AotHelper.EnsureList<int>();
+        //AotHelper.EnsureList<long>();
+        //AotHelper.EnsureList<float>();
+        //AotHelper.EnsureList<double>();
+        //AotHelper.EnsureList<string>();
+        //AotHelper.EnsureDictionary<int, int>();
+        //AotHelper.EnsureDictionary<int, string>();
+    }
+
+    public void RefProtobufNet()
+    {
+        
+    }
+
+    public void RefGoogleProtobuf()
+    {
+    }
+
+    class TestTable
+    {
+        public int Id { get; set; }
+
+        public string Name { get; set; }
+    }
+
+    public void RefSQLite()
+    {
+    }
+
+    public static async void TestAsync3()
+    {
+        Debug.Log("async task 1");
+        await Task.Delay(10);
+        Debug.Log("async task 2");
+    }
+
+    public static int Main_1()
+    {
+        Debug.Log("hello,hybridclr");
+
+        var task = Task.Run(async () =>
+        {
+            await TestAsync2();
+        });
+
+        task.Wait();
+
+        Debug.Log("async task end");
+        Debug.Log("async task end2");
+
+        return 0;
+    }
+
+    public static async Task TestAsync2()
+    {
+        Debug.Log("async task 1");
+        await Task.Delay(3000);
+        Debug.Log("async task 2");
+    }
+
+    // Update is called once per frame
+    void Update()
+    {
+        TestAsync();
+    }
+
+    public static int TestAsync()
+    {
+        var t0 = Task.Run(async () =>
+        {
+            await Task.Delay(10);
+        });
+        t0.Wait();
+        var task = Task.Run(async () =>
+        {
+            await Task.Delay(10);
+            return 100;
+        });
+        Debug.Log(task.Result);
+        return 0;
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/Mono/HybridCLR/RefTypes.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 17ed08ce9aa3e1f449ab4f2f79ecb0cb
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 36 - 0
Unity/Assets/Scripts/Mono/HybridCLR/RuntimeApi.cs

@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HybridCLR
+{
+    public static class RuntimeApi
+    {
+#if UNITY_STANDALONE_WIN
+        private const string dllName = "GameAssembly";
+#elif UNITY_IOS || UNITY_STANDALONE_OSX || UNITY_WEBGL
+    private const string dllName = "__Internal";
+#else
+    private const string dllName = "il2cpp";
+#endif
+
+        [DllImport(dllName, EntryPoint = "RuntimeApi_LoadMetadataForAOTAssembly")]
+        public static extern int LoadMetadataForAOTAssembly(IntPtr dllBytes, int dllSize);
+
+        [DllImport(dllName, EntryPoint = "RuntimeApi_GetInterpreterThreadObjectStackSize")]
+        public static extern int GetInterpreterThreadObjectStackSize();
+
+        [DllImport(dllName, EntryPoint = "RuntimeApi_SetInterpreterThreadObjectStackSize")]
+        public static extern void SetInterpreterThreadObjectStackSize(int size);
+
+        [DllImport(dllName, EntryPoint = "RuntimeApi_GetInterpreterThreadFrameStackSize")]
+        public static extern int GetInterpreterThreadFrameStackSize();
+
+        [DllImport(dllName, EntryPoint = "RuntimeApi_SetInterpreterThreadFrameStackSize")]
+        public static extern void SetInterpreterThreadFrameStackSize(int size);
+    }
+}

+ 11 - 0
Unity/Assets/Scripts/Mono/HybridCLR/RuntimeApi.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 3c8b35876046d1747ae7d62244ec693f
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 12 - 1
Unity/Assets/link.xml

@@ -2,5 +2,16 @@
     <assembly fullname="Unity.Mono" preserve="all"/>
     <assembly fullname="Unity.ThirdParty" preserve="all"/>
     <assembly fullname="UnityEngine" preserve="all"/>
-  <assembly fullname="System" preserve="all"/>
+    <assembly fullname="System" preserve="all"/>
+    <assembly fullname="CommandLine" preserve="all"/>
+    <assembly fullname="ICSharpCode.SharpZipLib" preserve="all"/>
+    <assembly fullname="MongoDB.Bson" preserve="all"/>
+    <assembly fullname="System.Runtime.CompilerServices.Unsafe" preserve="all"/>
+    <assembly fullname="UnityEngine.AnimationModule" preserve="all" />
+    <assembly fullname="System.Net.Http" preserve="all" />
+    <assembly fullname="mscorlib" preserve="all" />
+    <assembly fullname="UnityEngine.AssetBundleModule" preserve="all" />
+    <assembly fullname="NLog" preserve="all" />
+    <assembly fullname="UnityEngine.CoreModule" preserve="all" />
+    <assembly fullname="UnityEngine.InputLegacyModule" preserve="all" />
 </linker>

BIN
Unity/HybridCLRData/ModifiedUnityAssemblies/2019.4.40/Unity.IL2CPP.dll


BIN
Unity/HybridCLRData/ModifiedUnityAssemblies/2021.3.1/UnityEditor.CoreModule-Mac.dll


BIN
Unity/HybridCLRData/ModifiedUnityAssemblies/2021.3.1/UnityEditor.CoreModule-Win.dll


BIN
Unity/HybridCLRData/ModifiedUnityAssemblies/2021.3.6/UnityEditor.CoreModule-Mac.dll


BIN
Unity/HybridCLRData/ModifiedUnityAssemblies/2021.3.6/UnityEditor.CoreModule-Win.dll


+ 22 - 0
Unity/HybridCLRData/README.md

@@ -0,0 +1,22 @@
+# 使用说明
+
+这个目录主要包含
+
+- huatuo相关仓库
+- 本地il2cpp目录
+- 其他生成的目录
+
+## 安装huatuo
+
+正常情况下,安装huatuo需要替换Unity安装目录下libil2cpp目录为huatuo版本的实现,但Unity允许使用环境变量UNITY_IL2CPP_PATH自定义%IL2CPP_PATH%的位置。
+因此我们不修改原始的il2cpp目录,直接在本地创建huatuo版本的il2cpp,并让环境变量指向它
+
+安装流程
+
+- 酌情修改 init_local_il2cpp_data.bat(或.sh)文件中代码
+  - `set IL2CPP_BRANCH=2020.3.33` 改成你的版本(目前只有2020.3.33或2021.3.1)
+  - `set IL2CPP_PATH=<你的Unity editor的il2cpp目录的路径>` 改成你的Unity安装目录
+- 运行 init_local_il2cpp_data.bat 或.sh 文件 创建本地il2cpp目录,即 LocalIl2CppData 目录。
+
+如果看到初始化成功,表示运行成功。否则请参照文档,对应 .bat或.sh文件,自己查找错误原因。
+

+ 88 - 0
Unity/HybridCLRData/iOSBuild/CMakeLists.txt

@@ -0,0 +1,88 @@
+# file: CMakeList.txt
+cmake_minimum_required(VERSION 3.0)
+set(CMAKE_OSX_DEPLOYMENT_TARGET iOS)
+
+set(TMP $ENV{HUATUO_IL2CPP_SOURCE_DIR})
+if ( NOT TMP )
+    message(FATAL_ERROR "需要设置环境变量: HUATUO_IL2CPP_SOURCE_DIR")
+else()
+    message(STATUS "unity il2cpp 路径为: ${TMP}")
+endif()
+
+set(SDK_VERSION $ENV{IPHONESIMULATOR_VERSION})
+if ( SDK_VERSION )
+    message(STATUS "使用iPhoneSimulator版本:" ${SDK_VERSION})
+else()
+    message(STATUS "当前使用默认版本的iPhoneSimulator,可以通过设置环境变量IPHONESIMULATOR_VERSION,指定版本")
+endif()
+
+project(il2cpp)
+execute_process(COMMAND sh gen_lump.sh ${PROJECT_BINARY_DIR} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
+
+add_subdirectory(external)
+add_subdirectory(objective)
+
+
+set(IL2CPP_SOURCE_DIR $ENV{HUATUO_IL2CPP_SOURCE_DIR})
+
+message(STATUS "il2cpp project, binary dir: " ${CMAKE_BINARY_DIR})
+message(STATUS "il2cpp project, build dir: " ${PROJECT_BINARY_DIR})
+message(STATUS "il2cpp project, il2cpp source dir: " ${IL2CPP_SOURCE_DIR})
+
+
+SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON)
+find_program(CLANG_EXECUTABLE NAMES clang clang-7 clang-8 clang-9 clang-10)
+if (NOT CLANG_EXECUTABLE)
+    message(FATAL_ERROR "Cannot find any clang executable.")
+endif()
+
+
+set(CMAKE_OSX_SYSROOT /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator${SDK_VERSION}.sdk)
+
+#set(CMAKE_VERBOSE_MAKEFILE ON)
+set(CMAKE_CXX_COMPILER clang++)
+set(CMAKE_C_COMPILER clang)
+#add_compile_options(-x objective-c++)
+
+# 以下命令为复制的Xcode生成中的命令
+set(CMAKE_CXX_FLAGS "-target arm64-apple-ios11.0 -fmessage-length=0 -fdiagnostics-show-note-include-stack -fmacro-backtrace-limit=0 -std=gnu++1z -fmodules -fmodules-prune-interval=86400 -fmodules-prune-after=345600 -fmodules-ignore-macro=IL2CPP_TARGET_IOS=1 -fembed-bitcode -fmodules-ignore-macro=BASELIB_DYNAMICLIBRARY=1 -fmodules-ignore-macro=BASELIB_INLINE_NAMESPACE=il2cpp_baselib -fmodules-ignore-macro=AARCH64 -fmodules-ignore-macro=__aarch64__ -fmodules-ignore-macro=IL2CPP_SUPPORT_THREADS -fmodules-ignore-macro=IL2CPP_THREADS_PTHREAD -Wnon-modular-include-in-framework-module -Werror=non-modular-include-in-framework-module -Wno-trigraphs -fpascal-strings -Os -fno-common -Wno-missing-field-initializers -Wno-missing-prototypes -Werror=return-type -Wdocumentation -Wunreachable-code -Wquoted-include-in-framework-header -Werror=deprecated-objc-isa-usage -Werror=objc-root-class -Wno-non-virtual-dtor -Wno-overloaded-virtual -Wno-exit-time-destructors -Wno-missing-braces -Wparentheses -Wswitch -Wno-unused-function -Wno-unused-label -Wno-unused-parameter -Wno-unused-variable -Wunused-value -Wempty-body -Wuninitialized -Wconditional-uninitialized -Wno-unknown-pragmas -Wno-shadow -Wno-four-char-constants -Wno-conversion -Wconstant-conversion -Wint-conversion -Wbool-conversion -Wenum-conversion -Wno-float-conversion -Wnon-literal-null-conversion -Wobjc-literal-conversion -Wshorten-64-to-32 -Wno-newline-eof -Wno-c++11-extensions -DIL2CPP_TARGET_IOS=1 -isysroot ${CMAKE_OSX_SYSROOT} -fasm-blocks -fstrict-aliasing -Wdeprecated-declarations -Winvalid-offsetof -g -Wno-sign-conversion -Winfinite-recursion -Wmove -Wcomma -Wblock-capture-autoreleasing -Wstrict-prototypes -Wrange-loop-analysis -Wno-semicolon-before-method-body -Wunguarded-availability ")
+
+
+add_definitions(-DIL2CPP_TARGET_IOS=1)
+add_definitions(-DBASELIB_DYNAMICLIBRARY=1)
+add_definitions(-DBASELIB_INLINE_NAMESPACE=il2cpp_baselib)
+add_definitions(-DAARCH64)
+add_definitions(-D__aarch64__)
+add_definitions(-DIL2CPP_SUPPORT_THREADS)
+add_definitions(-DIL2CPP_THREADS_PTHREAD)
+#add_definitions(-DCMAKE_C_COMPILER=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang)
+#add_definitions(-DCMAKE_CXX_COMPILER=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++)
+#add_definitions(-DIL2CPP_TARGET_DARWIN)
+add_definitions(-DIL2CPP_PLATFORM_SUPPORTS_TIMEZONEINFO)
+
+add_definitions(-MMD)
+add_definitions(-MT dependencies)
+
+
+include_directories(${IL2CPP_SOURCE_DIR}/libil2cpp/)
+include_directories(${IL2CPP_SOURCE_DIR}/external/)
+include_directories(${IL2CPP_SOURCE_DIR}/external/baselib/Include/)
+include_directories(${IL2CPP_SOURCE_DIR}/external/bdwgc/include/)
+include_directories(${IL2CPP_SOURCE_DIR}/external/baselib/Platforms/OSX/Include/)
+
+# 修改为本机对应SDK路径
+include_directories(SYSTEM /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/c++/v1)
+include_directories(SYSTEM /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include)
+
+aux_source_directory(${PROJECT_BINARY_DIR}/lump_cpp LUMP_SOURCE_LIST)
+aux_source_directory(${IL2CPP_SOURCE_DIR}/libil2cpp LIBIL2CPP_SOURCE_LIST)
+
+#find_library(zlib ${PROJECT_SOURCE_DIR}/external)
+add_library(il2cpp_original STATIC ${LIBIL2CPP_SOURCE_LIST} ${LUMP_SOURCE_LIST})
+add_dependencies(il2cpp_original external objective)
+
+add_custom_command(TARGET il2cpp_original 
+    POST_BUILD
+    COMMAND xcrun -r libtool -static -o libil2cpp.a libil2cpp_original.a external/libexternal.a objective/libobjective.a
+    COMMENT "post build this is command combine libil2cpp_original.a, libojjective.a and libzlib.a into libil2cpp"
+    )

+ 19 - 0
Unity/HybridCLRData/iOSBuild/build_libil2cpp.sh

@@ -0,0 +1,19 @@
+#!/bin/bash
+
+export HUATUO_IL2CPP_SOURCE_DIR=$(pushd ../LocalIl2CppData/il2cpp > /dev/null && pwd && popd > /dev/null)
+export IPHONESIMULATOR_VERSION=
+
+rm -rf build
+
+mkdir build
+cd build
+cmake ..
+make -j4
+
+if [ -f "libil2cpp.a" ]
+then
+	echo 'build succ'
+else
+    echo "build fail"
+    exit 1
+fi

+ 47 - 0
Unity/HybridCLRData/iOSBuild/external/CMakeLists.txt

@@ -0,0 +1,47 @@
+# file: external/CMakeList.txt
+cmake_minimum_required(VERSION 3.0)
+set(CMAKE_OSX_DEPLOYMENT_TARGET iOS)
+
+set(IL2CPP_SOURCE_DIR $ENV{HUATUO_IL2CPP_SOURCE_DIR})
+set(SDK_VERSION $ENV{IPHONESIMULATOR_VERSION})
+
+message(STATUS "external project, external source dir: " ${IL2CPP_SOURCE_DIR})
+
+SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON)
+
+find_program(CLANG_EXECUTABLE NAMES clang clang-7 clang-8 clang-9 clang-10)
+if (NOT CLANG_EXECUTABLE)
+    message(FATAL_ERROR "Cannot find any clang executable.")
+endif()
+
+set(CMAKE_OSX_SYSROOT /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator${SDK_VERSION}.sdk)
+set(CMAKE_VERBOSE_MAKEFILE ON)
+set(CMAKE_C_COMPILER clang)
+
+set(CMAKE_C_FLAGS "-x c -target arm64-apple-ios11.0 -fmessage-length=0 -fdiagnostics-show-note-include-stack -fmacro-backtrace-limit=0 -std=gnu11 -fmodules -fmodules-prune-interval=86400 -fmodules-prune-after=345600 -fmodules-ignore-macro=IL2CPP_TARGET_IOS=1 -fembed-bitcode -fmodules-ignore-macro=BASELIB_DYNAMICLIBRARY=1 -fmodules-ignore-macro=BASELIB_INLINE_NAMESPACE=il2cpp_baselib -fmodules-ignore-macro=AARCH64 -fmodules-ignore-macro=__aarch64__ -fmodules-ignore-macro=IL2CPP_SUPPORT_THREADS -fmodules-ignore-macro=IL2CPP_THREADS_PTHREAD -Wnon-modular-include-in-framework-module -Werror=non-modular-include-in-framework-module -Wno-trigraphs -fpascal-strings -Os -fno-common -Wno-missing-field-initializers -Wno-missing-prototypes -Werror=return-type -Wdocumentation -Wunreachable-code -Wquoted-include-in-framework-header -Werror=deprecated-objc-isa-usage -Werror=objc-root-class -Wno-missing-braces -Wparentheses -Wswitch -Wunused-function -Wno-unused-label -Wno-unused-parameter -Wunused-variable -Wunused-value -Wempty-body -Wuninitialized -Wconditional-uninitialized -Wno-unknown-pragmas -Wno-shadow -Wno-four-char-constants -Wno-conversion -Wconstant-conversion -Wint-conversion -Wbool-conversion -Wenum-conversion -Wno-float-conversion -Wnon-literal-null-conversion -Wobjc-literal-conversion -Wshorten-64-to-32 -Wpointer-sign -Wno-newline-eof -DIL2CPP_TARGET_IOS=1 -isysroot ${CMAKE_OSX_SYSROOT} -fstrict-aliasing -Wdeprecated-declarations -g -Wno-sign-conversion -Winfinite-recursion -Wcomma -Wblock-capture-autoreleasing -Wstrict-prototypes -Wno-semicolon-before-method-body -Wunguarded-availability")
+
+
+add_definitions(-DIL2CPP_TARGET_IOS=1)
+add_definitions(-DBASELIB_DYNAMICLIBRARY=1)
+add_definitions(-DBASELIB_INLINE_NAMESPACE=il2cpp_baselib)
+add_definitions(-DAARCH64)
+add_definitions(-D__aarch64__)
+#add_definitions(-D__arm64__)
+add_definitions(-DIL2CPP_SUPPORT_THREADS)
+add_definitions(-DIL2CPP_THREADS_PTHREAD)
+#add_definitions(-DCMAKE_C_COMPILER=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang)
+#add_definitions(-DCMAKE_CXX_COMPILER=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++)
+#add_definitions(-DIL2CPP_TARGET_DARWIN)
+add_definitions(-DIL2CPP_PLATFORM_SUPPORTS_TIMEZONEINFO=0)
+
+add_definitions(-MMD)
+add_definitions(-MT dependencies)
+
+include_directories(${IL2CPP_SOURCE_DIR}/external/)
+include_directories(${IL2CPP_SOURCE_DIR}/external/baselib/Include/)
+include_directories(${IL2CPP_SOURCE_DIR}/external/bdwgc/include/)
+include_directories(${IL2CPP_SOURCE_DIR}/external/baselib/Platforms/OSX/Include/)
+
+aux_source_directory(${IL2CPP_SOURCE_DIR}/external/zlib/ ZLIB_C_SOURCE_LIST)
+add_library(external STATIC ${ZLIB_C_SOURCE_LIST})
+

+ 64 - 0
Unity/HybridCLRData/iOSBuild/gen_lump.sh

@@ -0,0 +1,64 @@
+echo '====================================================================='
+echo 'gen lump'
+echo '$HUATUO_IL2CPP_SOURCE_DIR='${HUATUO_IL2CPP_SOURCE_DIR}   #/Applications/Unity/Unity.app/Contents/il2cpp/
+
+GEN_SOURCE_DIR=$1
+BASE_DIR=${HUATUO_IL2CPP_SOURCE_DIR}/libil2cpp
+echo base dir: ${BASE_DIR}
+echo " "
+#BASE_DIR=${HUATUO_IL2CPP_SOURCE_DIR}/libil2cpp
+function SearchCppFile()
+{
+    for f in $(ls $1)
+    do
+        SUB_DIR=$1/$f
+        if [ -d ${SUB_DIR} ]; then
+            SearchCppFile ${SUB_DIR}
+        fi
+    done
+
+    CPP_FILE_NUM=`ls -l $1/ | grep "\.cpp$"|wc -l`
+    if (( ${CPP_FILE_NUM} > 0 ))
+    then
+        for f in $1/*.cpp
+        do
+            echo "#include \""$f"\"" >> ${OUTPUT_FILE_NAME}
+        done
+    fi
+
+    MM_FILE_NUM=`ls -l $1/ | grep "\.mm$"|wc -l`
+    if (( ${MM_FILE_NUM} > 0 ))
+    then
+        for f in $1/*.mm
+        do
+            echo "#include \""$f"\"" >> ${OBJECTIVE_FILE_NAME}
+        done
+    fi
+}
+
+rm -rf ${GEN_SOURCE_DIR}/lump_cpp
+rm -rf ${GEN_SOURCE_DIR}/lump_mm
+mkdir ${GEN_SOURCE_DIR}/lump_cpp
+mkdir ${GEN_SOURCE_DIR}/lump_mm
+
+OBJECTIVE_FILE_NAME=${GEN_SOURCE_DIR}/lump_mm/lump_libil2cpp_ojective.mm
+echo "#include \"${BASE_DIR}/il2cpp-config.h\"" > ${OBJECTIVE_FILE_NAME}
+echo gen file: ${OBJECTIVE_FILE_NAME}
+
+for FOLDER in hybridclr vm pch utils vm-utils codegen metadata os debugger mono gc icalls
+do
+    OUTPUT_FILE_NAME=${GEN_SOURCE_DIR}/lump_cpp/lump_libil2cpp_${FOLDER}.cpp
+    echo "#include \"${BASE_DIR}/il2cpp-config.h\"" > ${OUTPUT_FILE_NAME}
+    if  [ $FOLDER = hybridclr ] || [ $FOLDER = vm ]
+    then
+        echo "#include \"${BASE_DIR}/codegen/il2cpp-codegen.h\"" >> ${OUTPUT_FILE_NAME}
+    fi
+    SearchCppFile ${BASE_DIR}/${FOLDER}
+    echo gen file: ${OUTPUT_FILE_NAME}
+done
+
+echo gen done.
+echo '====================================================================='
+echo " "
+
+

Niektoré súbory nie sú zobrazené, pretože je v týchto rozdielových dátach zmenené mnoho súborov