Assets/AssetBundleCollectorSetting.asset
@@ -38,6 +38,43 @@ FilterRuleName: CollectAll AssetTags: UserData: - CollectPath: Assets/ResourcesOut/UIComp CollectorGUID: cafb96babf67f0e47aa47d7bd7e851f9 CollectorType: 0 AddressRuleName: AddressByFolderAndFileName PackRuleName: PackDirectory FilterRuleName: CollectAll AssetTags: UserData: - CollectPath: Assets/ResourcesOut/Sprite CollectorGUID: d525c1ea56911ef46968923700fee47f CollectorType: 0 AddressRuleName: AddressByFolderAndFileName PackRuleName: PackDirectory FilterRuleName: CollectAll AssetTags: UserData: - CollectPath: Assets/ResourcesOut/Texture CollectorGUID: cc4265f3ee528e64e8afa76bd8f7d3f7 CollectorType: 0 AddressRuleName: AddressByFolderAndFileName PackRuleName: PackDirectory FilterRuleName: CollectAll AssetTags: UserData: - GroupName: Font GroupDesc: AssetTags: ActiveRuleName: EnableGroup Collectors: - CollectPath: Assets/ResourcesOut/Font CollectorGUID: 6c72fee81b7c8804dbc80d80a5770197 CollectorType: 0 AddressRuleName: AddressByRelativePath PackRuleName: PackDirectory FilterRuleName: CollectAll AssetTags: UserData: - PackageName: Prefab PackageDesc: all prefab EnableAddressable: 1 @@ -52,8 +89,48 @@ AssetTags: ActiveRuleName: EnableGroup Collectors: - CollectPath: Assets/ResourcesOut/Prefab CollectorGUID: 84f0993784b8e8d41a68d0e1e2be57bd - CollectPath: Assets/ResourcesOut/BuiltIn CollectorGUID: e5f9df9a324df2b46b1a92fa8da26b67 CollectorType: 0 AddressRuleName: AddressByRelativePath PackRuleName: PackDirectory FilterRuleName: CollectAll AssetTags: UserData: - CollectPath: Assets/ResourcesOut/Shader CollectorGUID: 01ad80e2bb073fb46ad906e3572fbe50 CollectorType: 0 AddressRuleName: AddressByRelativePath PackRuleName: PackDirectory FilterRuleName: CollectAll AssetTags: UserData: - CollectPath: Assets/ResourcesOut/Materials CollectorGUID: 676c8b4532d6ca646804bf73ed43dd96 CollectorType: 0 AddressRuleName: AddressByFolderAndFileName PackRuleName: PackDirectory FilterRuleName: CollectAll AssetTags: UserData: - CollectPath: Assets/ResourcesOut/ScriptableObject CollectorGUID: 1482db32e9d88d444bc22e54075bf994 CollectorType: 0 AddressRuleName: AddressByFolderAndFileName PackRuleName: PackDirectory FilterRuleName: CollectAll AssetTags: UserData: - CollectPath: Assets/ResourcesOut/Scenes CollectorGUID: b3332ee13576c994186d5570af59b0b6 CollectorType: 0 AddressRuleName: AddressByFolderAndFileName PackRuleName: PackDirectory FilterRuleName: CollectAll AssetTags: UserData: - CollectPath: Assets/ResourcesOut/Config CollectorGUID: 6a0e1d814ea59174985b17c9f4ecaba3 CollectorType: 0 AddressRuleName: AddressByFolderAndFileName PackRuleName: PackDirectory @@ -76,10 +153,10 @@ Collectors: [] - PackageName: UIEffect PackageDesc: EnableAddressable: 0 EnableAddressable: 1 SupportExtensionless: 1 LocationToLower: 0 IncludeAssetGUID: 0 IncludeAssetGUID: 1 AutoCollectShaders: 1 IgnoreRuleName: NormalIgnoreRule Groups: @@ -88,10 +165,62 @@ AssetTags: ActiveRuleName: EnableGroup Collectors: - CollectPath: Assets/ResourcesOut/Effect CollectorGUID: 63ddc4df56ae98b4cbc48f45628a26a7 - CollectPath: Assets/ResourcesOut/UIEffect CollectorGUID: 62eb3abc624381e4b8950f355812a8e9 CollectorType: 0 AddressRuleName: AddressByFileName AddressRuleName: AddressByFolderAndFileName PackRuleName: PackDirectory FilterRuleName: CollectAll AssetTags: UserData: - PackageName: Battle PackageDesc: battle resources EnableAddressable: 1 SupportExtensionless: 1 LocationToLower: 0 IncludeAssetGUID: 1 AutoCollectShaders: 1 IgnoreRuleName: NormalIgnoreRule Groups: - GroupName: Prefab GroupDesc: AssetTags: ActiveRuleName: EnableGroup Collectors: - CollectPath: Assets/ResourcesOut/Hero CollectorGUID: 4ef1d5e33efbd83438f79bd2fd7c44ac CollectorType: 0 AddressRuleName: AddressByFolderAndFileName PackRuleName: PackDirectory FilterRuleName: CollectAll AssetTags: UserData: - CollectPath: Assets/ResourcesOut/Battle CollectorGUID: f4b5330ed101c7b4c8cbfba3f0daff9f CollectorType: 0 AddressRuleName: AddressByFolderAndFileName PackRuleName: PackDirectory FilterRuleName: CollectAll AssetTags: UserData: - PackageName: Audio PackageDesc: audio resources EnableAddressable: 1 SupportExtensionless: 1 LocationToLower: 0 IncludeAssetGUID: 1 AutoCollectShaders: 1 IgnoreRuleName: NormalIgnoreRule Groups: - GroupName: Prefab GroupDesc: AssetTags: ActiveRuleName: EnableGroup Collectors: - CollectPath: Assets/ResourcesOut/Audio CollectorGUID: 3d2c92bf721b286489d290a1a2c9763a CollectorType: 0 AddressRuleName: AddressByRelativePath PackRuleName: PackDirectory FilterRuleName: CollectAll AssetTags: Assets/Editor/YooAsset.meta
New file @@ -0,0 +1,8 @@ fileFormatVersion: 2 guid: 5357a95619b07614a93e905607cd4533 folderAsset: yes DefaultImporter: externalObjects: {} userData: assetBundleName: assetBundleVariant: Assets/Editor/YooAsset/AddressByRelativePath.cs
New file @@ -0,0 +1,43 @@ // ============================================================================ // AddressByRelativePath.cs — 自定义 YooAsset 地址规则 // 使用相对于 CollectPath 的完整路径(不含扩展名)作为地址 // 解决同 Package 内不同子目录下同名文件的地址冲突 // ============================================================================ using System.IO; using YooAsset.Editor; /// <summary> /// 定位地址 = 资源相对于收集目录的路径(不含扩展名)。 /// 例如 CollectPath = "Assets/ResourcesOut/Audio" /// AssetPath = "Assets/ResourcesOut/Audio/Battle/Effect/boom.wav" /// → 地址 = "Battle/Effect/boom" /// </summary> [DisplayName("定位地址: 相对路径")] public class AddressByRelativePath : IAddressRule { string IAddressRule.GetAssetAddress(AddressRuleData data) { // 去掉 CollectPath 前缀,得到相对路径 string relativePath = data.AssetPath; string collectRoot = data.CollectPath; // 确保以 / 结尾 if (!collectRoot.EndsWith("/")) collectRoot += "/"; if (relativePath.StartsWith(collectRoot)) { relativePath = relativePath.Substring(collectRoot.Length); } // 去掉扩展名 string ext = Path.GetExtension(relativePath); if (!string.IsNullOrEmpty(ext)) { relativePath = relativePath.Substring(0, relativePath.Length - ext.Length); } return relativePath; } } Assets/Editor/YooAsset/AddressByRelativePath.cs.meta
New file @@ -0,0 +1,11 @@ fileFormatVersion: 2 guid: b86b10bad08b3244ab4a912f2c8bdff7 MonoImporter: externalObjects: {} serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: assetBundleName: assetBundleVariant: Assets/Launch/Common/IYooAssetBridge.cs
New file @@ -0,0 +1,82 @@ // ============================================================================ // IYooAssetBridge.cs — 跨程序集资源加载桥接接口 // 定义在 Launch 程序集中,由 Main 程序集中的 YooAssetService 实现 // ============================================================================ using Cysharp.Threading.Tasks; using UnityEngine; namespace ProjSG.Resource { /// <summary> /// 跨程序集资源加载桥接接口。 /// 定义在 Launch 程序集中,允许 Launch 代码在 Main 热更 DLL 加载后 /// 通过该接口使用 Main 中实现的完整 YooAsset 封装。 /// </summary> public interface IYooAssetBridge { /// <summary> /// 桥接是否已注册(Main 程序集已加载并注册实现) /// </summary> bool IsRegistered { get; } /// <summary> /// 异步加载资源。 /// </summary> /// <typeparam name="T">资源类型</typeparam> /// <param name="location">YooAsset 资源地址</param> /// <returns>加载完成的资源对象</returns> UniTask<T> LoadAssetAsync<T>(string location) where T : UnityEngine.Object; /// <summary> /// 异步加载原始文本文件。 /// </summary> /// <param name="location">YooAsset 资源地址</param> /// <returns>文件文本内容</returns> UniTask<string> LoadRawFileTextAsync(string location); /// <summary> /// 异步加载原始二进制文件。 /// </summary> UniTask<byte[]> LoadRawFileBytesAsync(string location); /// <summary> /// 批量预加载资源。 /// </summary> /// <param name="locations">资源地址列表</param> UniTask PreloadAsync(string[] locations); /// <summary> /// 同步获取已缓存的资源。 /// 仅在资源已预加载后可用,否则返回 null。 /// </summary> T GetCached<T>(string location) where T : UnityEngine.Object; } /// <summary> /// IYooAssetBridge 的全局注册点。 /// Launch 程序集通过此静态类访问 Main 注册的桥接实现。 /// </summary> public static class YooAssetBridgeHolder { private static IYooAssetBridge _instance; /// <summary> /// 获取已注册的桥接实例。 /// </summary> public static IYooAssetBridge Instance => _instance; /// <summary> /// 注册桥接实现(由 Main 程序集在初始化时调用)。 /// </summary> public static void Register(IYooAssetBridge bridge) { _instance = bridge; } /// <summary> /// 桥接是否已注册。 /// </summary> public static bool IsRegistered => _instance != null && _instance.IsRegistered; } } Assets/Launch/Common/IYooAssetBridge.cs.meta
New file @@ -0,0 +1,11 @@ fileFormatVersion: 2 guid: f1ec0c19dc4344d4da9da6e52850e783 MonoImporter: externalObjects: {} serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: assetBundleName: assetBundleVariant: Assets/Launch/Launch.cs
@@ -11,6 +11,7 @@ using UnityEngine.Networking; using LaunchCommon; using HybridCLR; using YooAsset; public class Launch : MonoBehaviour { @@ -51,7 +52,7 @@ m_Instance = this; #if !UNITY_EDITOR #if !UNITY_EDITOR && !UNITY_WEBGL if (File.Exists(Directory.GetParent(Application.persistentDataPath) + "/Debug") || LocalSave.GetString("#@#BrancH") != string.Empty) { @@ -72,9 +73,48 @@ Debug.Log("Launch Start"); InitPlugins(); // 1. 尽早初始化 YooAsset,确保 LocalResManager 加载资源时可使用 YooAsset await InitYooAssetEarlyAsync(); InitSetting(); // 1. 打开加载界面 } /// <summary> /// 在 Launch 阶段尽早初始化 YooAsset。 /// 完成后 LocalResManager.LoadSprite/LoadBuiltInPrefab 将通过 YooAsset 加载资源。 /// </summary> private async UniTask InitYooAssetEarlyAsync() { try { #if UNITY_EDITOR var playMode = EPlayMode.EditorSimulateMode; #elif UNITY_WEBGL var playMode = EPlayMode.WebPlayMode; #else var playMode = EPlayMode.OfflinePlayMode; #endif Debug.Log($"[Launch] Initializing YooAsset early with PlayMode={playMode}"); await YooAssetInitializer.Instance.InitializeAsync(playMode); if (YooAssetInitializer.Instance.State == YooAssetInitializer.InitState.InitFailed) { Debug.LogError($"[Launch] YooAsset early init failed: {YooAssetInitializer.Instance.LastError}"); return; } // EditorSimulateMode 和 OfflinePlayMode 不需要远程版本管理, // 直接标记为 Ready await YooAssetInitializer.Instance.RequestVersionAndUpdateAsync(); Debug.Log("[Launch] YooAsset early init completed. State: " + YooAssetInitializer.Instance.State); } catch (Exception ex) { Debug.LogError($"[Launch] YooAsset early init exception: {ex}"); } } private void InitSetting() @@ -203,6 +243,10 @@ DownLoadAndDiscompressTask.Destroy(); } // YooAssetInitializer 不在此处销毁 —— 其 DefaultPackage 需要保留 // 供 Main 程序集中 YooAssetService 接管使用(通过 IYooAssetBridge) // YooAssetInitializer 的 Release 由 YooAssetService 初始化时决定 if (null != launchExWin) { Destroy(launchExWin); Assets/Launch/Manager/LocalResManager.cs
@@ -3,10 +3,12 @@ using System.Collections.Generic; using Cysharp.Threading.Tasks; using System; using System.Threading; using UnityEngine.U2D; using LitJson; using System.IO; using UnityEngine.Networking; using YooAsset; #if UNITY_EDITOR using UnityEditor; @@ -137,9 +139,18 @@ } } [Obsolete("Legacy AB loading — use YooAsset via YooAssetInitializer")] private AssetBundle spriteBundle = null; //需要卸载 [Obsolete("Legacy AB loading — use YooAsset via YooAssetInitializer")] private AssetBundle prefabBundle = null; //需要卸载 private SpriteAtlas spriteAtlas = null; /// <summary> /// YooAsset 是否已就绪(由 YooAssetInitializer 初始化) /// </summary> private bool IsYooAssetReady => YooAssetInitializer.IsValid() && YooAssetInitializer.Instance.State == YooAssetInitializer.InitState.Ready && YooAssetInitializer.Instance.DefaultPackage != null; public void Init() { @@ -152,6 +163,7 @@ } var parentDirectory = Directory.GetParent(Application.persistentDataPath); #if !UNITY_WEBGL if (File.Exists(parentDirectory + "/Debug")) { var content = File.ReadAllText(parentDirectory + "/Debug"); @@ -161,6 +173,7 @@ debugBranch = json.branch; } } #endif Clock.Init(); Debug.Log("LocalResManager.Init"); @@ -168,8 +181,10 @@ public void Release() { #pragma warning disable CS0612, CS0618 // Suppress obsolete warnings for legacy cleanup spriteBundle?.Unload(true); //true完全卸载,更新后重新加载 prefabBundle?.Unload(true); #pragma warning restore CS0612, CS0618 assetVersions = null; localAssetVersions = null; spriteAtlas = null; @@ -237,6 +252,10 @@ return path; } /// <summary> /// 同步加载 Sprite。 /// 优先使用 YooAsset(若已初始化),否则回退到传统 AssetBundle 加载。 /// </summary> public Sprite LoadSprite(string name) { Sprite sprite = null; @@ -251,15 +270,22 @@ var spriteAtlas = UnityEditor.AssetDatabase.LoadAssetAtPath<SpriteAtlas>("Assets/ResourcesOut/BuiltIn/Sprites/sprites.spriteatlasv2"); sprite = spriteAtlas.GetSprite(name); } #else if (spriteBundle == null) if (IsYooAssetReady) { string _path = GetAssetFilePath("builtin/sprites"); spriteBundle = AssetBundle.LoadFromFile(_path); var handle = YooAssetInitializer.Instance.DefaultPackage.LoadAssetSync<Sprite>(name); sprite = handle.AssetObject as Sprite; } sprite = spriteBundle.LoadAsset(name, typeof(Sprite)) as Sprite; else { // Legacy fallback — AssetBundle.LoadFromFile if (spriteBundle == null) { string _path = GetAssetFilePath("builtin/sprites"); spriteBundle = AssetBundle.LoadFromFile(_path); } sprite = spriteBundle.LoadAsset(name, typeof(Sprite)) as Sprite; } #endif if (sprite == null) { @@ -269,6 +295,49 @@ return sprite; } /// <summary> /// 异步加载 Sprite(WebGL 兼容)。 /// 使用 YooAsset 异步加载 API,适用于所有平台。 /// </summary> public async UniTask<Sprite> LoadSpriteAsync(string name, CancellationToken cancellationToken = default) { Sprite sprite = null; #if UNITY_EDITOR if (excludePngs.Contains(StringUtility.Concat(name, ".png"))) { var path = StringUtility.Concat("Assets/ResourcesOut/BuiltIn/Sprites/", name, ".png"); sprite = UnityEditor.AssetDatabase.LoadAssetAtPath<Sprite>(path); } else { var atlas = UnityEditor.AssetDatabase.LoadAssetAtPath<SpriteAtlas>("Assets/ResourcesOut/BuiltIn/Sprites/sprites.spriteatlasv2"); sprite = atlas.GetSprite(name); } #else if (IsYooAssetReady) { var handle = YooAssetInitializer.Instance.DefaultPackage.LoadAssetAsync<Sprite>(name); await handle.ToUniTask(cancellationToken: cancellationToken); sprite = handle.AssetObject as Sprite; } else { // Fallback to sync if YooAsset not ready (should not happen in normal flow) Debug.LogWarning($"[LocalResManager] LoadSpriteAsync: YooAsset not ready, falling back to sync for '{name}'"); sprite = LoadSprite(name); } #endif if (sprite == null) { Debug.LogErrorFormat("LoadSpriteAsync() => 加载不到资源: {0}.", name); } return sprite; } /// <summary> /// 同步加载内置预制体。 /// 优先使用 YooAsset(若已初始化),否则回退到传统 AssetBundle 加载。 /// </summary> public GameObject LoadBuiltInPrefab(string name) { GameObject prefab = null; @@ -276,12 +345,21 @@ var path = string.Concat("Assets/ResourcesOut/BuiltIn/Prefabs/", name, ".prefab"); prefab = UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>(path); #else if (prefabBundle == null) if (IsYooAssetReady) { string _path = GetAssetFilePath("builtin/prefabs"); prefabBundle = AssetBundle.LoadFromFile(_path); var handle = YooAssetInitializer.Instance.DefaultPackage.LoadAssetSync<GameObject>(name); prefab = handle.AssetObject as GameObject; } prefab = prefabBundle.LoadAsset(name) as GameObject; else { // Legacy fallback — AssetBundle.LoadFromFile if (prefabBundle == null) { string _path = GetAssetFilePath("builtin/prefabs"); prefabBundle = AssetBundle.LoadFromFile(_path); } prefab = prefabBundle.LoadAsset(name) as GameObject; } #endif if (prefab == null) { @@ -291,6 +369,36 @@ return prefab; } /// <summary> /// 异步加载内置预制体(WebGL 兼容)。 /// 使用 YooAsset 异步加载 API,适用于所有平台。 /// </summary> public async UniTask<GameObject> LoadBuiltInPrefabAsync(string name, CancellationToken cancellationToken = default) { GameObject prefab = null; #if UNITY_EDITOR var path = string.Concat("Assets/ResourcesOut/BuiltIn/Prefabs/", name, ".prefab"); prefab = UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>(path); #else if (IsYooAssetReady) { var handle = YooAssetInitializer.Instance.DefaultPackage.LoadAssetAsync<GameObject>(name); await handle.ToUniTask(cancellationToken: cancellationToken); prefab = handle.AssetObject as GameObject; } else { Debug.LogWarning($"[LocalResManager] LoadBuiltInPrefabAsync: YooAsset not ready, falling back to sync for '{name}'"); prefab = LoadBuiltInPrefab(name); } #endif if (prefab == null) { Debug.LogErrorFormat("LoadBuiltInPrefabAsync() => 加载不到资源: {0}.", name); } return prefab; } static Dictionary<string, string> languageShowDict = new Dictionary<string, string>();//射中显示的多语言版本 Dictionary<string, string> languageDict = new Dictionary<string, string>();// unity语言配置对应的约定字符 Assets/Launch/Manager/YooAssetInitializer.cs
New file @@ -0,0 +1,403 @@ // ============================================================================ // YooAssetInitializer.cs — Launch 阶段 YooAsset 初始化器 // 在 Launch AOT 程序集中执行 YooAsset 的包裹创建、版本请求与 Manifest 更新 // 支持 EditorSimulateMode / HostPlayMode / OfflinePlayMode / WebPlayMode // 支持多 Package 并行初始化 // ============================================================================ using System; using System.Collections.Generic; using Cysharp.Threading.Tasks; using UnityEngine; using YooAsset; /// <summary> /// Launch 阶段负责 YooAsset 资源系统的早期初始化。 /// 完成 ResourcePackage 的创建、初始化参数配置、版本请求与 Manifest 更新。 /// 支持多 Package 初始化,包名须与 AssetBundleCollectorSetting 一致。 /// </summary> public class YooAssetInitializer : Singleton<YooAssetInitializer> { /// <summary> /// 初始化状态 /// </summary> public enum InitState { Uninitialized, Initializing, Initialized, VersionChecked, Ready, InitFailed, VersionFailed, } // ==================================================================== // Package 名称常量 — 必须与 AssetBundleCollectorSetting.asset 一致 // Launch 程序集无法引用 Main 的 YooAssetPackageConfig,在此重复定义 // ==================================================================== /// <summary>默认包名 — Prefab 包含启动必需资源</summary> public const string DEFAULT_PACKAGE_NAME = "Prefab"; /// <summary> /// Launch 阶段需要初始化的包名(与 Collector 一致)。 /// </summary> private static readonly string[] LAUNCH_PACKAGES = new[] { "Prefab", "UI", "UIEffect", "Battle", "Audio" }; private EPlayMode _playMode; private IRemoteServices _remoteServices; private ResourcePackage _defaultPackage; private readonly Dictionary<string, ResourcePackage> _packages = new Dictionary<string, ResourcePackage>(); /// <summary> /// 当前初始化状态 /// </summary> public InitState State { get; private set; } = InitState.Uninitialized; /// <summary> /// 最后一次错误信息 /// </summary> public string LastError { get; private set; } /// <summary> /// 获取已初始化的默认包裹(向后兼容 LocalResManager) /// </summary> public ResourcePackage DefaultPackage => _defaultPackage; /// <summary> /// 当前运行模式 /// </summary> public EPlayMode PlayMode => _playMode; /// <summary> /// 获取指定名称的已初始化包裹,找不到返回 null /// </summary> public ResourcePackage GetPackage(string packageName) { _packages.TryGetValue(packageName, out var pkg); return pkg; } /// <summary> /// 所有已成功初始化的包名 /// </summary> public IEnumerable<string> InitializedPackageNames => _packages.Keys; // ==================================================================== // 初始化 // ==================================================================== /// <summary> /// 初始化 YooAsset,创建并初始化多个 ResourcePackage。 /// </summary> /// <param name="playMode">运行模式(EditorSimulateMode / HostPlayMode)</param> /// <param name="remoteServices">CDN 远程服务地址配置(HostPlayMode 必需)</param> /// <param name="packageNames">要初始化的包名列表,null 使用 LAUNCH_PACKAGES</param> public async UniTask InitializeAsync(EPlayMode playMode = EPlayMode.HostPlayMode, IRemoteServices remoteServices = null, string[] packageNames = null) { if (State != InitState.Uninitialized) { Debug.LogWarning($"[YooAssetInitializer] Invalid state for Initialize: {State}"); return; } State = InitState.Initializing; _playMode = playMode; _remoteServices = remoteServices; var names = packageNames ?? LAUNCH_PACKAGES; int successCount = 0; try { // YooAsset 全局初始化(幂等) YooAssets.Initialize(); foreach (var pkgName in names) { try { var 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($"[YooAssetInitializer] Package '{pkgName}' init failed: {initOp.Error}"); continue; } _packages[pkgName] = package; successCount++; // DEFAULT_PACKAGE_NAME 或第一个成功的包作为默认包 if (_defaultPackage == null || pkgName == DEFAULT_PACKAGE_NAME) { _defaultPackage = package; YooAssets.SetDefaultPackage(package); } Debug.Log($"[YooAssetInitializer] Package '{pkgName}' initialized."); } catch (Exception ex) { // EditorSimulateMode 下包不在 Collector 中会抛异常,跳过即可 Debug.LogWarning($"[YooAssetInitializer] Package '{pkgName}' init exception (skipped): {ex.Message}"); } } if (successCount == 0) { LastError = "No packages initialized successfully."; State = InitState.InitFailed; Debug.LogError($"[YooAssetInitializer] {LastError}"); return; } State = InitState.Initialized; Debug.Log($"[YooAssetInitializer] Initialized {successCount}/{names.Length} packages with PlayMode={playMode}"); } catch (Exception ex) { LastError = ex.Message; State = InitState.InitFailed; Debug.LogError($"[YooAssetInitializer] Initialize exception: {ex}"); } } // ==================================================================== // 版本管理 // ==================================================================== /// <summary> /// 请求最新版本号并更新 Manifest(对所有已初始化的包裹)。 /// 仅在 HostPlayMode 下有意义,EditorSimulateMode / OfflinePlayMode 下跳过。 /// </summary> public async UniTask RequestVersionAndUpdateAsync() { if (State != InitState.Initialized) { Debug.LogWarning($"[YooAssetInitializer] Invalid state for RequestVersionAndUpdate: {State}"); return; } // EditorSimulateMode / OfflinePlayMode 不需要远程版本管理 if (_playMode == EPlayMode.EditorSimulateMode || _playMode == EPlayMode.OfflinePlayMode) { State = InitState.VersionChecked; State = InitState.Ready; Debug.Log("[YooAssetInitializer] Skipped version check (local mode). State → Ready"); return; } try { foreach (var kvp in _packages) { var pkgName = kvp.Key; var package = kvp.Value; // 1. 请求版本号 var versionOp = package.RequestPackageVersionAsync(); await versionOp.ToUniTask(); if (versionOp.Status != EOperationStatus.Succeed) { Debug.LogWarning($"[YooAssetInitializer] RequestPackageVersion failed for '{pkgName}': {versionOp.Error}"); continue; } string packageVersion = versionOp.PackageVersion; Debug.Log($"[YooAssetInitializer] Package '{pkgName}' version: {packageVersion}"); // 2. 更新 Manifest var manifestOp = package.UpdatePackageManifestAsync(packageVersion); await manifestOp.ToUniTask(); if (manifestOp.Status != EOperationStatus.Succeed) { Debug.LogWarning($"[YooAssetInitializer] UpdatePackageManifest failed for '{pkgName}': {manifestOp.Error}"); continue; } Debug.Log($"[YooAssetInitializer] Package '{pkgName}' manifest updated to {packageVersion}."); } State = InitState.VersionChecked; State = InitState.Ready; Debug.Log("[YooAssetInitializer] All packages version checked. State → Ready"); } catch (Exception ex) { LastError = ex.Message; State = InitState.VersionFailed; Debug.LogError($"[YooAssetInitializer] Version update exception: {ex}"); } } // ==================================================================== // 下载器创建 // ==================================================================== /// <summary> /// 创建资源下载器,用于下载指定标签的远程资源。 /// </summary> /// <param name="tags">资源标签数组</param> /// <param name="downloadingMaxNumber">同时下载最大数量</param> /// <param name="failedTryAgain">失败重试次数</param> /// <param name="packageName">指定包名,null 则使用默认包</param> /// <returns>下载器操作句柄</returns> public ResourceDownloaderOperation CreateDownloader(string[] tags, int downloadingMaxNumber = 10, int failedTryAgain = 3, string packageName = null) { if (State < InitState.Ready) { Debug.LogError($"[YooAssetInitializer] Cannot create downloader in state: {State}"); return null; } var package = _defaultPackage; if (!string.IsNullOrEmpty(packageName) && _packages.TryGetValue(packageName, out var target)) { package = target; } // 多标签合并下载器 if (tags == null || tags.Length == 0) { return package.CreateResourceDownloader(downloadingMaxNumber, failedTryAgain); } if (tags.Length == 1) { return package.CreateResourceDownloader(tags[0], downloadingMaxNumber, failedTryAgain); } // 多个标签使用第一个标签创建下载器(YooAsset 2.x 不支持多标签合并创建) return package.CreateResourceDownloader(tags[0], downloadingMaxNumber, failedTryAgain); } /// <summary> /// 执行下载操作并等待完成。 /// </summary> public async UniTask DownloadAsync(ResourceDownloaderOperation downloader, IProgress<float> progress = null) { if (downloader == null) { Debug.LogWarning("[YooAssetInitializer] Downloader is null."); return; } if (downloader.TotalDownloadCount == 0) { Debug.Log("[YooAssetInitializer] No resources need to download."); progress?.Report(1f); return; } Debug.Log($"[YooAssetInitializer] Start downloading {downloader.TotalDownloadCount} files, total {downloader.TotalDownloadBytes} bytes"); downloader.BeginDownload(); while (!downloader.IsDone) { progress?.Report(downloader.Progress); await UniTask.Yield(); } if (downloader.Status != EOperationStatus.Succeed) { Debug.LogError($"[YooAssetInitializer] Download failed: {downloader.Error}"); throw new InvalidOperationException($"Resource download failed: {downloader.Error}"); } progress?.Report(1f); Debug.Log("[YooAssetInitializer] Download completed."); } // ==================================================================== // 辅助方法 // ==================================================================== private InitializeParameters CreateInitParameters(EPlayMode playMode, IRemoteServices remoteServices, string packageName) { switch (playMode) { case EPlayMode.EditorSimulateMode: { #if UNITY_EDITOR var simulateResult = EditorSimulateModeHelper.SimulateBuild(packageName); return new EditorSimulateModeParameters { EditorFileSystemParameters = FileSystemParameters .CreateDefaultEditorFileSystemParameters(simulateResult.PackageRootDirectory) }; #else throw new InvalidOperationException("EditorSimulateMode is only available in Unity Editor."); #endif } case EPlayMode.HostPlayMode: { return new HostPlayModeParameters { BuildinFileSystemParameters = FileSystemParameters .CreateDefaultBuildinFileSystemParameters(), CacheFileSystemParameters = FileSystemParameters .CreateDefaultCacheFileSystemParameters(remoteServices) }; } case EPlayMode.OfflinePlayMode: { return new OfflinePlayModeParameters { BuildinFileSystemParameters = FileSystemParameters .CreateDefaultBuildinFileSystemParameters() }; } case EPlayMode.WebPlayMode: { var webParams = new WebPlayModeParameters(); #if UNITY_WEBGL && WEIXINMINIGAME && !UNITY_EDITOR // 微信小游戏:使用 WechatFileSystem 进行资源缓存 string packageRoot = $"{WeChatWASM.WX.env.USER_DATA_PATH}/__GAME_FILE_CACHE"; webParams.WebServerFileSystemParameters = WechatFileSystemCreater .CreateFileSystemParameters(packageRoot, remoteServices); #elif UNITY_WEBGL && DOUYINMINIGAME && !UNITY_EDITOR // 抖音小游戏:使用 TiktokFileSystem 进行资源缓存 string packageRoot = TTSDK.TTFileSystem.USER_DATA_PATH + "/__GAME_FILE_CACHE"; webParams.WebServerFileSystemParameters = TiktokFileSystemCreater .CreateFileSystemParameters(packageRoot, remoteServices); #else // 默认 WebGL:使用标准 WebServer 文件系统 webParams.WebServerFileSystemParameters = FileSystemParameters .CreateDefaultWebServerFileSystemParameters(); if (remoteServices != null) { webParams.WebRemoteFileSystemParameters = FileSystemParameters .CreateDefaultWebRemoteFileSystemParameters(remoteServices); } #endif return webParams; } default: throw new ArgumentOutOfRangeException(nameof(playMode), playMode, "Unsupported PlayMode."); } } /// <summary> /// 释放资源,重置状态。 /// </summary> public void Release() { _defaultPackage = null; _packages.Clear(); _remoteServices = null; LastError = null; State = InitState.Uninitialized; } } Assets/Launch/Manager/YooAssetInitializer.cs.meta
New file @@ -0,0 +1,11 @@ fileFormatVersion: 2 guid: fd8ad00c7c0e32543a87d5a6fd048067 MonoImporter: externalObjects: {} serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: assetBundleName: assetBundleVariant: Assets/Launch/UI/LaunchWins/LaunchExWin.cs
@@ -2,6 +2,7 @@ using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using Cysharp.Threading.Tasks; using LaunchCommon; public class LaunchExWin : MonoBehaviour @@ -36,11 +37,35 @@ // m_BackGround.overrideSprite = sprite; // m_BackGround.preserveAspect = true; sliderText = InitialFunctionConfig.Get("Language").Numerical3; // 同步加载保留(YooAsset 初始化后走 YooAsset sync API,否则走 legacy AB) imagebg1.sprite = LocalResManager.Instance.LoadSprite("TY_TB_JH1"); imagebg2.sprite = LocalResManager.Instance.LoadSprite("TY_TB_JH1"); imageCircle.sprite = LocalResManager.Instance.LoadSprite("TY_TB_JH2"); imagebg3.sprite = LocalResManager.Instance.LoadSprite("LoadingBottom"); imageloding.sprite = LocalResManager.Instance.LoadSprite("LoadingSlider"); } /// <summary> /// 异步初始化 Launch 界面精灵(WebGL 兼容)。 /// 在 OpenWindowAsync 中调用,Awake 中的同步加载仅作后备。 /// </summary> public async UniTask InitSpritesAsync() { sliderText = InitialFunctionConfig.Get("Language").Numerical3; var sprites = await UniTask.WhenAll( LocalResManager.Instance.LoadSpriteAsync("TY_TB_JH1"), LocalResManager.Instance.LoadSpriteAsync("TY_TB_JH2"), LocalResManager.Instance.LoadSpriteAsync("LoadingBottom"), LocalResManager.Instance.LoadSpriteAsync("LoadingSlider") ); if (this == null) return; // destroyed check after await imagebg1.sprite = sprites.Item1; imagebg2.sprite = sprites.Item1; imageCircle.sprite = sprites.Item2; imagebg3.sprite = sprites.Item3; imageloding.sprite = sprites.Item4; } private void OnEnable() @@ -134,4 +159,30 @@ window.transform.localScale = Vector3.zero; return window; } /// <summary> /// 异步打开 Launch 窗口(WebGL 兼容)。 /// 通过 YooAsset 异步加载预制体和精灵,适用于所有平台。 /// </summary> public static async UniTask<GameObject> OpenWindowAsync() { var prefab = await LocalResManager.Instance.LoadBuiltInPrefabAsync("LaunchExWin"); if (prefab == null) { Debug.LogError("[LaunchExWin] Failed to load LaunchExWin prefab asynchronously."); return null; } GameObject window = GameObject.Instantiate(prefab); window.transform.localScale = Vector3.zero; // 异步加载精灵 var launchWin = window.GetComponent<LaunchExWin>(); if (launchWin != null) { await launchWin.InitSpritesAsync(); } return window; } } Assets/Plugins/YooAsset.MiniGame.meta
New file @@ -0,0 +1,8 @@ fileFormatVersion: 2 guid: 448a76f35c893fb4598fda8d52e76a58 folderAsset: yes DefaultImporter: externalObjects: {} userData: assetBundleName: assetBundleVariant: Assets/Plugins/YooAsset.MiniGame/README.md
New file @@ -0,0 +1,31 @@ # YooAsset Mini Game File Systems 此目录包含小游戏平台专用的 YooAsset 文件系统实现。 ## 导入说明 从 YooAsset 2.3.15 的 Samples~ 目录按需复制对应平台的实现: ``` Library/PackageCache/com.tuyoogame.yooasset@2.3.15/Samples~/Mini Game/Runtime/ ├── WechatFileSystem/ → 复制到 Assets/Plugins/YooAsset.MiniGame/WechatFileSystem/ ├── TiktokFileSystem/ → 复制到 Assets/Plugins/YooAsset.MiniGame/TiktokFileSystem/ └── YooAsset.MiniGame.asmdef ``` ## 平台编译宏 - **微信小游戏**: `UNITY_WEBGL && WEIXINMINIGAME` - **抖音小游戏**: `UNITY_WEBGL && DOUYINMINIGAME` ## 文件系统缓存路径 | 平台 | 缓存根路径 | |------|-----------| | 微信 | `WX.env.USER_DATA_PATH/__GAME_FILE_CACHE` | | 抖音 | `TTFileSystem.USER_DATA_PATH/__GAME_FILE_CACHE` | ## 使用方式 在 `YooAssetInitializer.CreateInitParameters` 和 `YooAssetService.CreateInitParameters` 中已集成。 当检测到对应平台宏时,会自动使用对应的文件系统创建器。 Assets/Plugins/YooAsset.MiniGame/README.md.meta
New file @@ -0,0 +1,7 @@ fileFormatVersion: 2 guid: fc233d1ce92f8164abbd31509b132529 TextScriptImporter: externalObjects: {} userData: assetBundleName: assetBundleVariant: Assets/Plugins/YooAsset.UniTask.meta
New file @@ -0,0 +1,8 @@ fileFormatVersion: 2 guid: 2be0d63fc0ca312459c0d0c4a802efe2 folderAsset: yes DefaultImporter: externalObjects: {} userData: assetBundleName: assetBundleVariant: Assets/Plugins/YooAsset.UniTask/Runtime.meta
New file @@ -0,0 +1,8 @@ fileFormatVersion: 2 guid: 448d43cd584a196498dedf8c0e71153f folderAsset: yes DefaultImporter: externalObjects: {} userData: assetBundleName: assetBundleVariant: Assets/Plugins/YooAsset.UniTask/Runtime/External.meta
New file @@ -0,0 +1,8 @@ fileFormatVersion: 2 guid: 7349d92658667a446946561d5ec25189 folderAsset: yes DefaultImporter: externalObjects: {} userData: assetBundleName: assetBundleVariant: Assets/Plugins/YooAsset.UniTask/Runtime/External/YooAsset.meta
New file @@ -0,0 +1,8 @@ fileFormatVersion: 2 guid: 01c8f5fcda5fc6742b9c202dbd83146c folderAsset: yes DefaultImporter: externalObjects: {} userData: assetBundleName: assetBundleVariant: Assets/Plugins/YooAsset.UniTask/Runtime/External/YooAsset/AsyncOperationBaseExtensions.cs
New file @@ -0,0 +1,125 @@ #if UNITASK_YOOASSET_SUPPORT using System; using YooAsset; using static Cysharp.Threading.Tasks.Internal.Error; namespace Cysharp.Threading.Tasks { public static class AsyncOperationBaseExtensions { public static UniTask.Awaiter GetAwaiter(this AsyncOperationBase handle) { return ToUniTask(handle).GetAwaiter(); } public static UniTask ToUniTask(this AsyncOperationBase handle, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update) { ThrowArgumentNullException(handle, nameof(handle)); if (handle.IsDone) { return UniTask.CompletedTask; } return new UniTask( AsyncOperationBaserConfiguredSource.Create(handle, timing, progress, out var token), token ); } sealed class AsyncOperationBaserConfiguredSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<AsyncOperationBaserConfiguredSource> { private static TaskPool<AsyncOperationBaserConfiguredSource> _pool; private AsyncOperationBaserConfiguredSource _nextNode; private readonly Action<AsyncOperationBase> _continuationAction; private AsyncOperationBase _handle; private IProgress<float> _progress; private bool _completed; private UniTaskCompletionSourceCore<AsyncUnit> _core; public ref AsyncOperationBaserConfiguredSource NextNode => ref _nextNode; static AsyncOperationBaserConfiguredSource() { TaskPool.RegisterSizeGetter(typeof(AsyncOperationBaserConfiguredSource), () => _pool.Size); } AsyncOperationBaserConfiguredSource() { _continuationAction = Continuation; } public static IUniTaskSource Create(AsyncOperationBase handle, PlayerLoopTiming timing, IProgress<float> progress, out short token) { if (!_pool.TryPop(out var result)) { result = new AsyncOperationBaserConfiguredSource(); } result._handle = handle; result._progress = progress; result._completed = false; TaskTracker.TrackActiveTask(result, 3); if (progress != null) { PlayerLoopHelper.AddAction(timing, result); } handle.Completed += result._continuationAction; token = result._core.Version; return result; } private void Continuation(AsyncOperationBase _) { _handle.Completed -= _continuationAction; if (_completed) { TryReturn(); } else { _completed = true; if (_handle.Status == EOperationStatus.Failed) { _core.TrySetException(new Exception(_handle.Error)); } else { _core.TrySetResult(AsyncUnit.Default); } } } private bool TryReturn() { TaskTracker.RemoveTracking(this); _core.Reset(); _handle = default; _progress = default; return _pool.TryPush(this); } public UniTaskStatus GetStatus(short token) => _core.GetStatus(token); public void OnCompleted(Action<object> continuation, object state, short token) { _core.OnCompleted(continuation, state, token); } public void GetResult(short token) { _core.GetResult(token); } public UniTaskStatus UnsafeGetStatus() => _core.UnsafeGetStatus(); public bool MoveNext() { if (_completed) { TryReturn(); return false; } if (!_handle.IsDone) { _progress?.Report(_handle.Progress); } return true; } } } } #endif Assets/Plugins/YooAsset.UniTask/Runtime/External/YooAsset/AsyncOperationBaseExtensions.cs.meta
New file @@ -0,0 +1,3 @@ fileFormatVersion: 2 guid: 2cceff5ec1f84bd0a6a9b4ed7719527c timeCreated: 1651978895 Assets/Plugins/YooAsset.UniTask/Runtime/External/YooAsset/OperationHandleBaseExtensions.cs
New file @@ -0,0 +1,221 @@ #if UNITASK_YOOASSET_SUPPORT #if UNITY_2020_1_OR_NEWER && ! UNITY_2021 #define UNITY_2020_BUG #endif using System; using System.Runtime.CompilerServices; using YooAsset; using static Cysharp.Threading.Tasks.Internal.Error; namespace Cysharp.Threading.Tasks { public static class HandleBaseExtensions { public static UniTask.Awaiter GetAwaiter(this HandleBase handle) { return ToUniTask(handle).GetAwaiter(); } public static UniTask ToUniTask(this HandleBase handle, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update) { ThrowArgumentNullException(handle, nameof(handle)); if (!handle.IsValid) { return UniTask.CompletedTask; } return new UniTask( HandleBaserConfiguredSource.Create(handle, timing, progress, out var token), token ); } sealed class HandleBaserConfiguredSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<HandleBaserConfiguredSource> { private static TaskPool<HandleBaserConfiguredSource> _pool; private HandleBaserConfiguredSource _nextNode; private readonly Action<HandleBase> _continuationAction; private HandleBase _handle; private IProgress<float> _progress; private bool _completed; private UniTaskCompletionSourceCore<AsyncUnit> _core; public ref HandleBaserConfiguredSource NextNode => ref _nextNode; static HandleBaserConfiguredSource() { TaskPool.RegisterSizeGetter(typeof(HandleBaserConfiguredSource), () => _pool.Size); } HandleBaserConfiguredSource() { _continuationAction = Continuation; } public static IUniTaskSource Create(HandleBase handle, PlayerLoopTiming timing, IProgress<float> progress, out short token) { if (!_pool.TryPop(out var result)) { result = new HandleBaserConfiguredSource(); } result._handle = handle; result._progress = progress; result._completed = false; TaskTracker.TrackActiveTask(result, 3); if (progress != null) { PlayerLoopHelper.AddAction(timing, result); } // BUG 在 Unity 2020.3.36 版本测试中, IL2Cpp 会报 如下错误 // BUG ArgumentException: Incompatible Delegate Types. First is System.Action`1[[YooAsset.AssetHandle, YooAsset, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]] second is System.Action`1[[YooAsset.OperationHandleBase, YooAsset, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]] // BUG 也可能报的是 Action '1' Action '1' 的 InvalidCastException // BUG 此处不得不这么修改, 如果后续 Unity 修复了这个问题, 可以恢复之前的写法 #if UNITY_2020_BUG switch (handle) { case AssetHandle asset_handle: asset_handle.Completed += result.AssetContinuation; break; case SceneHandle scene_handle: scene_handle.Completed += result.SceneContinuation; break; case SubAssetsHandle sub_asset_handle: sub_asset_handle.Completed += result.SubContinuation; break; case RawFileHandle raw_file_handle: raw_file_handle.Completed += result.RawFileContinuation; break; case AllAssetsHandle all_assets_handle: all_assets_handle.Completed += result.AllAssetsContinuation; break; } #else switch (handle) { case AssetHandle asset_handle: asset_handle.Completed += result.continuationAction; break; case SceneHandle scene_handle: scene_handle.Completed += result.continuationAction; break; case SubAssetsHandle sub_asset_handle: sub_asset_handle.Completed += result.continuationAction; break; case RawFileHandle raw_file_handle: raw_file_handle.Completed += result.continuationAction; break; case AllAssetsHandle all_assets_handle: all_assets_handle.Completed += result.continuationAction; break; } #endif token = result._core.Version; return result; } #if UNITY_2020_BUG private void AssetContinuation(AssetHandle handle) { handle.Completed -= AssetContinuation; BaseContinuation(); } private void SceneContinuation(SceneHandle handle) { handle.Completed -= SceneContinuation; BaseContinuation(); } private void SubContinuation(SubAssetsHandle handle) { handle.Completed -= SubContinuation; BaseContinuation(); } private void RawFileContinuation(RawFileHandle handle) { handle.Completed -= RawFileContinuation; BaseContinuation(); } private void AllAssetsContinuation(AllAssetsHandle handle) { handle.Completed -= AllAssetsContinuation; BaseContinuation(); } #endif [MethodImpl(MethodImplOptions.AggressiveInlining)] private void BaseContinuation() { if (_completed) { TryReturn(); } else { _completed = true; if (_handle.Status == EOperationStatus.Failed) { _core.TrySetException(new Exception(_handle.LastError)); } else { _core.TrySetResult(AsyncUnit.Default); } } } private void Continuation(HandleBase _) { switch (_handle) { case AssetHandle asset_handle: asset_handle.Completed -= _continuationAction; break; case SceneHandle scene_handle: scene_handle.Completed -= _continuationAction; break; case SubAssetsHandle sub_asset_handle: sub_asset_handle.Completed -= _continuationAction; break; case RawFileHandle raw_file_handle: raw_file_handle.Completed -= _continuationAction; break; case AllAssetsHandle all_assets_handle: all_assets_handle.Completed -= _continuationAction; break; } BaseContinuation(); } private bool TryReturn() { TaskTracker.RemoveTracking(this); _core.Reset(); _handle = default; _progress = default; return _pool.TryPush(this); } public UniTaskStatus GetStatus(short token) => _core.GetStatus(token); public void OnCompleted(Action<object> continuation, object state, short token) { _core.OnCompleted(continuation, state, token); } public void GetResult(short token) { _core.GetResult(token); } public UniTaskStatus UnsafeGetStatus() => _core.UnsafeGetStatus(); public bool MoveNext() { if (_completed) { TryReturn(); return false; } if (_handle.IsValid) { _progress?.Report(_handle.Progress); } return true; } } } } #endif Assets/Plugins/YooAsset.UniTask/Runtime/External/YooAsset/OperationHandleBaseExtensions.cs.meta
New file @@ -0,0 +1,3 @@ fileFormatVersion: 2 guid: e1c9a3a6de2246bf88547a6b59b99b9f timeCreated: 1650851321 Assets/Plugins/YooAsset.UniTask/Runtime/External/YooAsset/UniTask.YooAsset.asmdef
New file @@ -0,0 +1,23 @@ { "name": "UniTask.YooAsset", "rootNamespace": "", "references": [ "GUID:f51ebe6a0ceec4240a699833d6309b23", "GUID:e34a5702dd353724aa315fb8011f08c3" ], "includePlatforms": [], "excludePlatforms": [], "allowUnsafeCode": false, "overrideReferences": false, "precompiledReferences": [], "autoReferenced": true, "defineConstraints": [], "versionDefines": [ { "name": "com.cysharp.unitask", "expression": "", "define": "UNITASK_YOOASSET_SUPPORT" } ], "noEngineReferences": false } Assets/Plugins/YooAsset.UniTask/Runtime/External/YooAsset/UniTask.YooAsset.asmdef.meta
New file @@ -0,0 +1,7 @@ fileFormatVersion: 2 guid: 1278a46ce459c5a46b4eaeda148684ef AssemblyDefinitionImporter: externalObjects: {} userData: assetBundleName: assetBundleVariant: Assets/Plugins/YooAsset.UniTask/UniTaskRef.meta
New file @@ -0,0 +1,8 @@ fileFormatVersion: 2 guid: 9a37bcddb33f328418a9c5eaa682e6dd folderAsset: yes DefaultImporter: externalObjects: {} userData: assetBundleName: assetBundleVariant: Assets/Plugins/YooAsset.UniTask/UniTaskRef/UniTaskRef.asmref
New file @@ -0,0 +1,3 @@ { "reference": "GUID:f51ebe6a0ceec4240a699833d6309b23" } Assets/Plugins/YooAsset.UniTask/UniTaskRef/UniTaskRef.asmref.meta
New file @@ -0,0 +1,7 @@ fileFormatVersion: 2 guid: fb1a9972a41e10f40a752774a402830a AssemblyDefinitionReferenceImporter: externalObjects: {} userData: assetBundleName: assetBundleVariant: Assets/Plugins/YooAsset.UniTask/UniTaskRef/_InternalVisibleTo.cs
New file @@ -0,0 +1,3 @@ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("UniTask.YooAsset")] Assets/Plugins/YooAsset.UniTask/UniTaskRef/_InternalVisibleTo.cs.meta
New file @@ -0,0 +1,11 @@ fileFormatVersion: 2 guid: dc0f48d84ee89ad499856840eea08a64 MonoImporter: externalObjects: {} serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: assetBundleName: assetBundleVariant: