| Main/Core/GameEngine/Launch/YooAssetInitTask.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| Main/Manager/StageManager.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| Main/ResModule/BuiltInLoader.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| Main/ResModule/ResManager.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| Main/ResModule/ResourcePreloader.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| Main/ResModule/YooAssetService.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| Main/Utility/FontUtility.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
Main/Core/GameEngine/Launch/YooAssetInitTask.cs
@@ -48,7 +48,12 @@ } else { #if UNITY_EDITOR // 编辑器下 AB 模式使用 OfflinePlayMode(随包模式),从 StreamingAssets 加载 playMode = EPlayMode.OfflinePlayMode; #else playMode = EPlayMode.HostPlayMode; #endif } // Initialize YooAssetService Main/Manager/StageManager.cs
@@ -46,7 +46,7 @@ if (AssetSource.isUseAssetBundle) { loadingWin.SetProgress(0.05f); await YooAssetService.Instance.LoadAllAssetsAsync<UnityEngine.Object>("Assets/ResourcesOut/maps/Login"); await YooAssetService.Instance.LoadAllAssetsAsync<UnityEngine.Object>("Assets/ResourcesOut/Scenes/Login"); loadingWin.SetProgress(0.3f); } @@ -144,7 +144,7 @@ if (AssetSource.isUseAssetBundle) { loadingWin.SetProgress(0.05f); await YooAssetService.Instance.LoadAllAssetsAsync<UnityEngine.Object>("Assets/ResourcesOut/maps/Game"); await YooAssetService.Instance.LoadAllAssetsAsync<UnityEngine.Object>("Assets/ResourcesOut/Scenes/Game"); loadingWin.SetProgress(0.3f); } Main/ResModule/BuiltInLoader.cs
@@ -204,7 +204,7 @@ { #if UNITY_EDITOR var path = StringUtility.Concat(ResourcesPath.ResourcesOutAssetPath, "BuiltIn/Font/", fontName, ".ttf"); "Font/", fontName, ".ttf"); font = UnityEditor.AssetDatabase.LoadAssetAtPath<Font>(path); #endif } @@ -212,7 +212,7 @@ { // US1: Route through YooAssetService sync wrapper var path = StringUtility.Concat(ResourcesPath.ResourcesOutAssetPath, "BuiltIn/Font/", fontName, ".ttf"); "Font/", fontName, ".ttf"); #pragma warning disable CS0612 font = YooAssetService.Instance.LoadAssetSync<Font>(path); #pragma warning restore CS0612 @@ -270,7 +270,7 @@ public static async UniTask<Font> LoadFontAsync(string fontName, CancellationToken ct = default) { var path = StringUtility.Concat(ResourcesPath.ResourcesOutAssetPath, "BuiltIn/Font/", fontName, ".ttf"); "Font/", fontName, ".ttf"); return await YooAssetService.Instance.LoadAssetAsync<Font>(path, ct: ct); } Main/ResModule/ResManager.cs
@@ -388,29 +388,35 @@ /// <summary> /// 异步加载配置文件(UniTask 版本)。 /// WebGL 平台使用 YooAsset RawFile 异步加载,其他平台使用线程池。 /// AB 模式使用 YooAsset RawFile 异步加载,非 AB 模式直接读文件。 /// </summary> public async UniTask<string[]> LoadConfigAsync(string name, CancellationToken ct = default) { #if UNITY_WEBGL && !UNITY_EDITOR // WebGL 不支持多线程和 File.ReadAllLines,使用 YooAsset RawFile try // AB 模式(含 WebGL): 使用 YooAsset RawFile 加载(配置文件在 YooAsset 沙盒中) if (AssetSource.isUseAssetBundle) { var text = await ProjSG.Resource.YooAssetService.Instance.LoadRawFileTextAsync($"config/{name}", ct); if (!string.IsNullOrEmpty(text)) try { return text.Split(new[] { "\r\n", "\n" }, System.StringSplitOptions.None); var location = $"Assets/ResourcesOut/Config/{name}.txt"; var text = await ProjSG.Resource.YooAssetService.Instance.LoadRawFileTextAsync(location, ct); if (!string.IsNullOrEmpty(text)) { return text.Split(new[] { "\r\n", "\n" }, System.StringSplitOptions.None); } } catch (System.Exception ex) { UnityEngine.Debug.LogError($"[ResManager] LoadConfigAsync YooAsset failed for '{name}': {ex.Message}"); } return System.Array.Empty<string>(); } catch (System.Exception ex) { UnityEngine.Debug.LogError($"[ResManager] LoadConfigAsync WebGL fallback failed for '{name}': {ex.Message}"); } return System.Array.Empty<string>(); // 非 AB 模式: 直接读文件(Editor 开发模式) #if UNITY_EDITOR string path = ResourcesPath.CONFIG_FODLER + "/" + name + ".txt"; return await UniTask.RunOnThreadPool(() => File.ReadAllLines(path)); #else #pragma warning disable CS0618 // LoadConfig is obsolete — used here as thread-pool fallback for non-WebGL return await UniTask.RunOnThreadPool(() => LoadConfig(name)); #pragma warning restore CS0618 return System.Array.Empty<string>(); #endif } Main/ResModule/ResourcePreloader.cs
@@ -29,16 +29,15 @@ public void RegisterDefaultConfigs() { // 启动必需资源(常驻) // 注意:路径必须是具体的资源文件(含扩展名或 YooAsset 可识别的无扩展名路径), // 不能是目录路径。Shader/Materials 等目录级加载由 ShaderUtility 等专用系统处理。 RegisterConfig(new PreloadConfig { ConfigName = "StartupEssential", Locations = new[] { "Assets/ResourcesOut/Shader", // Shader 全部 "Assets/ResourcesOut/Materials", // 通用 Material "Assets/ResourcesOut/BuiltIn/Font", // 常用字体 "Assets/ResourcesOut/BuiltIn/UIRoot", // UIRoot 预制体 "Assets/ResourcesOut/BuiltIn/SoundPlayer", // 音频播放器 "Assets/ResourcesOut/BuiltIn/Prefabs/UIRoot.prefab", // UIRoot 预制体 "Assets/ResourcesOut/BuiltIn/Prefabs/SoundPlayer.prefab", // 音频播放器 }, Tags = null, IsPermanent = true, Main/ResModule/YooAssetService.cs
@@ -70,7 +70,47 @@ var package = YooAssets.TryGetPackage(pkgName); if (package != null) { Debug.Log($"[YooAssetService] Reusing existing package '{pkgName}' from YooAssetInitializer"); // 验证包裹是否已成功初始化 if (package.InitializeStatus == EOperationStatus.Succeed) { Debug.Log($"[YooAssetService] Reusing existing package '{pkgName}' (InitializeStatus=Succeed)"); } else { // 包裹存在但初始化未完成或失败(僵尸包裹) // 销毁后重新创建并初始化 Debug.LogWarning($"[YooAssetService] Package '{pkgName}' exists but InitializeStatus={package.InitializeStatus}, destroying and re-creating..."); // 根据状态清理僵尸包裹 if (package.InitializeStatus == EOperationStatus.None) { // 未初始化状态可以直接移除 YooAssets.RemovePackage(pkgName); } else { // Failed/Processing 状态需先销毁再移除 var destroyOp = package.DestroyAsync(); await destroyOp.ToUniTask(); YooAssets.RemovePackage(pkgName); } package = YooAssets.CreatePackage(pkgName); var initParams = CreateInitParameters(playMode, remoteServices, pkgName); var initOp = package.InitializeAsync(initParams); await initOp.ToUniTask(); if (initOp.Status != EOperationStatus.Succeed) { Debug.LogWarning($"[YooAssetService] Package '{pkgName}' re-init failed: {initOp.Error}"); continue; } Debug.Log($"[YooAssetService] Package '{pkgName}' re-initialized successfully."); // 重新初始化后必须请求版本并更新 Manifest await RequestVersionAndUpdateForPackageAsync(pkgName, package); } } else { @@ -85,6 +125,9 @@ Debug.LogWarning($"[YooAssetService] Package '{pkgName}' init failed: {initOp.Error}"); continue; } // 初始化后必须请求版本并更新 Manifest,否则 ActiveManifest 为 null await RequestVersionAndUpdateForPackageAsync(pkgName, package); Debug.Log($"[YooAssetService] Package '{pkgName}' newly initialized."); } @@ -112,7 +155,22 @@ } _isInitialized = true; Debug.Log($"[YooAssetService] Initialized {_packages.Count}/{YooAssetPackageConfig.AllPackages.Length} packages with PlayMode={playMode}"); // 输出初始化摘要 — 帮助诊断缺失的包裹 var allPkgs = YooAssetPackageConfig.AllPackages; var missingPkgs = new System.Collections.Generic.List<string>(); foreach (var p in allPkgs) { if (!_packages.ContainsKey(p)) missingPkgs.Add(p); } if (missingPkgs.Count > 0) { Debug.LogError($"[YooAssetService] WARNING: {missingPkgs.Count} package(s) FAILED to initialize: [{string.Join(", ", missingPkgs)}]. " + $"Assets routed to these packages will fail to load! Check earlier console errors for SimulateBuild failures."); } Debug.Log($"[YooAssetService] Initialized {_packages.Count}/{allPkgs.Length} packages with PlayMode={playMode}. " + $"Active: [{string.Join(", ", _packages.Keys)}]"); } /// <summary> @@ -129,6 +187,7 @@ // 优先复用已存在的包裹(可能由 Launch 阶段创建) var package = YooAssets.TryGetPackage(packageName); bool needManifest = false; if (package == null) { package = YooAssets.CreatePackage(packageName); @@ -141,9 +200,17 @@ Debug.LogError($"[YooAssetService] Initialize package '{packageName}' failed: {initOp.Error}"); throw new InvalidOperationException($"YooAsset package '{packageName}' initialization failed: {initOp.Error}"); } needManifest = true; } _packages[packageName] = package; // 确保 ActiveManifest 已加载 if (needManifest) { await RequestVersionAndUpdateForPackageAsync(packageName, package); } Debug.Log($"[YooAssetService] Package '{packageName}' initialized."); } @@ -206,6 +273,40 @@ } default: throw new ArgumentOutOfRangeException(nameof(playMode), playMode, "Unsupported PlayMode."); } } /// <summary> /// 对单个包裹执行版本请求和 Manifest 更新。 /// 所有运行模式(包括 EditorSimulateMode)都需要此步骤来填充 ActiveManifest。 /// </summary> private async UniTask RequestVersionAndUpdateForPackageAsync(string pkgName, ResourcePackage package) { try { var versionOp = package.RequestPackageVersionAsync(); await versionOp.ToUniTask(); if (versionOp.Status != EOperationStatus.Succeed) { Debug.LogWarning($"[YooAssetService] RequestPackageVersion failed for '{pkgName}': {versionOp.Error}"); return; } var manifestOp = package.UpdatePackageManifestAsync(versionOp.PackageVersion); await manifestOp.ToUniTask(); if (manifestOp.Status != EOperationStatus.Succeed) { Debug.LogWarning($"[YooAssetService] UpdatePackageManifest failed for '{pkgName}': {manifestOp.Error}"); return; } Debug.Log($"[YooAssetService] Package '{pkgName}' manifest loaded (version={versionOp.PackageVersion})."); } catch (Exception ex) { Debug.LogWarning($"[YooAssetService] RequestVersionAndUpdate for '{pkgName}' exception: {ex.Message}"); } } @@ -277,7 +378,11 @@ if (_packages.TryGetValue(packageName, out var package)) return package; // 路由到的包尚未初始化,回退到默认包 // 路由到的包尚未初始化,回退到默认包 — 发出明确警告 Debug.LogWarning($"[YooAssetService] Package '{packageName}' not available for location '{location}'. " + $"Available packages: [{string.Join(", ", _packages.Keys)}]. " + $"Falling back to default package '{_defaultPackage?.PackageName ?? "NULL"}'." + $"\n → This usually means SimulateBuild failed for '{packageName}'. Check earlier console errors."); return _defaultPackage; } Main/Utility/FontUtility.cs
@@ -7,17 +7,17 @@ public class FontUtility { // T044: Fonts must be pre-loaded via StartupEssential preload config // (location: "Assets/ResourcesOut/BuiltIn/Font") // T044: Fonts loaded via FontUtility.InitAsync or UILoader.LoadFont // Actual location: Assets/ResourcesOut/Font/ public static Font preferred { get { return ResourceCacheManager.Instance.GetCached<Font>("Assets/ResourcesOut/BuiltIn/Font/GameFont1.ttf"); } get { return ResourceCacheManager.Instance.GetCached<Font>("Assets/ResourcesOut/Font/GameFont1.ttf"); } } public static Font secondary { get { return ResourceCacheManager.Instance.GetCached<Font>("Assets/ResourcesOut/BuiltIn/Font/GameFont2.ttf"); } get { return ResourceCacheManager.Instance.GetCached<Font>("Assets/ResourcesOut/Font/GameFont2.ttf"); } } /// <summary>