Initial commit: Client Doc docs Server Tools

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
ud18010
2026-07-10 10:24:29 +08:00
co-authored by Cursor
commit 7e35d8da31
3374 changed files with 680813 additions and 0 deletions
@@ -0,0 +1,152 @@
using HybridCLR.Editor.Commands;
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 BuildAssetsCommand
{
public static string HybridCLRBuildCacheDir => Application.dataPath + "/HybridCLRBuildCache";
public static string AssetBundleOutputDir => $"{HybridCLRBuildCacheDir}/AssetBundleOutput";
public static string AssetBundleSourceDataTempDir => $"{HybridCLRBuildCacheDir}/AssetBundleSourceData";
public static string GetAssetBundleOutputDirByTarget(BuildTarget target)
{
return $"{AssetBundleOutputDir}/{target}";
}
public static string GetAssetBundleTempDirByTarget(BuildTarget target)
{
return $"{AssetBundleSourceDataTempDir}/{target}";
}
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);
List<AssetBundleBuild> abs = new List<AssetBundleBuild>();
{
var prefabAssets = new List<string>();
string testPrefab = $"{Application.dataPath}/Prefabs/HotUpdatePrefab.prefab";
prefabAssets.Add(testPrefab);
AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
abs.Add(new AssetBundleBuild
{
assetBundleName = "prefabs",
assetNames = prefabAssets.Select(s => ToRelativeAssetPath(s)).ToArray(),
});
}
BuildPipeline.BuildAssetBundles(outputDir, abs.ToArray(), BuildAssetBundleOptions.None, target);
AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
}
public static void BuildAssetBundleByTarget(BuildTarget target)
{
BuildAssetBundles(GetAssetBundleTempDirByTarget(target), GetAssetBundleOutputDirByTarget(target), target);
}
[MenuItem("HybridCLR/Build/BuildAssetsAndCopyToStreamingAssets")]
public static void BuildAndCopyABAOTHotUpdateDlls()
{
BuildAssetBundleByTarget(EditorUserBuildSettings.activeBuildTarget);
CopyAssetBundlesToStreamingAssets();
CompileDllCommand.CompileDllActiveBuildTarget();
CopyAOTAssembliesToStreamingAssets();
CopyHotUpdateAssembliesToStreamingAssets();
}
//[MenuItem("HybridCLR/Build/Copy_AB_AOT_HotUpdateDlls")]
public static void Copy_AB_AOT_HotUpdateDlls()
{
CopyAOTAssembliesToStreamingAssets();
CopyHotUpdateAssembliesToStreamingAssets();
CopyAssetBundlesToStreamingAssets();
}
//[MenuItem("HybridCLR/Build/BuildAssetbundle")]
public static void BuildSceneAssetBundleActiveBuildTargetExcludeAOT()
{
BuildAssetBundleByTarget(EditorUserBuildSettings.activeBuildTarget);
}
public static void CopyAOTAssembliesToStreamingAssets()
{
var target = EditorUserBuildSettings.activeBuildTarget;
string aotAssembliesSrcDir = SettingsUtil.GetAssembliesPostIl2CppStripDir(target);
string aotAssembliesDstDir = Application.streamingAssetsPath+"/xaot";//改为aot目录
if (!Directory.Exists(aotAssembliesDstDir))
Directory.CreateDirectory(aotAssembliesDstDir);
foreach (var dll in Packager.AOTMetaAssemblyNames)
{
string srcDllPath = $"{aotAssembliesSrcDir}/{dll}";
if (!File.Exists(srcDllPath))
{
Debug.LogError($"ab中添加AOT补充元数据dll:{srcDllPath} 时发生错误,文件不存在。裁剪后的AOT dll在BuildPlayer时才能生成,因此需要你先构建一次游戏App后再打包。");
continue;
}
string dllBytesPath = $"{aotAssembliesDstDir}/{dll}";
File.Copy(srcDllPath, dllBytesPath, true);
Debug.Log($"[CopyAOTAssembliesToStreamingAssets] copy AOT dll {srcDllPath} -> {dllBytesPath}");
}
}
public static void CopyHotUpdateAssembliesToStreamingAssets()
{
var target = EditorUserBuildSettings.activeBuildTarget;
string hotfixDllSrcDir = SettingsUtil.GetHotUpdateDllsOutputDirByTarget(target);
string hotfixAssembliesDstDir = Application.streamingAssetsPath+"/xhotfix";//改为hotfix目录
if (!Directory.Exists(hotfixAssembliesDstDir))
Directory.CreateDirectory(hotfixAssembliesDstDir);
foreach (var dll in SettingsUtil.HotUpdateAssemblyFilesExcludePreserved)
{
string dllPath = $"{hotfixDllSrcDir}/{dll}";
string dllBytesPath = $"{hotfixAssembliesDstDir}/{dll}";
File.Copy(dllPath, dllBytesPath, true);
Debug.Log($"[CopyHotUpdateAssembliesToStreamingAssets] copy hotfix dll {dllPath} -> {dllBytesPath}");
}
}
public static void CopyAssetBundlesToStreamingAssets()
{
var target = EditorUserBuildSettings.activeBuildTarget;
string streamingAssetPathDst = Application.streamingAssetsPath;
Directory.CreateDirectory(streamingAssetPathDst);
string outputDir = GetAssetBundleOutputDirByTarget(target);
var abs = new string[] { "prefabs" };
foreach (var ab in abs)
{
string srcAb = ToRelativeAssetPath($"{outputDir}/{ab}");
string dstAb = ToRelativeAssetPath($"{streamingAssetPathDst}/{ab}");
Debug.Log($"[CopyAssetBundlesToStreamingAssets] copy assetbundle {srcAb} -> {dstAb}");
AssetDatabase.CopyAsset( srcAb, dstAb);
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7417143702c594642ba8d9a138dbfa1d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,79 @@
#if EngineEditor
using HybridCLR.Editor.Commands;
using HybridCLR.Editor.Installer;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
namespace HybridCLR.Editor
{
public class BuildPlayerCommand
{
public static void CopyAssets(string outputDir)
{
Directory.CreateDirectory(outputDir);
foreach(var srcFile in Directory.GetFiles(Application.streamingAssetsPath))
{
string dstFile = $"{outputDir}/{Path.GetFileName(srcFile)}";
File.Copy(srcFile, dstFile, true);
}
}
private static string[] FindEnabledEditorScenes()
{
List<string> EditorScenes = new List<string>();
foreach (EditorBuildSettingsScene scene in EditorBuildSettings.scenes)
{
if (!scene.enabled) continue;
EditorScenes.Add(scene.path);
}
return EditorScenes.ToArray();
}
[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 = $"{SettingsUtil.ProjectDir}/Release-Win64";
var buildOptions = BuildOptions.CompressWithLz4;
string location = $"{outputPath}/HybridCLRTrial.exe";
PrebuildCommand.GenerateAll();
Debug.Log("====> Build App");
BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions()
{
scenes = FindEnabledEditorScenes(),//new string[] { "Assets/Scenes/SimpleScene.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("====> 复制热更新资源和代码");
BuildAssetsCommand.BuildAndCopyABAOTHotUpdateDlls();
BashUtil.CopyDir(Application.streamingAssetsPath, $"{outputPath}/HybridCLRTrial_Data/StreamingAssets", true);
#if UNITY_EDITOR
Application.OpenURL($"file:///{location}");
#endif
}
}
}
#endif
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9fc09201239ded843a793c9167e0ff6a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 227b11ce7187c9b4da274d4119b36597
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: