Add hot-update boot pipeline, UI bundles/atlas assets, and design docs.

Ignore AIClient/Library and AIClient/HybridCLRData permanently; include HybridCLR/YooAsset project setup and UI tooling.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
udx
2026-09-21 16:02:58 +08:00
co-authored by Cursor
parent f3f66ab063
commit b7a0bbcb89
279 changed files with 27332 additions and 14 deletions
@@ -0,0 +1,34 @@
using YooAsset;
namespace AOT.Boot
{
/// <summary>
/// 壳层传给热更入口的运行时上下文。
/// </summary>
public sealed class BootContext
{
public string AppVersion;
public string ResVersion;
public string CdnRoot;
public string PackageName;
public ResourcePackage Package;
public string WsUrlTemplate;
public string BuildWsUrl(string pid, string token = null)
{
if (string.IsNullOrEmpty(WsUrlTemplate))
{
if (string.IsNullOrEmpty(token))
return $"wss://game.xworld.ren/ws?pid={pid}";
return $"wss://game.xworld.ren/ws?pid={pid}&token={UnityEngine.Networking.UnityWebRequest.EscapeURL(token)}";
}
var url = WsUrlTemplate.Replace("{pid}", pid ?? string.Empty);
if (url.Contains("{token}"))
url = url.Replace("{token}", UnityEngine.Networking.UnityWebRequest.EscapeURL(token ?? string.Empty));
else if (!string.IsNullOrEmpty(token))
url += (url.Contains("?") ? "&" : "?") + "token=" + UnityEngine.Networking.UnityWebRequest.EscapeURL(token);
return url;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3a57e0242ddf4ff48af5d8e8a763e105
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,71 @@
using AOT.Boot;
using AOT.HotUpdate;
using AOT.Patch;
using AOT.UI;
using UnityEngine;
namespace AOT.Boot
{
/// <summary>
/// 壳层启动入口:版本检查 → 资源补丁 → HybridCLR/热更入口。
/// </summary>
public sealed class BootDriver : MonoBehaviour
{
[SerializeField] BootSettings settings = new BootSettings();
BootPatchView _view;
void Awake()
{
Application.targetFrameRate = 60;
Screen.sleepTimeout = SleepTimeout.NeverSleep;
DontDestroyOnLoad(gameObject);
if (Screen.orientation != ScreenOrientation.Portrait)
Screen.orientation = ScreenOrientation.Portrait;
}
void Start()
{
_view = BootPatchView.Create();
StartCoroutine(Bootstrap());
}
System.Collections.IEnumerator Bootstrap()
{
BootContext ctx = null;
string error = null;
var runner = new PatchRunner(this, settings, _view);
yield return runner.Run((c, e) =>
{
ctx = c;
error = e;
});
if (!string.IsNullOrEmpty(error) || ctx == null)
{
_view?.SetError(error ?? "启动失败");
Debug.LogError($"[Boot] {error}");
yield break;
}
_view?.SetStatus("加载热更代码…");
_view?.SetProgress(0.97f);
string loadError = null;
yield return HotUpdateLoader.LoadAndStart(ctx, settings, e => loadError = e);
if (!string.IsNullOrEmpty(loadError))
{
_view?.SetError(loadError);
Debug.LogError($"[Boot] {loadError}");
yield break;
}
_view?.SetProgress(1f);
_view?.SetStatus("热更已启动");
Debug.Log($"[Boot] OK app={ctx.AppVersion} res={ctx.ResVersion} cdn={ctx.CdnRoot}");
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4d11b543accc52448b82d773c022254c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,39 @@
using UnityEngine;
using YooAsset;
namespace AOT.Boot
{
/// <summary>
/// Boot 可序列化配置(挂在 BootDriver 上)。
/// </summary>
[System.Serializable]
public class BootSettings
{
[Tooltip("壳版本,对应提审包 appVersion")]
public string AppVersion = "1.0.0";
[Tooltip("CDN 总控 version.json")]
public string VersionUrl = "https://www.xworld.ren/wechat/version.json";
[Tooltip("CDN 根(version.json 未下发 cdnRoot 时回退;含 Package 名)")]
public string DefaultCdnRoot = "https://www.xworld.ren/wechat/1.0.0/DefaultPackage";
[Tooltip("YooAsset 默认包名")]
public string PackageName = "DefaultPackage";
[Tooltip("热更 DLL 在包内的定位地址")]
public string HotUpdateDllLocation = "HotUpdate.Runtime";
[Tooltip("WebSocket 模板,{pid}/{token} 会被替换")]
public string WsUrlTemplate = "wss://game.xworld.ren/ws?pid={pid}&token={token}";
[Tooltip("运行模式;编辑器默认 EditorSimulateMode;M1 Offline/Host 验证时切换")]
public EPlayMode PlayMode = EPlayMode.EditorSimulateMode;
[Tooltip("编辑器下跳过 YooAsset 补丁,直接反射加载已编译热更程序集(M0 默认开;M1 验证补丁时关掉)")]
public bool EditorDirectHotUpdate = true;
[Tooltip("version.json 拉取失败时是否允许使用 StreamingAssets 本地回退")]
public bool AllowStreamingVersionFallback = true;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f2c6317a2a3e50f4ca2bed34aafc0291
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: