diff --git a/Assets/YooAsset/CHANGELOG.md b/Assets/YooAsset/CHANGELOG.md index e10db8fb..90dd9a42 100644 --- a/Assets/YooAsset/CHANGELOG.md +++ b/Assets/YooAsset/CHANGELOG.md @@ -2,1359 +2,6 @@ All notable changes to this package will be documented in this file. -## [2.3.18] - 2025-12-04 - -### Fixed - -- (#676) 修复了UniTask扩展包的编译报错。 -- (#684) 修复了资源配置窗口Group列表数量过多的时候,添加和删除按钮会变小的问题。 -- (#700) [**严重**] 修复了小游戏扩展库的下载器再失败后重试逻辑不起效的问题。 - -### Added - -- (#683) 新增了内置文件系统类初始化参数:UNPACK_FILE_SYSTEM_ROOT - - ```csharp - class FileSystemParametersDefine - { - // 指定解压文件的根目录 - public const string UNPACK_FILE_SYSTEM_ROOT = "UNPACK_FILE_SYSTEM_ROOT"; - } - ``` - -- (#682) 原生文件构建管线新增构建参数:IncludePathInHash - - ```csharp - class RawFileBuildParameters : BuildParameters - { - /// - /// 文件哈希值计算包含路径信息 - /// - public bool IncludePathInHash = false; - } - ``` - -- (#671) 新增扩展工具,可以生成空的包裹内置资源目录文件。 - - ```csharp - public class CreateEmptyCatalogWindow : EditorWindow - ``` - -- (#694) 新增资源清理方式:ClearBundleFilesByLocations - - ```csharp - public enum EFileClearMode - { - /// - /// 清理指定地址的文件 - /// 说明:需要指定参数,可选:string, string[], List - /// - ClearBundleFilesByLocations, - } - ``` - -## [2.3.17] - 2025-10-30 - -**非常重要**:修复了#627优化导致的资源清单CRC值为空的问题。 - -该问题会导致下载的损坏文件验证通过。 - -影响范围:v2.3.15版本,v2.3.16版本。 - -**非常重要**:(#661) 修复了Package销毁过程中,遇到正在加载的AssetBundle会导致无法卸载的问题。 - -该问题是偶现,引擎会提示AssetBundle已经加载,无法加载新的文件,导致资源对象加载失败! - -影响范围:所有版本! - -### Fixed - -- (#645) 修复了着色器变种收集工具,在极端情况下变种收集不完整的问题。 -- (#646) 修复了EditorSimulateMode模式下开启模拟下载tag不生效的问题。 -- (#667) 修复了所有编辑器窗口针对中文IME的输入问题。 -- (#670) 修复了Catalog文件生成过程中白名单未考虑自定义清单前缀名。 - -### Improvements - -- 重构并统一了资源清单的反序列化逻辑。 -- (#650) 解决互相依赖的资源包无法卸载的问题。需要开启宏定义:YOOASSET_EXPERIMENTAL -- (#655) 优化了初始化的时候,缓存文件搜索效率。安卓平台性能提升1倍,IOS平台性能提升3倍。 - -### Added - -- (#643) 新增构建参数,可以节省资源清单运行时内存 - - ```csharp - class ScriptableBuildParameters - { - /// - /// 使用可寻址地址代替资源路径 - /// 说明:开启此项可以节省运行时清单占用的内存! - /// - public bool ReplaceAssetPathWithAddress = false; - } - ``` - -- (#648) 新增初始化参数,可以自动释放引用计数为零的资源包 - - ```csharp - class InitializeParameters - { - /// - /// 当资源引用计数为零的时候自动释放资源包 - /// - public bool AutoUnloadBundleWhenUnused = false; - } - ``` - -### Changed - -- 程序集宏定义代码转移到扩展工程。参考MacroSupport文件夹。 - -## [2.3.16] - 2025-09-17 - -### Improvements - -- (#638) 优化了Provider加载机制,引用计数为零时自动挂起! - -### Fixed - -- (#644) [**严重**] 修复了2.3.15版本,资产量巨大的情况下,编辑器下模拟模式初始化耗时很久的问题。 - -### Added - -- (#639) 新增了文件系统参数:VIRTUAL_DOWNLOAD_MODE 和 VIRTUAL_DOWNLOAD_SPEED - - 编辑器下不需要构建AB,也可以模拟远端资源下载,等同真机运行环境。 - - ```csharp - class DefaultEditorFIleSystem - { - /// - /// 模拟虚拟下载模式 - /// - public bool VirtualDownloadMode { private set; get; } = false; - - /// - /// 模拟虚拟下载的网速(单位:字节) - /// - public int VirtualDownloadSpeed { private set; get; } = 1024; - } - ``` - -- (#640) 新增了文件系统参数:VIRTUAL_WEBGL_MODE - - 编辑器下不需要构建AB,也可以模拟小游戏开发环境,等同真机运行环境。 - - ```csharp - class DefaultEditorFIleSystem - { - /// - /// 模拟WebGL平台模式 - /// - public bool VirtualWebGLMode { private set; get; } = false; - } - ``` - -- (#642) 新增了文件系统参数:DOWNLOAD_WATCH_DOG_TIME - - 监控时间范围内,如果没有接收到任何下载数据,那么直接终止任务! - - ```csharp - class DefaultCacheFIleSystem - { - /// - /// 自定义参数:下载任务的看门狗机制监控时间 - /// - public int DownloadWatchDogTime { private set; get; } = int.MaxValue; - } - ``` - -### Changed - -- 下载器参数timeout移除。 - - 可以使用文件系统的看门狗机制代替。 - -- (#632) IFilterRule接口变动。 - - 收集器可以指定搜寻的资源类型,在收集目录资产量巨大的情况下,可以极大加快打包速度! - - ```csharp - public interface IFilterRule - { - /// - /// 搜寻的资源类型 - /// 说明:使用引擎方法搜索获取所有资源列表 - /// - string FindAssetType { get; } - } - ``` - - - -## [2.3.15] - 2025-09-09 - -**重要**:升级了资源清单版本,不兼容老版本。建议重新提审安装包。 - -### Improvements - -- 重构了UniTask扩展库的目录结构和说明文档。 -- 重构了内置文件系统类的加载和拷贝逻辑,解决在一些特殊机型上遇到的偶发性拷贝失败问题。 -- 增加了生成内置清单文件的窗口工具,详情见扩展工程里CreateBuildinCatalog目录。 -- 优化了异步操作系统的繁忙检测机制。 -- (#621) 资源配置页面可以展示DependCollector和StaticCollector包含的文件列表内容。 -- (#627) 优化了资源清单部分字段类型,CRC字段从字符串类型调整为整形,可以降低清单尺寸。 - -### Fixed - -- 修复了构建页面扩展类缺少指定属性报错的问题。 -- (#611) 修复了资源扫描器配置页面,修改备注信息后会丢失焦点的问题。 -- (#622) 修复了纯鸿蒙系统读取内置加密文件失败的问题。 -- (#620) 修复了LINUX系统URL地址转换失败的问题。 -- (#631) 修复了NET 4.x程序集库Math.Clamp导致的编译错误。 - -### Added - -- 新增了支持支付宝小游戏的文件系统扩展类。 - -- 新增了支持Taptap小游戏的文件系统扩展类。 - -- 新增了资源系统初始化参数:UseWeakReferenceHandle - - 目前处于预览版,可以在引擎设置页面开启宏:YOOASSET_EXPERIMENTAL - - ```csharp - /// - /// 启用弱引用资源句柄 - /// - public bool UseWeakReferenceHandle = false; - ``` - -- 内置文件系统和缓存文件系统新增初始化参数:FILE_VERIFY_MAX_CONCURRENCY - - ```csharp - /// - /// 自定义参数:初始化的时候缓存文件校验最大并发数 - /// - public int FileVerifyMaxConcurrency { private set; get; } - ``` - -- (#623) 内置构建管线新增构建参数:StripUnityVersion - - ```csharp - /// - /// 从文件头里剥离Unity版本信息 - /// - public bool StripUnityVersion = false; - ``` - -- 可编程构建管线新增构建参数:TrackSpriteAtlasDependencies - - ```csharp - /// - /// 自动建立资源对象对图集的依赖关系 - /// - public bool TrackSpriteAtlasDependencies = false; - ``` - -- (#617) 新增资源收集配置参数:SupportExtensionless - - 在不需要模糊加载模式的前提下,关闭此选项,可以降低运行时内存大小。 - - 该选项默认开启! - - ```csharp - public class CollectCommand - { - /// - /// 支持无后缀名的资源定位地址 - /// - public bool SupportExtensionless { set; get; } - } - ``` - -- (#625) 异步操作系统类新增监听方法。 - - ```csharp - class OperationSystem - { - /// - /// 监听任务开始 - /// - public static void RegisterStartCallback(Action callback); - - /// - /// 监听任务结束 - /// - public static void RegisterFinishCallback(Action callback); - } - ``` - - - -## [2.3.14] - 2025-07-23 - -**重要**:**所有下载相关的超时参数(timeout)已更新判定逻辑** - -超时不再以‘指定时间内未接收到任何数据’为判定条件,而是以‘指定时间内未完成整个下载任务’为判定条件。 - -### Improvements - -- 重构了核心代码的下载逻辑,解决了同步加载触发的下载任务没有完成的问题。 -- 扩展工程里新增了PreprocessBuildCatalog类,用于处理在构建应用程序前自动生成内置资源目录文件。 -- (#592) 优化了资源清单逻辑里不必要产生的GC逻辑。 - -### Fixed - -- (#590) 修复了TryUnloadUnusedAsset方法,在依赖嵌套层数过深导致没有卸载的问题。 - -### Added - -- 新增了支持Google Play的文件系统扩展示例。 - -- 新增了支持DefaultCacheFileSystem的单元测试用例。 - -- 新增了文件系统配置参数:DISABLE_ONDEMAND_DOWNLOAD - - ```csharp - public class FileSystemParametersDefine - { - // 禁用边玩边下机制 - public const string DISABLE_ONDEMAND_DOWNLOAD = "DISABLE_ONDEMAND_DOWNLO"; - } - ``` - -### Changed - -- IManifestServices接口拆分为了IManifestProcessServices和IManifestRestoreServices - - ```csharp - public interface IManifestProcessServices - { - /// - /// 处理资源清单(压缩或加密) - /// - byte[] ProcessManifest(byte[] fileData); - } - - public interface IManifestRestoreServices - { - /// - /// 还原资源清单(解压或解密) - /// - byte[] RestoreManifest(byte[] fileData); - } - ``` - -## [2.3.12] - 2025-07-01 - -### Improvements - -- 优化了同步接口导致的资源拷贝和资源验证性能开销高的现象。 -- 微信小游戏和抖音小游戏支持资源清单加密。 - -### Fixed - -- (#579) 修复了2.3.10版本资源包构建页面里CopyBuildinFileParam无法编辑问题。 -- (#572) 修复了资源收集页面指定收集的预制体名称变动的问题。 -- (#582) 修复了非递归收集依赖时,依赖列表中才包含主资源的问题。 - -### Added - -- 新增初始化参数:WebGLForceSyncLoadAsset - - ```csharp - public abstract class InitializeParameters - { - /// - /// WebGL平台强制同步加载资源对象 - /// Add commentMore actions - public bool WebGLForceSyncLoadAsset = false; - } - ``` - -- (#576) 新增了资源清单服务类:IManifestServices - - ```csharp - /// - /// 资源清单文件处理服务接口 - /// - public interface IManifestServices - { - /// - /// 处理资源清单(压缩和加密) - /// - byte[] ProcessManifest(byte[] fileData); - - /// - /// 还原资源清单(解压和解密) - /// - byte[] RestoreManifest(byte[] fileData); - } - ``` - -- (#585) 新增了本地文件拷贝服务类:ICopyLocalFileServices - - ```csharp - /// - /// 本地文件拷贝服务类 - /// - public interface ICopyLocalFileServices - { - void CopyFile(LocalFileInfo sourceFileInfo, string destFilePath); - } - ``` - -## [2.3.10] - 2025-06-17 - -### Improvements - -- 小游戏扩展库已经独立,可以单独导入到项目工程。 -- 编辑器里的TableView视图新增了AssetObjectCell类。 -- (#552) 微信小游戏文件系统类,增加了URL合法性的初始化检测机制。 -- (#566) 重构了资源构建页面,方便扩展自定义界面。 -- (#573) 完善了AssetDependencyDB的输出日志,可以正确输出丢失的引用资产信息。 - -### Fixed - -- 修复太空战机DEMO在退出运行模式时的报错。 -- (#551) 修复了Unity2019, Unity2020的代码兼容性报错。 -- (#569) 修复了TVOS平台的兼容问题。 -- (#564) 修复了TiktokFileSystem文件系统里appendTimeTicks无效的问题。 - -### Added - -- (#562) 新增了解密方法。 - - ```csharp - public interface IDecryptionServices - { - /// - /// 后备方式获取解密的资源包对象 - /// 注意:当正常解密方法失败后,会触发后备加载! - /// 说明:建议通过LoadFromMemory()方法加载资源对象作为保底机制。 - /// issues : https://github.com/tuyoogame/YooAsset/issues/562 - /// - DecryptResult LoadAssetBundleFallback(DecryptFileInfo fileInfo); - } - ``` - - - -## [2.3.9] - 2025-05-13 - -### Improvements - -- 增加了YOO_ASSET_EXPERIMENT宏,用于控制实验性代码的开关。 -- 构建管线目前会输出构建日志到输出目录下,方便查看引擎在构建时主动清空的控制台日志。 -- 优化了收集器tag传染扩散逻辑,避免Group里配置了Tag导致的无意义的警告信息。 -- 扩展工程内PanelMonitor代码默认关闭状态。 - -### Fixed - -- (#528) 修复了AssetDependencyDatabase在查询引擎资源对象是否存在的时效问题。 - -### Added - -- (#542) 新增了资源管理系统销毁方法。 - - 该方法会销毁所有的资源包裹和异步操作任务,以及卸载所有AssetBundle对象! - - ```csharp - public class YooAssets - { - /// - /// 销毁资源系统 - /// - public static void Destroy(); - } - ``` - -- 新增了SBP构建管线的构建参数 - - ```csharp - /// - /// 从AssetBundle文件头里剥离Unity版本信息 - /// - public bool StripUnityVersion = false; - ``` - -- 新增了构建错误码:BuiltinShadersBundleNameIsNull - -## [2.3.8] - 2025-04-17 - -### Improvements - -- 扩展工程里增加了“图集丢失变白块的解决方案”的相关代码。 - -### Fixed - -- (#528) 修复了微信小游戏平台WXFSClearUnusedBundleFiles无法清理的问题。 -- (#531) 修复了微信小游戏平台WXFSClearUnusedBundleFiles没有适配BundleName_HashName命名方式。 -- (#533) 修复了Editor程序集下无法访问YooAsset.Editor程序集里的internal字段的问题。 -- (#534) 修复了资源报告窗口AssetView视图里,依赖资源包列表显示不准确的问题。 - -## [2.3.7] - 2025-04-01 - -### Improvements - -- (#526) 运行时资源清单的哈希值验证兼容了MD5和CRC32两种方式。 -- (#515) 优化了资源路径大小写不敏感的逻辑代码,减少字符串操作产生的GC。 -- (#523) UnloadUnusedAssetsOperation方法支持了分帧处理。 - -### Fixed - -- (#520) 修复了UWP平台获取WWW加载路径未适配的问题。 - -### Added - -- 新增了文件系统初始化参数:INSTALL_CLEAR_MODE - - ```csharp - /// - /// 覆盖安装清理模式 - /// - public enum EOverwriteInstallClearMode - { - /// - /// 不做任何处理 - /// - None = 0, - - /// - /// 清理所有缓存文件(包含资源文件和清单文件) - /// - ClearAllCacheFiles = 1, - - /// - /// 清理所有缓存的资源文件 - /// - ClearAllBundleFiles = 2, - - /// - /// 清理所有缓存的清单文件 - /// - ClearAllManifestFiles = 3, - } - ``` - -- 新增了初始化参数:BundleLoadingMaxConcurrency - - ```csharp - public abstract class InitializeParameters - { - /// - /// 同时加载Bundle文件的最大并发数 - /// - public int BundleLoadingMaxConcurrency = int.MaxValue; - } - ``` - -## [2.3.6] - 2025-03-25 - -### Improvements - -- 构建管线新增了TaskCreateCatalog任务节点。 -- 内置文件系统的catalog文件现在存储在streammingAssets目录下。 - -### Fixed - -- (#486) 修复了微信小游戏文件系统调用ClearUnusedBundleFiles时候的异常。 - -## [2.3.5-preview] - 2025-03-14 - -### Fixed - -- (#502) 修复了原生缓存文件由于文件格式变动导致的加载本地缓存文件失败的问题。 -- (#504) 修复了MacOS平台Offline Play Mode模式请求本地资源清单失败的问题。 -- (#506) 修复了v2.3x版本LoadAllAssets方法计算依赖Bundle不完整的问题。 -- (#506) 修复了微信小游戏文件系统,在启用加密算法后卸载bundle报错的问题。 - -## [2.3.4-preview] - 2025-03-08 - -### Improvements - -- YooAsset支持了版本宏定义。 - - ```csharp - YOO_ASSET_2 - YOO_ASSET_2_3 - YOO_ASSET_2_3_OR_NEWER - ``` - -### Fixed - -- (#389) 修复了禁用域重载(Reload Domain)的情况下,再次启动游戏报错的问题。 -- (#496) 修复了文件系统参数RESUME_DOWNLOAD_MINMUM_SIZE传入int值会导致异常的错误。 -- (#498) 修复了v2.3版本尝试加载安卓包内的原生资源包失败的问题。 - -### Added - -- 新增了YooAssets.GetAllPackages()方法 - - ```csharp - /// - /// 获取所有资源包裹 - /// - public static List GetAllPackages() - ``` - -## [2.3.3-preview] - 2025-03-06 - -### Improvements - -- 新增了异步操作任务调试器,AssetBundleDebugger窗口-->OperationView视图模式 -- 编辑器下模拟构建默认启用依赖关系数据库,可以大幅降低编辑器下启动游戏的时间。 -- 单元测试用例增加加密解密测试用例。 - -### Fixed - -- (#492) 修复了发布的MAC平台应用,在启动的时候提示权限无法获取的问题。 - -## [2.3.2-preview] - 2025-02-27 - -### Fixed - -- (2.3.1) 修复小游戏平台下载器不生效的问题。 -- (#480) 修复了Unity工程打包导出时的报错。 - -### Added - -- 下载器新增参数:recursiveDownload - - ```csharp - /// - /// 创建资源下载器,用于下载指定的资源依赖的资源包文件 - /// - /// 下载资源对象所属资源包内所有资源对象依赖的资源包 - public ResourceDownloaderOperation CreateBundleDownloader() - ``` - -- 新增CustomPlayMode模式 - - ```csharp - /// - /// 自定义运行模式的初始化参数 - /// - public class CustomPlayModeParameters : InitializeParameters - { - /// - /// 文件系统初始化参数列表 - /// 注意:列表最后一个元素作为主文件系统! - /// - public List FileSystemParameterList; - } - ``` - -## [2.3.1-preview] - 2025-02-25 - -**资源加载依赖计算方式还原为了1.5x版本的模式,只加载资源对象实际依赖的资源包,不再以资源对象所在资源包的依赖关系为加载标准**。 - -### Improvements - -- 优化OperationSystem的更新机制,异步加载的耗时降低了50%。 -- 优化了Debugger窗口的显示页面,BundleView页面增加资源包的引用列表。 -- 优化了Reporter窗口的显示页面。 - -### Fixed - -- 修复了怀旧依赖模式下,TAG传染不正确的问题。 - -## [2.3.0-preview] - 2025-02-19 - -### Improvements - -资源收集窗口列表元素支持手动上下拖拽排序! - -资源扫描窗口列表元素支持手动上下拖拽排序! - -### Added - -- 新增了UIElements扩展类ReorderableListView - -- 新增初始化方法 - - ```csharp - public class YooAssets - { - /// - /// 设置异步系统参数,快速启动模式的开关 - /// 注意:该模式默认开启 - /// - public static void SetOperationSystemQuickStartMode(bool state) - } - ``` - -- 新增打包构建参数 - - ```csharp - public class BuildParameters - { - /// - /// 旧版依赖模式 - /// 说明:兼容YooAssets1.5.x版本 - /// - public bool LegacyDependency = false; - } - ``` - -### Fixed - -- (#472) 修复了Unity6平台,TableView视图无法显示问题。 -- 修复了微信小游戏和抖音小游戏未正确使用插件的卸载方法。 - -## [2.2.12] - 2025-02-14 - -### Improvements - -- WebGL网页平台支持文件加密。 -- 微信小游戏平台支持文件加密。 -- 抖音小游戏平台支持文件加密。 - -### Fixed - -- (#466) 修复了微信小游戏文件系统查询机制不生效! -- (#341) 修复了微信小游戏的下载进度异常问题。 -- (#471) 修复了Unity2019,Unity2020平台上,TableView视图无法显示的问题。 - -### Added - -- 新增了ResourcePackage.UnloadAllAssetsAsync(UnloadAllAssetsOptions options)方法 - - ```csharp - public sealed class UnloadAllAssetsOptions - { - /// - /// 释放所有资源句柄,防止卸载过程中触发完成回调! - /// - public bool ReleaseAllHandles = true; - - /// - /// 卸载过程中锁定加载操作,防止新的任务请求! - /// - public bool LockLoadOperation = true; - } - ``` - -## [2.2.11] - 2025-02-10 - -### Improvements - -- AssetArtScanner配置和生成报告的容错性检测。 - -### Fixed - -- (#465) 修复了特殊情况下,没有配置资源包文件后缀名构建失败的问题。 -- (#468) 修复了安卓平台二次启动加载原生文件或加密文件失败的问题。 - -## [2.2.10] - 2025-02-08 - -### Improvements - -- 新增了可扩展的AssetArtScanner资源扫描工具,详细请见官方说明文档。 -- 优化了AssetBundleReporter页面。 -- 优化了AssetBundleDebugger页面。 -- 优化了微信小游戏文件系统的缓存查询机制。 -- 优化了抖音小游戏文件系统的缓存查询机制。 - -### Fixed - -- (#447) 修复了Unity2019平台代码编译错误问题。 -- (#456) 修复了在Package未激活有效清单之前,无法销毁的问题。 -- (#452) 修复了内置文件系统类NeedPack方法总是返回TRUE的问题。 -- (#424) 适配了Unity6000版本替换了过时方法。 - -### Added - -- 新增了SBP构建管线构建参数:BuiltinShadersBundleName - -- 新增了SBP构建管线构建参数:MonoScriptsBundleName - -- 新增了全局构建管线构建参数:SingleReferencedPackAlone - - ```csharp - /// - /// 对单独引用的共享资源进行独立打包 - /// 说明:关闭该选项单独引用的共享资源将会构建到引用它的资源包内! - /// - public bool SingleReferencedPackAlone = true; - ``` - -- 新增了内置文件系统初始化参数:COPY_BUILDIN_PACKAGE_MANIFEST - - ```csharp - // 内置文件系统初始化的时候,自动拷贝内置清单到沙盒目录。 - var systemParameters = FileSystemParameters.CreateDefaultBuildinFileSystemParameters(); - systemParameters.AddParameter(FileSystemParametersDefine.COPY_BUILDIN_PACKAGE_MANIFEST, true); - ``` - -## [2.2.9] - 2025-01-14 - -### Fixed - -- (#438) 修复了纯血鸿蒙加载本地文件失败的问题。 -- (#445) 修复了小游戏扩展文件系统脚本编译错误。 - -### Changed - -- EditorSimulateModeHelper.SimulateBuild()方法变更 - - ```csharp - public static PackageInvokeBuildResult SimulateBuild(string packageName); - ``` - -## [2.2.8-preview] - 2025-01-03 - -新增了单元测试用例。 - -### Improvements - -- EditorSimulateModeHelper.SimulateBuild()方法提供指定自定义构建类 - - ```csharp - public class EditorSimulateBuildParam - { - /// - /// 模拟构建类所属程序集名称 - /// - public string InvokeAssmeblyName = "YooAsset.Editor"; - - /// - /// 模拟构建执行的类名全称 - /// 注意:类名必须包含命名空间! - /// - public string InvokeClassFullName = "YooAsset.Editor.AssetBundleSimulateBuilder"; - - /// - /// 模拟构建执行的方法名称 - /// 注意:执行方法必须满足 BindingFlags.Public | BindingFlags.Static - /// - public string InvokeMethodName = "SimulateBuild"; - } - ``` - -- 文件清理方式新增清理缓存清单。 - - ```csharp - /// - /// 文件清理方式 - /// - public enum EFileClearMode - { - /// - /// 清理所有清单 - /// - ClearAllManifestFiles, - - /// - /// 清理未在使用的清单 - /// - ClearUnusedManifestFiles, - } - ``` - -### Fixed - -- (#426) 修复了鸿蒙next平台加载内置文件路径报错的问题。 -- (#428) 修复了鸿蒙next平台加载内置文件路径报错的问题。 -- (#434) 修复了2.2版本 catalog文件对Json格式原生文件不记录的问题。 -- (#435) 修复了WebGL平台调用MD5算法触发异常的问题。 - -### Added - -- 新增了视频打包规则。 - - ```csharp - /// - /// 打包视频文件 - /// - [DisplayName("打包视频文件")] - public class PackVideoFile : IPackRule - ``` - -### Changed - -- 重命名FileSystemParameters.RootDirectory字段为PackageRoot -- 重命名ResourcePackage.ClearCacheBundleFilesAsync()方法为ClearCacheFilesAsync() - -## [2.2.7-preview] - 2024-12-30 - -### Improvements - -- 重构了下载器的委托方法。 - -- YooAssetSettings配置文件新增Package Manifest Prefix参数。 - - ```csharp - /// - /// 资源清单前缀名称(默认为空) - /// - public string PackageManifestPrefix = string.Empty; - ``` - -### Fixed - -- (#422) 修复了同步加载场景的NotImplementedException异常报错。 -- (#418) 修复了web远程文件系统初始化不正确的问题 -- (#392) 修复了引擎版本代码兼容相关的警告。 -- (#332) 修复了当用户的设备中有特殊字符时,URL路径无法被正确识别的问题。 - -### Added - -- 新增代码字段:AsyncOperationBase.PackageName - -### Changed - -- 重命名DownloaderOperation.OnDownloadOver()方法为DownloaderFinish() -- 重命名DownloaderOperation.OnDownloadProgress()方法为DownloadUpdate() -- 重命名DownloaderOperation.OnDownloadError()方法为DownloadError() -- 重命名DownloaderOperation.OnStartDownloadFile()方法为DownloadFileBegin() - -## [2.2.6-preview] - 2024-12-27 - -### Improvements - -- 增强了对Steam平台DLC拓展包的支持。 - - ```csharp - // 新增参数关闭Catalog目录查询内置文件的功能 - var fileSystemParams = CreateDefaultBuildinFileSystemParameters(); - fileSystemParams .AddParameter(FileSystemParametersDefine.DISABLE_CATALOG_FILE, true); - ``` - -- 资源句柄基类提供了统一的Release方法。 - - ```csharp - public abstract class HandleBase : IEnumerator, IDisposable - { - /// - /// 释放资源句柄 - /// - public void Release(); - - /// - /// 释放资源句柄 - /// - public void Dispose(); - } - ``` - -- 优化了场景卸载逻辑。 - - ```csharp - //框架内不在区分主场景和附加场景。 - //场景卸载后自动释放资源句柄。 - ``` - -### Fixed - -- 修复了Unity2020版本提示的脚本编译错误。 -- (#417) 修复了DefaultWebServerFileSystem文件系统内Catalog未起效的问题。 - -### Added - -- 新增示例文件 GetCacheBundleSizeOperation.cs - - 可以获取指定Package的缓存资源总大小。 - -### Removed - -- 移除了SceneHandle.IsMainScene()方法。 - -## [2.2.5-preview] - 2024-12-25 - -依赖的ScriptableBuildPipeline (SBP) 插件库版本切换为1.21.25版本! - -重构了ResourceManager相关的核心代码,方便借助文件系统扩展和支持更复杂的需求! - -### Editor - -- 新增了编辑器模拟构建管线 EditorSimulateBuildPipeline -- 移除了EBuildMode枚举类型,构建界面有变动。 -- IActiveRule分组激活接口新增GroupData类。 - -### Improvements - -- 增加抖音小游戏文件系统,见扩展示例代码。 - -- 微信小游戏文件系统支持删除无用缓存文件和全部缓存文件。 - -- 资源构建管线现在默认剔除了Gizmos和编辑器资源。 - -- 优化了资源构建管线里资源收集速度。 - - 资源收集速度提升100倍! - - ```csharp - class BuildParameters - { - /// - /// 使用资源依赖缓存数据库 - /// 说明:开启此项可以极大提高资源收集速度 - /// - public bool UseAssetDependencyDB = false; - } - ``` - -- WebPlayMode支持跨域加载。 - - ```csharp - // 创建默认的WebServer文件系统参数 - public static FileSystemParameters CreateDefaultWebServerFileSystemParameters(bool disableUnityWebCache = false) - - // 创建默认的WebRemote文件系统参数(支持跨域加载) - public static FileSystemParameters CreateDefaultWebRemoteFileSystemParameters(IRemoteServices remoteServices, bool disableUnityWebCache = false) - ``` - -- 编辑器模拟文件系统新增初始化参数:支持异步模拟加载帧数。 - - ```csharp - /// - /// 异步模拟加载最小帧数 - /// - FileSystemParametersDefine.ASYNC_SIMULATE_MIN_FRAME - - /// - /// 异步模拟加载最大帧数 - /// - FileSystemParametersDefine.ASYNC_SIMULATE_MAX_FRAME - ``` - -- 缓存文件系统新增初始化参数:支持设置下载器最大并发连接数和单帧最大请求数 - - ```csharp - var fileSystremParams = FileSystemParameters.CreateDefaultCacheFileSystemParameters(); - fileSystremParams .AddParameter(FileSystemParametersDefine.DOWNLOAD_MAX_CONCURRENCY, 99); - fileSystremParams .AddParameter(FileSystemParametersDefine.DOWNLOAD_MAX_REQUEST_PER_FRAME, 10); - ``` - -### Fixed - -- (#349) 修复了在加载清单的时候,即使本地存在缓存文件还会去远端下载。 -- (#361) 修复了协程里等待的asset handle被release,会无限等待并输出警告信息。 -- (#359) 修复了SubAssetsHandle.GetSubAssetObject会获取到同名的主资源。 -- (#387) 修复了加密后文件哈希冲突的时候没有抛出异常错误。 -- (#404) 修复了Unity2022.3.8版本提示编译错误:Cannot resolve symbol 'AsyncInstantiateOperation' - -### Added - -- 新增示例文件 CopyBuildinManifestOperation.cs - -- 新增示例文件 LoadGameObjectOperation.cs - -- 新增了获取配置清单详情的方法 - - ```csharp - class ResourcePackage - { - public PackageDetails GetPackageDetails() - } - ``` - -- 新增了获取所有资源信息的方法 - - ```csharp - class ResourcePackage - { - public AssetInfo[] GetAllAssetInfos() - } - ``` - -- 新增了清理缓存文件的通用方法 - - ```csharp - /// - /// 文件清理方式 - /// - public enum EFileClearMode - { - /// - /// 清理所有文件 - /// - ClearAllBundleFiles = 1, - /// - /// 清理未在使用的文件 - /// - ClearUnusedBundleFiles = 2, - /// - /// 清理指定标签的文件 - /// 说明:需要指定参数,可选:string, string[], List - /// - ClearBundleFilesByTags = 3, - } - class ResourcePackage - { - /// - /// 清理缓存文件 - /// - /// 清理方式 - /// 执行参数 - public ClearCacheBundleFilesOperation ClearCacheBundleFilesAsync(EFileClearMode clearMode, object clearParam = null) - } - ``` - -### Changed - -- 修改了EditorSimulateModeHelper.SimulateBuild()方法 - -- 重命名ResourcePackage.GetAssetsInfoByTags()方法为GetAssetInfosByTags() - -- 实例化对象方法增加激活参数。 - - ```csharp - public InstantiateOperation InstantiateAsync(bool actived = true) - ``` - -- 清单文件的版本提升到2.2.5版本 - - ```csharp - /// - /// 资源包裹的备注信息 - /// - public string PackageNote; - ``` - - -### Removed - -- 移除了HostPlayModeParameters.DeliveryFileSystemParameters字段 -- 移除了ResourcePackage.ClearAllBundleFilesAsync()方法 -- 移除了ResourcePackage.ClearUnusedBundleFilesAsync()方法 -- 移除了FileSystemParameters.CreateDefaultBuildinRawFileSystemParameters()方法 -- 移除了FileSystemParameters.CreateDefaultCacheRawFileSystemParameters()方法 -- 移除了枚举类型:EDefaultBuildPipeline -- 移除了配置参数:YooAssetSettings.ManifestFileName - -## [2.2.4-preview] - 2024-08-15 - -### Fixed - -- 修复了HostPlayMode初始化卡死的问题。 - -## [2.2.3-preview] - 2024-08-13 - -### Fixed - -- (#311) 修复了断点续传下载器极小概率报错 : “416 Range Not Satisfiable” - -### Improvements - -- 原生文件构建管线支持原生文件加密。 - -- HostPlayMode模式下内置文件系统初始化参数可以为空。 - -- 场景加载增加了LocalPhysicsMode参数来控制物理运行模式。 - -- 默认的内置文件系统和缓存文件系统增加解密方法。 - - ```csharp - /// - /// 创建默认的内置文件系统参数 - /// - /// 加密文件解密服务类 - /// 缓存文件的校验等级 - /// 内置文件的根路径 - public static FileSystemParameters CreateDefaultBuildinFileSystemParameters(IDecryptionServices decryptionServices, EFileVerifyLevel verifyLevel, string rootDirectory); - - /// - /// 创建默认的缓存文件系统参数 - /// - /// 远端资源地址查询服务类 - /// 加密文件解密服务类 - /// 缓存文件的校验等级 - /// 文件系统的根目录 - public static FileSystemParameters CreateDefaultCacheFileSystemParameters(IRemoteServices remoteServices, IDecryptionServices decryptionServices, EFileVerifyLevel verifyLevel, string rootDirectory); - ``` - -## [2.2.2-preview] - 2024-07-31 - -### Fixed - -- (#321) 修复了在Unity2022里编辑器下离线模式运行失败的问题。 -- (#325) 修复了在Unity2019里编译报错问题。 - -## [2.2.1-preview] - 2024-07-10 - -统一了所有PlayMode的初始化逻辑,EditorSimulateMode和OfflinePlayMode初始化不再主动加载资源清单! - -### Added - -- 新增了IFileSystem.ReadFileData方法,支持原生文件自定义获取文本和二进制数据。 - -### Improvements - -- 优化了DefaultWebFileSystem和DefaultBuildFileSystem文件系统的内部初始化逻辑。 - -## [2.2.0-preview] - 2024-07-07 - -重构了运行时代码,新增了文件系统接口(IFileSystem)方便开发者扩展特殊需求。 - -新增微信小游戏文件系统示例代码,详细见Extension Sample/Runtime/WechatFileSystem - -### Added - -- 新增了ResourcePackage.DestroyAsync方法 - -- 新增了FileSystemParameters类帮助初始化文件系统 - - 内置了编辑器文件系统参数,内置文件系统参数,缓存文件系统参数,Web文件系统参数。 - - ```csharp - public class FileSystemParameters - { - /// - /// 文件系统类 - /// - public string FileSystemClass { private set; get; } - - /// - /// 文件系统的根目录 - /// - public string RootDirectory { private set; get; } - - /// - /// 添加自定义参数 - /// - public void AddParameter(string name, object value) - } - ``` - -### Changed - -- 重构了InitializeParameters初始化参数 -- 重命名YooAssets.DestroyPackage方法为RemovePackage -- 重命名ResourcePackage.UpdatePackageVersionAsync方法为RequestPackageVersionAsync -- 重命名ResourcePackage.UnloadUnusedAssets方法为UnloadUnusedAssetsAsync -- 重命名ResourcePackage.ForceUnloadAllAssets方法为UnloadAllAssetsAsync -- 重命名ResourcePackage.ClearUnusedCacheFilesAsync方法为ClearUnusedBundleFilesAsync -- 重命名ResourcePackage.ClearAllCacheFilesAsync方法为ClearAllBundleFilesAsync - -### Removed - -- 移除了YooAssets.Destroy方法 -- 移除了YooAssets.SetDownloadSystemClearFileResponseCode方法 -- 移除了YooAssets.SetCacheSystemDisableCacheOnWebGL方法 -- 移除了ResourcePackage.GetPackageBuildinRootDirectory方法 -- 移除了ResourcePackage.GetPackageSandboxRootDirectory方法 -- 移除了ResourcePackage.ClearPackageSandbox方法 -- 移除了IBuildinQueryServices接口 -- 移除了IDeliveryLoadServices接口 -- 移除了IDeliveryQueryServices接口 - - -## [2.1.2] - 2024-05-16 - -SBP库依赖版本升级至2.1.3 - -### Fixed - -- (#236) 修复了资源配置界面AutoCollectShader复选框没有刷新的问题。 -- (#244) 修复了导入器在安卓平台导入本地下载的资源失败的问题。 -- (#268) 修复了挂起场景未解除状态前无法卸载的问题。 -- (#269) 优化场景挂起流程,支持中途取消挂起操作。 -- (#276) 修复了HostPlayMode模式下,如果内置清单是最新版本,每次运行都会触发拷贝行为。 -- (#289) 修复了Unity2019版本脚本IWebRequester编译报错。 -- (#295) 解决了在安卓移动平台,华为和三星真机上有极小概率加载资源包失败 : Unable to open archive file - -### Added - -- 新增GetAllCacheFileInfosOperation()获取缓存文件信息的方法。 - -- 新增LoadSceneSync()同步加载场景的方法。 - -- 新增IIgnoreRule接口,资源收集流程可以自定义。 - -- 新增IWechatQueryServices接口,用于微信平台本地文件查询。 - - 后续将会通过虚拟文件系统来支持! - -### Changed - -- 调整了UnloadSceneOperation代码里场景的卸载顺序。 - -### Improvements - -- 优化了资源清单的解析过程。 -- 移除资源包名里的空格字符。 -- 支持华为鸿蒙系统。 - -## [2.1.1] - 2024-01-17 - -### Fixed - -- (#224) 修复了编辑器模式打包时 SimulateBuild 报错的问题。 -- (#223) 修复了资源构建界面读取配置导致的报错问题。 - -### Added - -- 支持共享资源打包规则,可以定制化独立的构建规则。 - - ```c# - public class BuildParameters - { - /// - /// 是否启用共享资源打包 - /// - public bool EnableSharePackRule = false; - } - ``` - -- 微信小游戏平台,资源下载器支持底层缓存查询。 - -## [2.1.0] - 2023-12-27 - -升级了 Scriptable build pipeline (SBP) 的版本,来解决图集引用的精灵图片冗余问题。 - -### Fixed - -- (#195) 修复了在EditorPlayMode模式下,AssetHandle.GetDownloadStatus()发生异常的问题。 -- (#201) 修复了断点续传失效的问题。 -- (#202) 修复了打包参数FileNameStyle设置为BundleName后,IQueryServices会一直返回true的问题。 -- (#205) 修复了HybridCLR插件里创建资源下载器触发的异常。 -- (#210) 修复了DownloaderOperation在未开始下载前,内部的PackageName为空的问题。 -- (#220) 修复了资源收集界面关闭后,撤回操作还会生效的问题。 -- 修复了下载器合并后重新计算下载字节数不正确的问题。 - -### Improvements - -- (#198) 资源收集界面禁用的分组不再检测合法性。 -- (#203) 资源构建类容许自定义打包的输出目录。 -- 资源构建报告增加未依赖的资源信息列表。 - -### Changed - -- IBuildinQueryServices和IDeliveryQueryServices查询方法变更。 - - ```c# - public interface IBuildinQueryServices - { - /// - /// 查询是否为应用程序内置的资源文件 - /// - /// 包裹名称 - /// 文件名称(包含文件的后缀格式) - /// 文件哈希值 - /// 返回查询结果 - bool Query(string packageName, string fileName, string fileCRC); - } - - public interface IDeliveryQueryServices - { - /// - /// 查询是否为开发者分发的资源文件 - /// - /// 包裹名称 - /// 文件名称(包含文件的后缀格式) - /// 文件哈希值 - /// 返回查询结果 - bool Query(string packageName, string fileName, string fileCRC); - } - ``` - - - -### Removed - -- (#212) 移除了构建报告里的资源冗余信息列表。 +## [3.0.0] - 2026-05-01 +beta released. diff --git a/Assets/YooAsset/Editor/Assembly/AssemblyInfo.cs b/Assets/YooAsset/Editor/Assembly/AssemblyInfo.cs index 16b85520..a9ca6dd2 100644 --- a/Assets/YooAsset/Editor/Assembly/AssemblyInfo.cs +++ b/Assets/YooAsset/Editor/Assembly/AssemblyInfo.cs @@ -1,5 +1,5 @@ using System.Runtime.CompilerServices; // 外部友元 -[assembly: InternalsVisibleTo("YooAsset.EditorExtension")] +[assembly: InternalsVisibleTo("YooAsset.Extension.Editor")] [assembly: InternalsVisibleTo("Assembly-CSharp-Editor")] \ No newline at end of file diff --git a/Assets/YooAsset/Editor/BundleBuilder/BuildPipeline/BaseTasks/TaskCopyBundledFiles.cs b/Assets/YooAsset/Editor/BundleBuilder/BuildPipeline/BaseTasks/TaskCopyBundledFiles.cs index c97495e6..c93e1e55 100644 --- a/Assets/YooAsset/Editor/BundleBuilder/BuildPipeline/BaseTasks/TaskCopyBundledFiles.cs +++ b/Assets/YooAsset/Editor/BundleBuilder/BuildPipeline/BaseTasks/TaskCopyBundledFiles.cs @@ -36,7 +36,8 @@ namespace YooAsset.Editor // 清空首包资源目录 if (copyOption == EBundledCopyOption.ClearAndCopyAll || copyOption == EBundledCopyOption.ClearAndCopyByTags) { - EditorFileUtility.ClearFolder(bundledRootDirectory); + EditorFileUtility.DeleteDirectory(bundledRootDirectory); + EditorFileUtility.CreateDirectory(bundledRootDirectory); } // 拷贝补丁清单文件 diff --git a/Assets/YooAsset/Editor/Common/EditorAssetInfo.cs b/Assets/YooAsset/Editor/Common/EditorAssetInfo.cs index ecd0637a..eb413074 100644 --- a/Assets/YooAsset/Editor/Common/EditorAssetInfo.cs +++ b/Assets/YooAsset/Editor/Common/EditorAssetInfo.cs @@ -7,6 +7,7 @@ namespace YooAsset.Editor [Serializable] public class EditorAssetInfo : IComparable { + [NonSerialized] private string _fileExtension = null; /// diff --git a/Assets/YooAsset/Editor/Utilities/EditorFileUtility.cs b/Assets/YooAsset/Editor/Utilities/EditorFileUtility.cs index 8b297780..db777aa6 100644 --- a/Assets/YooAsset/Editor/Utilities/EditorFileUtility.cs +++ b/Assets/YooAsset/Editor/Utilities/EditorFileUtility.cs @@ -118,28 +118,6 @@ namespace YooAsset.Editor File.Copy(sourcePath, destPath, overwrite); } - /// - /// 清空文件夹 - /// - /// 要清理的文件夹路径 - public static void ClearFolder(string directoryPath) - { - if (Directory.Exists(directoryPath) == false) - return; - - string[] allFiles = Directory.GetFiles(directoryPath); - for (int i = 0; i < allFiles.Length; i++) - { - File.Delete(allFiles[i]); - } - - string[] allFolders = Directory.GetDirectories(directoryPath); - for (int i = 0; i < allFolders.Length; i++) - { - Directory.Delete(allFolders[i], true); - } - } - /// /// 获取文件字节大小 /// diff --git a/Assets/YooAsset/LICENSE.md b/Assets/YooAsset/LICENSE.md index 075661d2..5db28162 100644 --- a/Assets/YooAsset/LICENSE.md +++ b/Assets/YooAsset/LICENSE.md @@ -187,7 +187,7 @@ identification within third-party archives. Copyright 2018-2021 何冠峰 - Copyright 2021-2025 TuYoo Games + Copyright 2021-2026 TuYoo Games Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/Assets/YooAsset/Runtime/Assembly/AssemblyInfo.cs b/Assets/YooAsset/Runtime/Assembly/AssemblyInfo.cs index eec2c904..9cc6b5a3 100644 --- a/Assets/YooAsset/Runtime/Assembly/AssemblyInfo.cs +++ b/Assets/YooAsset/Runtime/Assembly/AssemblyInfo.cs @@ -1,12 +1,12 @@ -using System.Runtime.CompilerServices; +using System.Runtime.CompilerServices; // 内部友元 [assembly: InternalsVisibleTo("YooAsset.Editor")] -[assembly: InternalsVisibleTo("YooAsset.Test")] -[assembly: InternalsVisibleTo("YooAsset.Test.Editor")] +[assembly: InternalsVisibleTo("YooAsset.Tests")] +[assembly: InternalsVisibleTo("YooAsset.Tests.Editor")] // 外部友元 [assembly: InternalsVisibleTo("YooAsset.MiniGame")] -[assembly: InternalsVisibleTo("YooAsset.RuntimeExtension")] -[assembly: InternalsVisibleTo("YooAsset.EditorExtension")] +[assembly: InternalsVisibleTo("YooAsset.Extension")] +[assembly: InternalsVisibleTo("YooAsset.Extension.Editor")] [assembly: InternalsVisibleTo("Assembly-CSharp-Editor")] \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/AsyncOperation/AsyncOperationBase.cs b/Assets/YooAsset/Runtime/AsyncOperation/AsyncOperationBase.cs index 22e1fe1c..14fad5b6 100644 --- a/Assets/YooAsset/Runtime/AsyncOperation/AsyncOperationBase.cs +++ b/Assets/YooAsset/Runtime/AsyncOperation/AsyncOperationBase.cs @@ -8,7 +8,7 @@ namespace YooAsset /// /// 异步操作基类 /// - public abstract class AsyncOperationBase : IEnumerator, IComparable + public abstract partial class AsyncOperationBase : IEnumerator, IComparable { private List _children; private Action _completedCallback; diff --git a/Assets/YooAsset/Runtime/AsyncOperation/EOperationStatus.cs b/Assets/YooAsset/Runtime/AsyncOperation/EOperationStatus.cs index 103f4a81..ef9ef0d9 100644 --- a/Assets/YooAsset/Runtime/AsyncOperation/EOperationStatus.cs +++ b/Assets/YooAsset/Runtime/AsyncOperation/EOperationStatus.cs @@ -25,5 +25,13 @@ namespace YooAsset /// 已失败 /// Failed, + +#if YOOASSET_LEGACY_API + /// + /// v2.3 兼容别名 + /// + [System.Obsolete("Use Succeeded instead.")] + Succeed = Succeeded, +#endif } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/BundleCache/Policies/EvictionByLocationsPolicy.cs b/Assets/YooAsset/Runtime/BundleCache/Policies/EvictionByLocationsPolicy.cs index 109b8036..c6fd4a58 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Policies/EvictionByLocationsPolicy.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Policies/EvictionByLocationsPolicy.cs @@ -6,7 +6,7 @@ namespace YooAsset /// 按资源地址清理缓存文件 /// /// - /// ClearParameter 类型:string / string[] / List + /// ClearParameter 类型:string / array / list /// internal class EvictionByLocationsPolicy : ICacheEvictionPolicy { diff --git a/Assets/YooAsset/Runtime/BundleCache/Policies/EvictionByTagsPolicy.cs b/Assets/YooAsset/Runtime/BundleCache/Policies/EvictionByTagsPolicy.cs index 6a2b6ead..3001fbde 100644 --- a/Assets/YooAsset/Runtime/BundleCache/Policies/EvictionByTagsPolicy.cs +++ b/Assets/YooAsset/Runtime/BundleCache/Policies/EvictionByTagsPolicy.cs @@ -6,7 +6,7 @@ namespace YooAsset /// 按标签清理缓存文件 /// /// - /// ClearParameter 类型:string / string[] / List + /// ClearParameter 类型:string / array / list /// internal class EvictionByTagsPolicy : ICacheEvictionPolicy { diff --git a/Assets/YooAsset/Samples~/Mini Game/Scenes.meta b/Assets/YooAsset/Runtime/Compatibility.meta similarity index 77% rename from Assets/YooAsset/Samples~/Mini Game/Scenes.meta rename to Assets/YooAsset/Runtime/Compatibility.meta index dbabebe6..6629621e 100644 --- a/Assets/YooAsset/Samples~/Mini Game/Scenes.meta +++ b/Assets/YooAsset/Runtime/Compatibility.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 0f79d08cddb5196408cff10f6750ae69 +guid: da061aaa46527ed44a052b269aeeaeb0 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Assets/YooAsset/Runtime/Compatibility/CompatibleDownloader.cs b/Assets/YooAsset/Runtime/Compatibility/CompatibleDownloader.cs new file mode 100644 index 00000000..7321b557 --- /dev/null +++ b/Assets/YooAsset/Runtime/Compatibility/CompatibleDownloader.cs @@ -0,0 +1,191 @@ +#if YOOASSET_LEGACY_API +// YooAsset v2.3 兼容层 - DownloaderOperation 兼容 +// 通过 partial class 为 DownloaderOperation 补充 v2.3 的旧式回调属性和 BeginDownload 方法。 + +using System; + +namespace YooAsset +{ + #region v2.3 委托和数据类型 + /// + /// v2.3 下载器结束回调委托 + /// + [Obsolete("Use DownloadCompleted event instead.")] + public delegate void DownloaderFinish(DownloaderFinishData data); + + /// + /// v2.3 下载进度更新回调委托 + /// + [Obsolete("Use DownloadProgressChanged event instead.")] + public delegate void DownloadUpdateDelegate(DownloadUpdateData data); + + /// + /// v2.3 下载错误回调委托(重命名以避免与 v3 event DownloadError 冲突) + /// + [Obsolete("Use DownloadError event instead.")] + public delegate void DownloadErrorDelegate(DownloadErrorData data); + + /// + /// v2.3 开始下载文件回调委托 + /// + [Obsolete("Use DownloadFileStarted event instead.")] + public delegate void DownloadFileBeginDelegate(DownloadFileData data); + + /// + /// v2.3 下载器结束数据 + /// + [Obsolete("Use DownloadCompletedEventArgs instead.")] + public struct DownloaderFinishData + { + public string PackageName; + public bool Succeed; + } + + /// + /// v2.3 下载进度更新数据 + /// + [Obsolete("Use DownloadProgressChangedEventArgs instead.")] + public struct DownloadUpdateData + { + public string PackageName; + public float Progress; + public int TotalDownloadCount; + public int CurrentDownloadCount; + public long TotalDownloadBytes; + public long CurrentDownloadBytes; + } + + /// + /// v2.3 下载错误数据 + /// + [Obsolete("Use DownloadErrorEventArgs instead.")] + public struct DownloadErrorData + { + public string PackageName; + public string FileName; + public string ErrorInfo; + } + + /// + /// v2.3 下载文件数据 + /// + [Obsolete("Use DownloadFileStartedEventArgs instead.")] + public struct DownloadFileData + { + public string PackageName; + public string FileName; + public long FileSize; + } + #endregion + + public abstract partial class DownloaderOperation + { + private DownloaderFinish _downloadFinishCallback; + private DownloadUpdateDelegate _downloadUpdateCallback; + private DownloadErrorDelegate _downloadErrorCallback; + private DownloadFileBeginDelegate _downloadFileBeginCallback; + + private bool _finishBridged; + private bool _updateBridged; + private bool _errorBridged; + private bool _fileBeginBridged; + + [Obsolete("Use DownloadCompleted event instead.")] + public DownloaderFinish DownloadFinishCallback + { + get => _downloadFinishCallback; + set + { + _downloadFinishCallback = value; + if (!_finishBridged && value != null) + { + _finishBridged = true; + DownloadCompleted += args => + { + _downloadFinishCallback?.Invoke(new DownloaderFinishData + { + PackageName = args.PackageName, + Succeed = args.Succeeded + }); + }; + } + } + } + + [Obsolete("Use DownloadProgressChanged event instead.")] + public DownloadUpdateDelegate DownloadUpdateCallback + { + get => _downloadUpdateCallback; + set + { + _downloadUpdateCallback = value; + if (!_updateBridged && value != null) + { + _updateBridged = true; + DownloadProgressChanged += args => + { + _downloadUpdateCallback?.Invoke(new DownloadUpdateData + { + PackageName = args.PackageName, + Progress = args.Progress, + TotalDownloadCount = args.TotalDownloadCount, + CurrentDownloadCount = args.CurrentDownloadCount, + TotalDownloadBytes = args.TotalDownloadBytes, + CurrentDownloadBytes = args.CurrentDownloadBytes + }); + }; + } + } + } + + [Obsolete("Use DownloadError event instead.")] + public DownloadErrorDelegate DownloadErrorCallback + { + get => _downloadErrorCallback; + set + { + _downloadErrorCallback = value; + if (!_errorBridged && value != null) + { + _errorBridged = true; + DownloadError += args => + { + _downloadErrorCallback?.Invoke(new DownloadErrorData + { + PackageName = args.PackageName, + FileName = args.FileName, + ErrorInfo = args.ErrorInfo + }); + }; + } + } + } + + [Obsolete("Use DownloadFileStarted event instead.")] + public DownloadFileBeginDelegate DownloadFileBeginCallback + { + get => _downloadFileBeginCallback; + set + { + _downloadFileBeginCallback = value; + if (!_fileBeginBridged && value != null) + { + _fileBeginBridged = true; + DownloadFileStarted += args => + { + _downloadFileBeginCallback?.Invoke(new DownloadFileData + { + PackageName = args.PackageName, + FileName = args.FileName, + FileSize = args.FileSize + }); + }; + } + } + } + + [Obsolete("Use StartDownload() instead.")] + public void BeginDownload() => StartDownload(); + } +} +#endif diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/Test/TiktokFileSystemTest.cs.meta b/Assets/YooAsset/Runtime/Compatibility/CompatibleDownloader.cs.meta similarity index 83% rename from Assets/YooAsset/Samples~/Mini Game/Runtime/Test/TiktokFileSystemTest.cs.meta rename to Assets/YooAsset/Runtime/Compatibility/CompatibleDownloader.cs.meta index f20dba27..fc93ff38 100644 --- a/Assets/YooAsset/Samples~/Mini Game/Runtime/Test/TiktokFileSystemTest.cs.meta +++ b/Assets/YooAsset/Runtime/Compatibility/CompatibleDownloader.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: ec9d17e765ccd4642aa3aa9ca0580799 +guid: 5c410769c5f99174897f030039b64116 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/YooAsset/Runtime/Compatibility/CompatibleFileSystem.cs b/Assets/YooAsset/Runtime/Compatibility/CompatibleFileSystem.cs new file mode 100644 index 00000000..47a400d6 --- /dev/null +++ b/Assets/YooAsset/Runtime/Compatibility/CompatibleFileSystem.cs @@ -0,0 +1,293 @@ +#if YOOASSET_LEGACY_API +// YooAsset v2.3 兼容层 - 文件系统参数兼容 +// 通过 partial class 为 FileSystemParameters 补充 v2.3 旧工厂方法, +// 并恢复 FileSystemParametersDefine、IRemoteServices、IManifestRestoreServices 等旧类型。 + +using System; +using System.Collections.Generic; +using System.IO; +using UnityEngine; + +namespace YooAsset +{ + #region FileSystemParameters partial + + public partial class FileSystemParameters + { + /// + /// v2.3 属性名,转发到 v3 的 FileSystemTypeName + /// + [Obsolete("Use FileSystemTypeName instead.")] + public string FileSystemClass + { + get { return FileSystemTypeName; } + } + + /// + /// 兼容 v2.3 REMOTE_SERVICES 参数对象 + /// + [Obsolete("Use AddParameter(EFileSystemParameter.RemoteService, IRemoteService) instead.")] + public void AddParameter(string paramName, IRemoteServices value) + { + if (paramName == FileSystemParametersDefine.REMOTE_SERVICES && value != null) + AddParameter(paramName, new RemoteServicesAdapter(value)); + else + AddParameter(paramName, (object)value); + } + + /// + /// 兼容 v2.3 MANIFEST_SERVICES 参数对象 + /// + [Obsolete("Use AddParameter(EFileSystemParameter.ManifestDecryptor, IManifestDecryptor) instead.")] + public void AddParameter(string paramName, IManifestRestoreServices value) + { + if (paramName == FileSystemParametersDefine.MANIFEST_SERVICES && value != null) + AddParameter(paramName, new ManifestRestoreServicesAdapter(value)); + else + AddParameter(paramName, (object)value); + } + + /// + /// 兼容 v2.3 INSTALL_CLEAR_MODE 枚举值 + /// + [Obsolete("Use AddParameter(EFileSystemParameter.InstallCleanupMode, EInstallCleanupMode) instead.")] + public void AddParameter(string paramName, EOverwriteInstallClearMode value) + { + if (paramName == FileSystemParametersDefine.INSTALL_CLEAR_MODE) + AddParameter(paramName, (EInstallCleanupMode)(int)value); + else + AddParameter(paramName, (object)value); + } + + /// + /// v2.3 旧拼写入口,转发到 CreateDefaultBuiltinFileSystemParameters + /// + [Obsolete("Use CreateDefaultBuiltinFileSystemParameters instead. IDecryptionServices is no longer supported; pass null or migrate to IBundleDecryptor.")] + public static FileSystemParameters CreateDefaultBuildinFileSystemParameters(IDecryptionServices decryptionServices = null, string packageRoot = null) + { + return CreateDefaultBuiltinFileSystemParameters(packageRoot); + } + + /// + /// v2.3 缓存文件系统入口,转发到 CreateDefaultSandboxFileSystemParameters + /// + [Obsolete("Use CreateDefaultSandboxFileSystemParameters instead. IDecryptionServices is no longer supported; pass null or migrate to IBundleDecryptor.")] + public static FileSystemParameters CreateDefaultCacheFileSystemParameters(IRemoteServices remoteServices, IDecryptionServices decryptionServices = null, string packageRoot = null) + { + var adapter = remoteServices != null ? new RemoteServicesAdapter(remoteServices) : null; + return CreateDefaultSandboxFileSystemParameters(adapter, packageRoot); + } + + /// + /// v2.3 WebServer 文件系统入口 + /// + [Obsolete("Use CreateDefaultWebServerFileSystemParameters(bool) instead. IWebDecryptionServices is no longer supported.")] + public static FileSystemParameters CreateDefaultWebServerFileSystemParameters(IWebDecryptionServices decryptionServices, bool disableUnityWebCache = false) + { + return CreateDefaultWebServerFileSystemParameters(disableUnityWebCache); + } + + /// + /// v2.3 WebRemote 文件系统入口 + /// + [Obsolete("Use CreateDefaultWebRemoteFileSystemParameters(IRemoteService, bool) instead. IWebDecryptionServices is no longer supported.")] + public static FileSystemParameters CreateDefaultWebRemoteFileSystemParameters(IRemoteServices remoteServices, IWebDecryptionServices decryptionServices = null, bool disableUnityWebCache = false) + { + var adapter = remoteServices != null ? new RemoteServicesAdapter(remoteServices) : null; + return CreateDefaultWebRemoteFileSystemParameters(adapter, disableUnityWebCache); + } + } + + #endregion + + #region FileSystemParametersDefine + + /// + /// v2.3 文件系统参数常量定义 + /// + [Obsolete("Use EFileSystemParameter enum instead.")] + public static class FileSystemParametersDefine + { + public const string FILE_VERIFY_LEVEL = "FileVerifyLevel"; + public const string FILE_VERIFY_MAX_CONCURRENCY = "FileVerifyMaxConcurrency"; + public const string INSTALL_CLEAR_MODE = "InstallCleanupMode"; + public const string REMOTE_SERVICES = "RemoteService"; + public const string DECRYPTION_SERVICES = "DECRYPTION_SERVICES"; + public const string MANIFEST_SERVICES = "ManifestDecryptor"; + public const string APPEND_FILE_EXTENSION = "APPEND_FILE_EXTENSION"; + public const string DISABLE_CATALOG_FILE = "DISABLE_CATALOG_FILE"; + public const string DISABLE_UNITY_WEB_CACHE = "DisableUnityWebCache"; + public const string DISABLE_ONDEMAND_DOWNLOAD = "DownloadDisableOndemand"; + public const string DOWNLOAD_MAX_CONCURRENCY = "DownloadMaxConcurrency"; + public const string DOWNLOAD_MAX_REQUEST_PER_FRAME = "DownloadMaxRequestPerFrame"; + public const string DOWNLOAD_WATCH_DOG_TIME = "DownloadWatchdogTimeout"; + public const string RESUME_DOWNLOAD_MINMUM_SIZE = "DownloadResumeMinimumSize"; + public const string RESUME_DOWNLOAD_RESPONSE_CODES = "RESUME_DOWNLOAD_RESPONSE_CODES"; + public const string VIRTUAL_WEBGL_MODE = "VirtualWebglMode"; + public const string VIRTUAL_DOWNLOAD_MODE = "VirtualDownloadMode"; + public const string VIRTUAL_DOWNLOAD_SPEED = "VirtualDownloadSpeed"; + public const string ASYNC_SIMULATE_MIN_FRAME = "AsyncSimulateMinFrame"; + public const string ASYNC_SIMULATE_MAX_FRAME = "AsyncSimulateMaxFrame"; + public const string COPY_BUILDIN_PACKAGE_MANIFEST = "CopyBuiltinPackageManifest"; + public const string COPY_BUILDIN_PACKAGE_MANIFEST_DEST_ROOT = "CopyBuiltinPackageManifestDestRoot"; + public const string COPY_LOCAL_FILE_SERVICES = "COPY_LOCAL_FILE_SERVICES"; + public const string UNPACK_FILE_SYSTEM_ROOT = "UnpackFileSystemRoot"; + } + + #endregion + + #region EOverwriteInstallClearMode + + /// + /// v2.3 覆盖安装清理模式(v3 改为 EInstallCleanupMode) + /// + [Obsolete("Use EInstallCleanupMode instead.")] + public enum EOverwriteInstallClearMode + { + None = 0, + ClearAllCacheFiles = 1, + ClearAllBundleFiles = 2, + ClearAllManifestFiles = 3, + } + + #endregion + + #region IRemoteServices + + /// + /// v2.3 远端资源地址查询服务接口 + /// + [Obsolete("Implement IRemoteService instead.")] + public interface IRemoteServices + { + string GetRemoteMainURL(string fileName); + string GetRemoteFallbackURL(string fileName); + } + + /// + /// 将 v2.3 IRemoteServices 适配为 v3 IRemoteService + /// + internal sealed class RemoteServicesAdapter : IRemoteService + { + private readonly IRemoteServices _legacy; + + public RemoteServicesAdapter(IRemoteServices legacy) + { + _legacy = legacy; + } + + public IReadOnlyList GetRemoteUrls(string fileName) + { + var urls = new List(2); + string main = _legacy.GetRemoteMainURL(fileName); + if (!string.IsNullOrEmpty(main)) + urls.Add(main); + string fallback = _legacy.GetRemoteFallbackURL(fileName); + if (!string.IsNullOrEmpty(fallback)) + urls.Add(fallback); + return urls; + } + } + + #endregion + + #region IManifestRestoreServices + + /// + /// v2.3 资源清单文件处理服务接口 + /// + [Obsolete("Implement IManifestDecryptor instead.")] + public interface IManifestRestoreServices + { + byte[] RestoreManifest(byte[] fileData); + } + + /// + /// 将 v2.3 IManifestRestoreServices 适配为 v3 IManifestDecryptor + /// + internal sealed class ManifestRestoreServicesAdapter : IManifestDecryptor + { + private readonly IManifestRestoreServices _legacy; + + public ManifestRestoreServicesAdapter(IManifestRestoreServices legacy) + { + _legacy = legacy; + } + + public byte[] Decrypt(byte[] fileData) + { + return _legacy.RestoreManifest(fileData); + } + } + + #endregion + + #region IDecryptionServices / IWebDecryptionServices + + /// + /// v2.3 解密文件信息(仅用于旧接口编译兼容) + /// + [Obsolete("v3 has split decryption into dedicated decryptor interfaces. Manual migration required.")] + public struct DecryptFileInfo + { + public string BundleName; + public string FileLoadPath; + public uint FileLoadCRC; + } + + /// + /// v2.3 解密结果(仅用于旧接口编译兼容) + /// + [Obsolete("v3 has split decryption into dedicated decryptor interfaces. Manual migration required.")] + public struct DecryptResult + { + public AssetBundle Result; + public AssetBundleCreateRequest CreateRequest; + public Stream ManagedStream; + } + + /// + /// v2.3 加密文件解密服务接口(仅用于编译兼容,无法自动转换为 v3 解密器) + /// + [Obsolete("v3 has split decryption into IBundleOffsetDecryptor, IBundleMemoryDecryptor, IBundleStreamDecryptor. Manual migration required.")] + public interface IDecryptionServices + { + DecryptResult LoadAssetBundle(DecryptFileInfo fileInfo); + DecryptResult LoadAssetBundleAsync(DecryptFileInfo fileInfo); + DecryptResult LoadAssetBundleFallback(DecryptFileInfo fileInfo); + byte[] ReadFileData(DecryptFileInfo fileInfo); + string ReadFileText(DecryptFileInfo fileInfo); + } + + /// + /// v2.3 Web 解密文件信息(仅用于旧接口编译兼容) + /// + [Obsolete("v3 no longer supports IWebDecryptionServices. Manual migration required.")] + public struct WebDecryptFileInfo + { + public string BundleName; + public uint FileLoadCRC; + public byte[] FileData; + } + + /// + /// v2.3 Web 解密结果(仅用于旧接口编译兼容) + /// + [Obsolete("v3 no longer supports IWebDecryptionServices. Manual migration required.")] + public struct WebDecryptResult + { + public AssetBundle Result; + } + + /// + /// v2.3 Web 解密服务接口(仅用于编译兼容,无法自动转换为 v3 解密器) + /// + [Obsolete("v3 no longer supports IWebDecryptionServices. Manual migration required.")] + public interface IWebDecryptionServices + { + WebDecryptResult LoadAssetBundle(WebDecryptFileInfo fileInfo); + } + + #endregion +} +#endif diff --git a/Assets/YooAsset/Samples~/Extension Sample/Runtime/CompatibleOldVersion.cs.meta b/Assets/YooAsset/Runtime/Compatibility/CompatibleFileSystem.cs.meta similarity index 83% rename from Assets/YooAsset/Samples~/Extension Sample/Runtime/CompatibleOldVersion.cs.meta rename to Assets/YooAsset/Runtime/Compatibility/CompatibleFileSystem.cs.meta index 466e4d35..e678a970 100644 --- a/Assets/YooAsset/Samples~/Extension Sample/Runtime/CompatibleOldVersion.cs.meta +++ b/Assets/YooAsset/Runtime/Compatibility/CompatibleFileSystem.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: b974d3d744622f3499d026f99074cd72 +guid: a0283a72bdff8b54b93d9807ba038dbf MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/YooAsset/Runtime/Compatibility/CompatibleHandles.cs b/Assets/YooAsset/Runtime/Compatibility/CompatibleHandles.cs new file mode 100644 index 00000000..8ad9d3a5 --- /dev/null +++ b/Assets/YooAsset/Runtime/Compatibility/CompatibleHandles.cs @@ -0,0 +1,207 @@ +#if YOOASSET_LEGACY_API +// YooAsset v2.3 兼容层 - Handle 类兼容 +// 通过 partial class 为各 Handle 类补充 v2.3 的旧属性和方法。 + +using System; +using System.Threading.Tasks; +using UnityEngine; + +namespace YooAsset +{ + /// + /// v2.3 下载状态结构体(v3 已移除) + /// + [Obsolete("DownloadStatus has been removed in v3.")] + public struct DownloadStatus + { + public bool IsDone; + public float Progress; + public long TotalBytes; + public long DownloadedBytes; + + public static DownloadStatus CreateDefaultStatus() + { + return new DownloadStatus(); + } + } + + #region HandleBase -- LastError / Task / GetDownloadStatus + public abstract partial class HandleBase + { + private TaskCompletionSource _taskCompletionSource; + + /// + /// v2.3: handle.LastError + /// + [Obsolete("Use Error instead.")] + public string LastError => Error; + + /// + /// v2.3: handle.Task (System.Threading.Tasks.Task) + /// + [Obsolete("Use 'await handle' directly instead.")] + public Task Task + { + get + { + if (CheckValidWithWarning() == false) + return null; + + if (_taskCompletionSource == null) + { + _taskCompletionSource = new TaskCompletionSource(); + if (Provider.IsDone) + { + _taskCompletionSource.TrySetResult(null); + } + else + { + Provider.Completed += delegate (AsyncOperationBase op) + { + _taskCompletionSource.TrySetResult(null); + }; + } + } + return _taskCompletionSource.Task; + } + } + + /// + /// v2.3: handle.GetDownloadStatus() + /// + [Obsolete("GetDownloadStatus is no longer supported in v3.")] + public DownloadStatus GetDownloadStatus() + { + return DownloadStatus.CreateDefaultStatus(); + } + } + #endregion + + #region SceneHandle -- UnSuspend / UnloadAsync + public sealed partial class SceneHandle + { + /// + /// v2.3: sceneHandle.UnSuspend() -> v3: AllowSceneActivation() + /// + [Obsolete("Use AllowSceneActivation() instead.")] + public bool UnSuspend() => AllowSceneActivation(); + + /// + /// v2.3: sceneHandle.UnloadAsync() -> v3: UnloadSceneAsync() + /// + [Obsolete("Use UnloadSceneAsync() instead.")] + public UnloadSceneOperation UnloadAsync() => UnloadSceneAsync(); + } + #endregion + + #region RawFileHandle -- GetRawFileData / GetRawFileText + public sealed partial class RawFileHandle + { + /// + /// v2.3: rawFileHandle.GetRawFileData() + /// + [Obsolete("Read file manually via GetRawFilePath().")] + public byte[] GetRawFileData() + { + if (CheckValidWithWarning() == false) return null; + return System.IO.File.ReadAllBytes(GetRawFilePath()); + } + + /// + /// v2.3: rawFileHandle.GetRawFileText() + /// + [Obsolete("Read file manually via GetRawFilePath().")] + public string GetRawFileText() + { + if (CheckValidWithWarning() == false) return null; + return System.IO.File.ReadAllText(GetRawFilePath()); + } + } + #endregion + + #region AssetHandle -- Instantiate 多重载 + public sealed partial class AssetHandle + { + /// + /// v2.3: handle.InstantiateSync(parent) + /// + [Obsolete("Use InstantiateSync(InstantiateOptions) instead.")] + public GameObject InstantiateSync(Transform parent) + { + var options = new InstantiateOptions(true, parent, false); + return InstantiateSync(options); + } + + /// + /// v2.3: handle.InstantiateSync(parent, worldPositionStays) + /// + [Obsolete("Use InstantiateSync(InstantiateOptions) instead.")] + public GameObject InstantiateSync(Transform parent, bool worldPositionStays) + { + var options = new InstantiateOptions(true, parent, worldPositionStays); + return InstantiateSync(options); + } + + /// + /// v2.3: handle.InstantiateSync(position, rotation) + /// + [Obsolete("Use InstantiateSync(InstantiateOptions) instead.")] + public GameObject InstantiateSync(Vector3 position, Quaternion rotation) + { + var options = new InstantiateOptions(true, position, rotation); + return InstantiateSync(options); + } + + /// + /// v2.3: handle.InstantiateSync(position, rotation, parent) + /// + [Obsolete("Use InstantiateSync(InstantiateOptions) instead.")] + public GameObject InstantiateSync(Vector3 position, Quaternion rotation, Transform parent) + { + var options = new InstantiateOptions(true, parent, position, rotation); + return InstantiateSync(options); + } + + /// + /// v2.3: handle.InstantiateAsync(parent, actived) + /// + [Obsolete("Use InstantiateAsync(InstantiateOptions) instead.")] + public InstantiateOperation InstantiateAsync(Transform parent, bool actived = true) + { + var options = new InstantiateOptions(actived, parent, false); + return InstantiateAsync(options); + } + + /// + /// v2.3: handle.InstantiateAsync(parent, worldPositionStays, actived) + /// + [Obsolete("Use InstantiateAsync(InstantiateOptions) instead.")] + public InstantiateOperation InstantiateAsync(Transform parent, bool worldPositionStays, bool actived = true) + { + var options = new InstantiateOptions(actived, parent, worldPositionStays); + return InstantiateAsync(options); + } + + /// + /// v2.3: handle.InstantiateAsync(position, rotation, actived) + /// + [Obsolete("Use InstantiateAsync(InstantiateOptions) instead.")] + public InstantiateOperation InstantiateAsync(Vector3 position, Quaternion rotation, bool actived = true) + { + var options = new InstantiateOptions(actived, position, rotation); + return InstantiateAsync(options); + } + + /// + /// v2.3: handle.InstantiateAsync(position, rotation, parent, actived) + /// + [Obsolete("Use InstantiateAsync(InstantiateOptions) instead.")] + public InstantiateOperation InstantiateAsync(Vector3 position, Quaternion rotation, Transform parent, bool actived = true) + { + var options = new InstantiateOptions(actived, parent, position, rotation); + return InstantiateAsync(options); + } + } + #endregion +} +#endif diff --git a/Assets/YooAsset/Samples~/Extension Sample/Runtime/ExtensionOperation/CopyBuildinManifestOperation.cs.meta b/Assets/YooAsset/Runtime/Compatibility/CompatibleHandles.cs.meta similarity index 83% rename from Assets/YooAsset/Samples~/Extension Sample/Runtime/ExtensionOperation/CopyBuildinManifestOperation.cs.meta rename to Assets/YooAsset/Runtime/Compatibility/CompatibleHandles.cs.meta index 745ac22b..bc8f12dc 100644 --- a/Assets/YooAsset/Samples~/Extension Sample/Runtime/ExtensionOperation/CopyBuildinManifestOperation.cs.meta +++ b/Assets/YooAsset/Runtime/Compatibility/CompatibleHandles.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 41ab464f315df234fb40b0c24e97ee23 +guid: 2c3bc780b23878f4f952d53fe28bf325 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/YooAsset/Runtime/Compatibility/CompatibleOperation.cs b/Assets/YooAsset/Runtime/Compatibility/CompatibleOperation.cs new file mode 100644 index 00000000..c75bcde3 --- /dev/null +++ b/Assets/YooAsset/Runtime/Compatibility/CompatibleOperation.cs @@ -0,0 +1,219 @@ +#if YOOASSET_LEGACY_API +// YooAsset v2.3 兼容层 - Operation 类型 +// 提供 v2.3 的 InitializeParameters 类族、Operation 包装类、ImportFileInfo 和 GameAsyncOperation。 + +using System; + +namespace YooAsset +{ + #region InitializeParameters + /// + /// v2.3 初始化参数基类 + /// + [Obsolete("Use specific Options classes (e.g. EditorSimulateModeOptions) instead.")] + public abstract class InitializeParameters + { + public int BundleLoadingMaxConcurrency = int.MaxValue; + public bool AutoUnloadBundleWhenUnused = false; + public bool WebGLForceSyncLoadAsset = false; + } + + /// + /// v2.3 编辑器模拟模式初始化参数 + /// + [Obsolete("Use EditorSimulateModeOptions instead.")] + public class EditorSimulateModeParameters : InitializeParameters + { + public FileSystemParameters EditorFileSystemParameters; + } + + /// + /// v2.3 离线运行模式初始化参数 + /// + [Obsolete("Use OfflinePlayModeOptions instead.")] + public class OfflinePlayModeParameters : InitializeParameters + { + public FileSystemParameters BuildinFileSystemParameters; + } + + /// + /// v2.3 联机运行模式初始化参数 + /// + [Obsolete("Use HostPlayModeOptions instead.")] + public class HostPlayModeParameters : InitializeParameters + { + public FileSystemParameters BuildinFileSystemParameters; + public FileSystemParameters CacheFileSystemParameters; + } + + /// + /// v2.3 WebGL 运行模式初始化参数 + /// + [Obsolete("Use WebPlayModeOptions instead.")] + public class WebPlayModeParameters : InitializeParameters + { + public FileSystemParameters WebServerFileSystemParameters; + public FileSystemParameters WebRemoteFileSystemParameters; + } + + /// + /// v2.3 自定义运行模式初始化参数 + /// + [Obsolete("Use CustomPlayModeOptions instead.")] + public class CustomPlayModeParameters : InitializeParameters + { + public readonly System.Collections.Generic.List FileSystemParameterList = new System.Collections.Generic.List(); + } + #endregion + + #region LegacyOperationWrapper + /// + /// v2.3 Operation 包装基类,将 v3 的 AsyncOperationBase 转发为旧类型。 + /// + [Obsolete("Use v3 operation types directly.")] + public class LegacyOperationWrapper : AsyncOperationBase + { + private bool _isDone = false; + protected readonly AsyncOperationBase _operation; + + internal LegacyOperationWrapper(AsyncOperationBase op) + { + _operation = op; + } + protected override void InternalStart() + { + } + protected override void InternalUpdate() + { + if (_isDone) + return; + + if (IsWaitForCompletion) + _operation.WaitForCompletion(); + + _operation.UpdateOperation(); + Progress = _operation.Progress; + if (_operation.IsDone == false) + return; + + _isDone = true; + if (_operation.Status == EOperationStatus.Succeeded) + SetResult(); + else + SetError(_operation.Error); + } + protected override void InternalWaitForCompletion() + { + ExecuteBatch(); + } + } + #endregion + + #region Legacy Operations + [Obsolete("Use InitializePackageOperation instead.")] + public class InitializationOperation : LegacyOperationWrapper + { + internal InitializationOperation(InitializePackageOperation op) : base(op) { } + } + + [Obsolete("Use DestroyPackageOperation instead.")] + public class DestroyOperation : LegacyOperationWrapper + { + internal DestroyOperation(DestroyPackageOperation op) : base(op) { } + } + + [Obsolete("Use LoadPackageManifestOperation instead.")] + public class UpdatePackageManifestOperation : LegacyOperationWrapper + { + internal UpdatePackageManifestOperation(LoadPackageManifestOperation op) : base(op) { } + } + + [Obsolete("Use PrefetchManifestOperation instead.")] + public class PreDownloadContentOperation : LegacyOperationWrapper + { + private readonly PrefetchManifestOperation _prefetchOp; + + internal PreDownloadContentOperation(PrefetchManifestOperation op) : base(op) + { + _prefetchOp = op; + } + + [Obsolete("Use PrefetchManifestOperation.CreateResourceDownloader(ResourceDownloaderOptions) instead.")] + public ResourceDownloaderOperation CreateResourceDownloader(int downloadingMaxNumber, int failedTryAgain) + { + var options = new ResourceDownloaderOptions(downloadingMaxNumber, failedTryAgain); + return _prefetchOp.CreateResourceDownloader(options); + } + + [Obsolete("Use PrefetchManifestOperation.CreateResourceDownloader(ResourceDownloaderOptions) instead.")] + public ResourceDownloaderOperation CreateResourceDownloader(string tag, int downloadingMaxNumber, int failedTryAgain) + { + string[] tags = new string[] { tag }; + var options = new ResourceDownloaderOptions(tags, downloadingMaxNumber, failedTryAgain); + return _prefetchOp.CreateResourceDownloader(options); + } + + [Obsolete("Use PrefetchManifestOperation.CreateResourceDownloader(ResourceDownloaderOptions) instead.")] + public ResourceDownloaderOperation CreateResourceDownloader(string[] tags, int downloadingMaxNumber, int failedTryAgain) + { + var options = new ResourceDownloaderOptions(tags, downloadingMaxNumber, failedTryAgain); + return _prefetchOp.CreateResourceDownloader(options); + } + } + #endregion + + #region ImportFileInfo + /// + /// v2.3 导入文件信息 + /// + [Obsolete("Use ImportBundleInfo instead.")] + public struct ImportFileInfo + { + public string FilePath; + public string BundleName; + public string BundleGUID; + } + #endregion + + #region GameAsyncOperation + /// + /// v2.3 游戏异步操作基类(v3 已移除) + /// + [Obsolete("GameAsyncOperation has been removed in v3. Use AsyncOperationBase directly.")] + public abstract class GameAsyncOperation : AsyncOperationBase + { + protected override void InternalStart() + { + OnStart(); + } + protected override void InternalUpdate() + { + OnUpdate(); + } + protected override void InternalAbort() + { + OnAbort(); + } + protected override void InternalWaitForCompletion() + { + OnWaitForAsyncComplete(); + } + + protected abstract void OnStart(); + protected abstract void OnUpdate(); + protected abstract void OnAbort(); + protected virtual void OnWaitForAsyncComplete() { } + + protected new bool IsBusy + { + get { return AsyncOperationSystem.IsBusy; } + } + + protected void Abort() + { + AbortOperation(); + } + } + #endregion +} +#endif diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/Test/FileSystemTester.cs.meta b/Assets/YooAsset/Runtime/Compatibility/CompatibleOperation.cs.meta similarity index 83% rename from Assets/YooAsset/Samples~/Mini Game/Runtime/Test/FileSystemTester.cs.meta rename to Assets/YooAsset/Runtime/Compatibility/CompatibleOperation.cs.meta index e4df1b9b..471e5b7d 100644 --- a/Assets/YooAsset/Samples~/Mini Game/Runtime/Test/FileSystemTester.cs.meta +++ b/Assets/YooAsset/Runtime/Compatibility/CompatibleOperation.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 19ed2b81fece5b84fa771a5eeb108572 +guid: f16ea24f57c29f74babb8169fb1fa7a6 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/YooAsset/Runtime/Compatibility/CompatibleResourcePackage.cs b/Assets/YooAsset/Runtime/Compatibility/CompatibleResourcePackage.cs new file mode 100644 index 00000000..c4b3776c --- /dev/null +++ b/Assets/YooAsset/Runtime/Compatibility/CompatibleResourcePackage.cs @@ -0,0 +1,334 @@ +#if YOOASSET_LEGACY_API +// YooAsset v2.3 兼容层 - ResourcePackage 兼容方法 +// 通过 partial class 为 ResourcePackage 补充 v2.3 的旧接口。 + +using System; +using System.Collections.Generic; + +namespace YooAsset +{ + /// + /// v2.3 缓存清理模式(v3 改用字符串参数) + /// + [Obsolete("Use string-based ClearCacheOptions instead.")] + public enum EFileClearMode + { + ClearAllBundleFiles, + ClearUnusedBundleFiles, + ClearBundleFilesByLocations, + ClearBundleFilesByTags, + ClearAllManifestFiles, + ClearUnusedManifestFiles, + } + + public partial class ResourcePackage + { + #region 初始化 / 销毁 + [Obsolete("Use InitializePackageAsync(options) instead.")] + public InitializationOperation InitializeAsync(InitializeParameters parameters) + { + if (parameters is EditorSimulateModeParameters esp) + { + var options = new EditorSimulateModeOptions(); + options.BundleLoadingMaxConcurrency = esp.BundleLoadingMaxConcurrency; + options.AutoUnloadBundleWhenUnused = esp.AutoUnloadBundleWhenUnused; + options.WebGLForceSyncLoadAsset = esp.WebGLForceSyncLoadAsset; + options.EditorFileSystemParameters = esp.EditorFileSystemParameters; + var operation = InitializePackageAsync(options); + var wrapper = new InitializationOperation(operation); + AsyncOperationSystem.StartOperation(PackageName, wrapper); + return wrapper; + } + else if (parameters is OfflinePlayModeParameters opp) + { + var options = new OfflinePlayModeOptions(); + options.BundleLoadingMaxConcurrency = opp.BundleLoadingMaxConcurrency; + options.AutoUnloadBundleWhenUnused = opp.AutoUnloadBundleWhenUnused; + options.WebGLForceSyncLoadAsset = opp.WebGLForceSyncLoadAsset; + options.BuiltinFileSystemParameters = opp.BuildinFileSystemParameters; + var operation = InitializePackageAsync(options); + var wrapper = new InitializationOperation(operation); + AsyncOperationSystem.StartOperation(PackageName, wrapper); + return wrapper; + } + else if (parameters is HostPlayModeParameters hpp) + { + var options = new HostPlayModeOptions(); + options.BundleLoadingMaxConcurrency = hpp.BundleLoadingMaxConcurrency; + options.AutoUnloadBundleWhenUnused = hpp.AutoUnloadBundleWhenUnused; + options.WebGLForceSyncLoadAsset = hpp.WebGLForceSyncLoadAsset; + options.BuiltinFileSystemParameters = hpp.BuildinFileSystemParameters; + options.CacheFileSystemParameters = hpp.CacheFileSystemParameters; + var operation = InitializePackageAsync(options); + var wrapper = new InitializationOperation(operation); + AsyncOperationSystem.StartOperation(PackageName, wrapper); + return wrapper; + } + else if (parameters is WebPlayModeParameters wpp) + { + var options = new WebPlayModeOptions(); + options.BundleLoadingMaxConcurrency = wpp.BundleLoadingMaxConcurrency; + options.AutoUnloadBundleWhenUnused = wpp.AutoUnloadBundleWhenUnused; + options.WebGLForceSyncLoadAsset = wpp.WebGLForceSyncLoadAsset; + options.WebServerFileSystemParameters = wpp.WebServerFileSystemParameters; + options.WebRemoteFileSystemParameters = wpp.WebRemoteFileSystemParameters; + var operation = InitializePackageAsync(options); + var wrapper = new InitializationOperation(operation); + AsyncOperationSystem.StartOperation(PackageName, wrapper); + return wrapper; + } + else if (parameters is CustomPlayModeParameters cpp) + { + var options = new CustomPlayModeOptions(); + options.BundleLoadingMaxConcurrency = cpp.BundleLoadingMaxConcurrency; + options.AutoUnloadBundleWhenUnused = cpp.AutoUnloadBundleWhenUnused; + options.WebGLForceSyncLoadAsset = cpp.WebGLForceSyncLoadAsset; + foreach (var fsp in cpp.FileSystemParameterList) + options.FileSystemParameterList.Add(fsp); + var operation = InitializePackageAsync(options); + var wrapper = new InitializationOperation(operation); + AsyncOperationSystem.StartOperation(PackageName, wrapper); + return wrapper; + } + else + { + throw new NotImplementedException($"Unsupported InitializeParameters type: {parameters.GetType().Name}"); + } + } + + [Obsolete("Use DestroyPackageAsync() instead.")] + public DestroyOperation DestroyAsync() + { + var operation = DestroyPackageAsync(); + var wrapper = new DestroyOperation(operation); + AsyncOperationSystem.StartOperation(AsyncOperationSystem.GlobalSchedulerName, wrapper); + return wrapper; + } + #endregion + + #region 版本 / 清单 + [Obsolete("Use RequestPackageVersionAsync(RequestPackageVersionOptions) instead.")] + public RequestPackageVersionOperation RequestPackageVersionAsync(bool appendTimeTicks, int timeout) + { + var options = new RequestPackageVersionOptions(appendTimeTicks, timeout); + return RequestPackageVersionAsync(options); + } + + [Obsolete("Use LoadPackageManifestAsync(LoadPackageManifestOptions) instead.")] + public UpdatePackageManifestOperation UpdatePackageManifestAsync(string packageVersion, int timeout = 60) + { + var options = new LoadPackageManifestOptions(packageVersion, timeout); + var operation = LoadPackageManifestAsync(options); + var wrapper = new UpdatePackageManifestOperation(operation); + AsyncOperationSystem.StartOperation(PackageName, wrapper); + return wrapper; + } + + [Obsolete("Use PrefetchManifestAsync(PrefetchManifestOptions) instead.")] + public PreDownloadContentOperation PreDownloadContentAsync(string packageVersion, int timeout = 60) + { + var options = new PrefetchManifestOptions(packageVersion, timeout); + var op = PrefetchManifestAsync(options); + var wrapper = new PreDownloadContentOperation(op); + AsyncOperationSystem.StartOperation(PackageName, wrapper); + return wrapper; + } + #endregion + + #region 缓存清理 + [Obsolete("Use ClearCacheAsync(ClearCacheOptions) instead.")] + public ClearCacheOperation ClearCacheFilesAsync(string fileClearMode, object clearParam = null) + { + var options = new ClearCacheOptions(fileClearMode, clearParam); + return ClearCacheAsync(options); + } + + [Obsolete("Use ClearCacheAsync(ClearCacheOptions) instead.")] + public ClearCacheOperation ClearCacheFilesAsync(EFileClearMode clearMode, object clearParam = null) + { + var options = new ClearCacheOptions(clearMode.ToString(), clearParam); + return ClearCacheAsync(options); + } + #endregion + + #region 资源卸载 + [Obsolete("Use UnloadUnusedAssetsAsync(UnloadUnusedAssetsOptions) instead.")] + public UnloadUnusedAssetsOperation UnloadUnusedAssetsAsync(int loopCount) + { + var options = new UnloadUnusedAssetsOptions(loopCount); + return UnloadUnusedAssetsAsync(options); + } + #endregion + + #region 资源查询 + [Obsolete("Use GetDownloadSize() instead.")] + public bool IsNeedDownloadFromRemote(string location) + { + return GetDownloadSize(location) > 0; + } + + [Obsolete("Use GetDownloadSize() instead.")] + public bool IsNeedDownloadFromRemote(AssetInfo assetInfo) + { + return GetDownloadSize(assetInfo) > 0; + } + + [Obsolete("Use IsLocationValid() instead.")] + public bool CheckLocationValid(string location) + { + return IsLocationValid(location); + } + + [Obsolete("Use GetAssetInfoByGuid() instead.")] + public AssetInfo GetAssetInfoByGUID(string assetGUID) + { + return GetAssetInfoByGuid(assetGUID); + } + + [Obsolete("Use GetAssetInfoByGuid() instead.")] + public AssetInfo GetAssetInfoByGUID(string assetGUID, Type type) + { + return GetAssetInfoByGuid(assetGUID, type); + } + #endregion + + #region 资源下载 + [Obsolete("Use CreateResourceDownloader(ResourceDownloaderOptions) instead.")] + public ResourceDownloaderOperation CreateResourceDownloader(int downloadingMaxNumber, int failedTryAgain) + { + var options = new ResourceDownloaderOptions(downloadingMaxNumber, failedTryAgain); + return CreateResourceDownloader(options); + } + + [Obsolete("Use CreateResourceDownloader(ResourceDownloaderOptions) instead.")] + public ResourceDownloaderOperation CreateResourceDownloader(string tag, int downloadingMaxNumber, int failedTryAgain) + { + string[] tags = new string[] { tag }; + var options = new ResourceDownloaderOptions(tags, downloadingMaxNumber, failedTryAgain); + return CreateResourceDownloader(options); + } + + [Obsolete("Use CreateResourceDownloader(ResourceDownloaderOptions) instead.")] + public ResourceDownloaderOperation CreateResourceDownloader(string[] tags, int downloadingMaxNumber, int failedTryAgain) + { + var options = new ResourceDownloaderOptions(tags, downloadingMaxNumber, failedTryAgain); + return CreateResourceDownloader(options); + } + + [Obsolete("Use CreateResourceDownloader(BundleDownloaderOptions) instead.")] + public ResourceDownloaderOperation CreateBundleDownloader(string location, bool recursiveDownload, int downloadingMaxNumber, int failedTryAgain) + { + var assetInfo = ConvertLocationToAssetInfo(location, null); + var options = new BundleDownloaderOptions(assetInfo, recursiveDownload, downloadingMaxNumber, failedTryAgain); + return CreateResourceDownloader(options); + } + + [Obsolete("Use CreateResourceDownloader(BundleDownloaderOptions) instead.")] + public ResourceDownloaderOperation CreateBundleDownloader(string location, int downloadingMaxNumber, int failedTryAgain) + { + return CreateBundleDownloader(location, false, downloadingMaxNumber, failedTryAgain); + } + + [Obsolete("Use CreateResourceDownloader(BundleDownloaderOptions) instead.")] + public ResourceDownloaderOperation CreateBundleDownloader(string[] locations, bool recursiveDownload, int downloadingMaxNumber, int failedTryAgain) + { + List assetInfos = new List(locations.Length); + foreach (var location in locations) + { + var assetInfo = ConvertLocationToAssetInfo(location, null); + assetInfos.Add(assetInfo); + } + var options = new BundleDownloaderOptions(assetInfos.ToArray(), recursiveDownload, downloadingMaxNumber, failedTryAgain); + return CreateResourceDownloader(options); + } + + [Obsolete("Use CreateResourceDownloader(BundleDownloaderOptions) instead.")] + public ResourceDownloaderOperation CreateBundleDownloader(string[] locations, int downloadingMaxNumber, int failedTryAgain) + { + return CreateBundleDownloader(locations, false, downloadingMaxNumber, failedTryAgain); + } + + [Obsolete("Use CreateResourceDownloader(BundleDownloaderOptions) instead.")] + public ResourceDownloaderOperation CreateBundleDownloader(AssetInfo assetInfo, bool recursiveDownload, int downloadingMaxNumber, int failedTryAgain) + { + AssetInfo[] assetInfos = new AssetInfo[] { assetInfo }; + var options = new BundleDownloaderOptions(assetInfos, recursiveDownload, downloadingMaxNumber, failedTryAgain); + return CreateResourceDownloader(options); + } + + [Obsolete("Use CreateResourceDownloader(BundleDownloaderOptions) instead.")] + public ResourceDownloaderOperation CreateBundleDownloader(AssetInfo assetInfo, int downloadingMaxNumber, int failedTryAgain) + { + return CreateBundleDownloader(assetInfo, false, downloadingMaxNumber, failedTryAgain); + } + + [Obsolete("Use CreateResourceDownloader(BundleDownloaderOptions) instead.")] + public ResourceDownloaderOperation CreateBundleDownloader(AssetInfo[] assetInfos, bool recursiveDownload, int downloadingMaxNumber, int failedTryAgain) + { + var options = new BundleDownloaderOptions(assetInfos, recursiveDownload, downloadingMaxNumber, failedTryAgain); + return CreateResourceDownloader(options); + } + + [Obsolete("Use CreateResourceDownloader(BundleDownloaderOptions) instead.")] + public ResourceDownloaderOperation CreateBundleDownloader(AssetInfo[] assetInfos, int downloadingMaxNumber, int failedTryAgain) + { + return CreateBundleDownloader(assetInfos, false, downloadingMaxNumber, failedTryAgain); + } + #endregion + + #region 资源解压 + [Obsolete("Use CreateResourceUnpacker(ResourceUnpackerOptions) instead.")] + public ResourceUnpackerOperation CreateResourceUnpacker(int unpackingMaxNumber, int failedTryAgain) + { + var options = new ResourceUnpackerOptions(unpackingMaxNumber, failedTryAgain); + return CreateResourceUnpacker(options); + } + + [Obsolete("Use CreateResourceUnpacker(ResourceUnpackerOptions) instead.")] + public ResourceUnpackerOperation CreateResourceUnpacker(string tag, int unpackingMaxNumber, int failedTryAgain) + { + string[] tags = new string[] { tag }; + var options = new ResourceUnpackerOptions(tags, unpackingMaxNumber, failedTryAgain); + return CreateResourceUnpacker(options); + } + + [Obsolete("Use CreateResourceUnpacker(ResourceUnpackerOptions) instead.")] + public ResourceUnpackerOperation CreateResourceUnpacker(string[] tags, int unpackingMaxNumber, int failedTryAgain) + { + var options = new ResourceUnpackerOptions(tags, unpackingMaxNumber, failedTryAgain); + return CreateResourceUnpacker(options); + } + #endregion + + #region 资源导入 + [Obsolete("Use CreateResourceImporter(BundleImporterOptions) instead.")] + public ResourceImporterOperation CreateResourceImporter(string[] filePaths, int importerMaxNumber, int failedTryAgain) + { + ImportFileInfo[] fileInfos = new ImportFileInfo[filePaths.Length]; + for (int i = 0; i < filePaths.Length; i++) + { + ImportFileInfo fileInfo = new ImportFileInfo(); + fileInfo.FilePath = filePaths[i]; + fileInfos[i] = fileInfo; + } + return CreateResourceImporter(fileInfos, importerMaxNumber, failedTryAgain); + } + + [Obsolete("Use CreateResourceImporter(BundleImporterOptions) instead.")] + public ResourceImporterOperation CreateResourceImporter(ImportFileInfo[] fileInfos, int importerMaxNumber, int failedTryAgain) + { + ImportBundleInfo[] bundleInfos = new ImportBundleInfo[fileInfos.Length]; + for (int i = 0; i < fileInfos.Length; i++) + { + bundleInfos[i] = new ImportBundleInfo( + filePath: fileInfos[i].FilePath, + bundleName: fileInfos[i].BundleName, + bundleGuid: fileInfos[i].BundleGUID); + } + var options = new BundleImporterOptions(bundleInfos, importerMaxNumber, failedTryAgain); + return CreateResourceImporter(options); + } + #endregion + } +} +#endif diff --git a/Assets/YooAsset/Runtime/Compatibility/CompatibleResourcePackage.cs.meta b/Assets/YooAsset/Runtime/Compatibility/CompatibleResourcePackage.cs.meta new file mode 100644 index 00000000..263015c3 --- /dev/null +++ b/Assets/YooAsset/Runtime/Compatibility/CompatibleResourcePackage.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fcb10923f246d8844b4980dcb84bec86 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/YooAsset/Runtime/Compatibility/CompatibleYooAssets.cs b/Assets/YooAsset/Runtime/Compatibility/CompatibleYooAssets.cs new file mode 100644 index 00000000..95d80e0f --- /dev/null +++ b/Assets/YooAsset/Runtime/Compatibility/CompatibleYooAssets.cs @@ -0,0 +1,83 @@ +#if YOOASSET_LEGACY_API +// YooAsset v2.3 兼容层 - YooAssets 静态类兼容 +// 通过 partial class 为 YooAssets 补充 v2.3 的旧静态属性和方法。 + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace YooAsset +{ + public static partial class YooAssets + { + /// + /// v2.3: YooAssets.Initialized + /// + [Obsolete("Use IsInitialized instead.")] + public static bool Initialized => IsInitialized; + + /// + /// v2.3: YooAssets.GetAllPackages() + /// + [Obsolete("Use GetPackages() instead.")] + public static List GetAllPackages() + { + return GetPackages().ToList(); + } + + /// + /// v2.3: YooAssets.TryGetPackage(string) + /// + [Obsolete("Use TryGetPackage(string, out ResourcePackage) instead.")] + public static ResourcePackage TryGetPackage(string packageName) + { + TryGetPackage(packageName, out var package); + return package; + } + + /// + /// v2.3: YooAssets.RemovePackage(ResourcePackage) + /// + [Obsolete("Use RemovePackage(string) instead.")] + public static bool RemovePackage(ResourcePackage package) + { + try + { + RemovePackage(package.PackageName); + return true; + } + catch + { + return false; + } + } + + /// + /// v2.3: YooAssets.SetOperationSystemMaxTimeSlice(long) + /// + [Obsolete("Use SetAsyncOperationMaxTimeSlice() instead.")] + public static void SetOperationSystemMaxTimeSlice(long milliseconds) + { + SetAsyncOperationMaxTimeSlice(milliseconds); + } + + /// + /// v2.3: YooAssets.SetDownloadSystemUnityWebRequest(delegate) + /// + [Obsolete("This API has been removed in v3.")] + public static void SetDownloadSystemUnityWebRequest(object createDelegate) + { + throw new System.NotImplementedException(); + } + + /// + /// v2.3: YooAssets.StartOperation(GameAsyncOperation) + /// + [Obsolete("GameAsyncOperation has been removed in v3.")] + public static void StartOperation(GameAsyncOperation operation) + { + AsyncOperationSystem.StartOperation(AsyncOperationSystem.GlobalSchedulerName, operation); + } + } +} +#endif diff --git a/Assets/YooAsset/Runtime/Compatibility/CompatibleYooAssets.cs.meta b/Assets/YooAsset/Runtime/Compatibility/CompatibleYooAssets.cs.meta new file mode 100644 index 00000000..579e0fbc --- /dev/null +++ b/Assets/YooAsset/Runtime/Compatibility/CompatibleYooAssets.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 93e9bc10b05be8b42a704832abed581d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/YooAsset/Runtime/Compatibility/MIGRATION_GUIDE.md b/Assets/YooAsset/Runtime/Compatibility/MIGRATION_GUIDE.md new file mode 100644 index 00000000..a7b66b40 --- /dev/null +++ b/Assets/YooAsset/Runtime/Compatibility/MIGRATION_GUIDE.md @@ -0,0 +1,230 @@ +# YooAsset v2.3 → v3.x 迁移指南 + +本兼容层允许大部分 v2.3 业务代码在 v3.x 下**零修改编译通过**。所有兼容 API 均标记了 `[Obsolete]`,编译时会输出警告提示迁移到 v3 新接口。 + +## 启用兼容层 + +兼容代码默认**不参与编译**,需要手动添加编译宏才能启用: + +**Unity Editor**:`Edit → Project Settings → Player → Scripting Define Symbols`,添加 `YOOASSET_LEGACY_API` + +添加后重新编译即可生效。当所有业务代码已迁移到 v3 新接口后,移除该宏即可彻底关闭兼容层。 + +--- + +## 一、API 对照表(自动兼容,无需修改代码) + +### 1.1 枚举与状态 + +| v2.3 写法 | v3 新写法 | +|-----------|----------| +| `EOperationStatus.Succeed` | `EOperationStatus.Succeeded` | +| `EFileClearMode.ClearAllBundleFiles` | `"ClearAllBundleFiles"` (字符串) | +| `EPlayMode.HostPlayMode` | 已移除(用 Options 类代替) | +| `handle.GetDownloadStatus()` | 已移除 | + +### 1.2 HandleBase + +| v2.3 写法 | v3 新写法 | +|-----------|----------| +| `handle.LastError` | `handle.Error` | +| `await handle.Task` | `await handle` | +| `handle.GetDownloadStatus()` | 已移除 | + +### 1.3 SceneHandle + +| v2.3 写法 | v3 新写法 | +|-----------|----------| +| `sceneHandle.UnSuspend()` | `sceneHandle.AllowSceneActivation()` | +| `sceneHandle.UnloadAsync()` | `sceneHandle.UnloadSceneAsync()` | + +### 1.4 RawFileHandle + +| v2.3 写法 | v3 新写法 | +|-----------|----------| +| `rawHandle.GetRawFileData()` | `File.ReadAllBytes(rawHandle.GetRawFilePath())` | +| `rawHandle.GetRawFileText()` | `File.ReadAllText(rawHandle.GetRawFilePath())` | + +### 1.5 AssetHandle 实例化 + +| v2.3 写法 | v3 新写法 | +|-----------|----------| +| `handle.InstantiateSync(parent)` | `handle.InstantiateSync(new InstantiateOptions(...))` | +| `handle.InstantiateSync(parent, worldPositionStays)` | 同上 | +| `handle.InstantiateSync(position, rotation)` | 同上 | +| `handle.InstantiateSync(position, rotation, parent)` | 同上 | +| `handle.InstantiateAsync(parent, actived)` | `handle.InstantiateAsync(new InstantiateOptions(...))` | +| `handle.InstantiateAsync(parent, worldPositionStays, actived)` | 同上 | +| `handle.InstantiateAsync(position, rotation, actived)` | 同上 | +| `handle.InstantiateAsync(position, rotation, parent, actived)` | 同上 | + +### 1.6 DownloaderOperation + +| v2.3 写法 | v3 新写法 | +|-----------|----------| +| `downloader.BeginDownload()` | `downloader.StartDownload()` | +| `downloader.DownloadFinishCallback = ...` | `downloader.DownloadCompleted += ...` | +| `downloader.DownloadUpdateCallback = ...` | `downloader.DownloadProgressChanged += ...` | +| `downloader.DownloadErrorCallback = ...` | `downloader.DownloadError += ...` | +| `downloader.DownloadFileBeginCallback = ...` | `downloader.DownloadFileStarted += ...` | + +> **注意**:v2.3 的 `DownloadError` 委托名与 v3 的 `DownloadError` event 冲突,已重命名为 `DownloadErrorDelegate`。如果你的旧代码中直接引用了 `DownloaderOperation.DownloadError` 委托类型,需要改为 `DownloadErrorDelegate`。 + +### 1.7 ResourcePackage + +| v2.3 写法 | v3 新写法 | +|-----------|----------| +| `package.InitializeAsync(parameters)` | `package.InitializePackageAsync(options)` | +| `package.DestroyAsync()` | `package.DestroyPackageAsync()` | +| `package.RequestPackageVersionAsync(bool, int)` | `package.RequestPackageVersionAsync(options)` | +| `package.UpdatePackageManifestAsync(version, timeout)` | `package.LoadPackageManifestAsync(options)` | +| `package.PreDownloadContentAsync(version, timeout)` | `package.PrefetchManifestAsync(options)` | +| `package.ClearCacheFilesAsync(mode, param)` | `package.ClearCacheAsync(options)` | +| `package.UnloadUnusedAssetsAsync(loopCount)` | `package.UnloadUnusedAssetsAsync(options)` | +| `package.IsNeedDownloadFromRemote(location)` | `package.GetDownloadSize(location) > 0` | +| `package.CheckLocationValid(location)` | `package.IsLocationValid(location)` | +| `package.GetAssetInfoByGUID(guid)` | `package.GetAssetInfoByGuid(guid)` | +| `package.CreateResourceDownloader(maxNum, retry)` | `package.CreateResourceDownloader(options)` | +| `package.CreateBundleDownloader(...)` | `package.CreateResourceDownloader(bundleOptions)` | +| `package.CreateResourceUnpacker(maxNum, retry)` | `package.CreateResourceUnpacker(options)` | +| `package.CreateResourceImporter(paths, maxNum, retry)` | `package.CreateResourceImporter(bundleImporterOptions)` | + +### 1.8 YooAssets 静态类 + +| v2.3 写法 | v3 新写法 | +|-----------|----------| +| `YooAssets.Initialized` | `YooAssets.IsInitialized` | +| `YooAssets.GetAllPackages()` | `YooAssets.GetPackages()` | +| `YooAssets.TryGetPackage(name)` 返回 null | `YooAssets.TryGetPackage(name, out pkg)` | +| `YooAssets.RemovePackage(package)` 传入实例 | `YooAssets.RemovePackage(packageName)` 传入字符串 | +| `YooAssets.SetOperationSystemMaxTimeSlice(ms)` | `YooAssets.SetAsyncOperationMaxTimeSlice(ms)` | +| `YooAssets.SetDownloadSystemUnityWebRequest(...)` | 已移除 | +| `YooAssets.StartOperation(gameAsyncOp)` | 已移除 | + +### 1.9 文件系统参数 + +| v2.3 写法 | v3 新写法 | +|-----------|----------| +| `params.FileSystemClass` | `params.FileSystemTypeName` | +| `CreateDefaultBuildinFileSystemParameters(decryptSvc, root)` | `CreateDefaultBuiltinFileSystemParameters(root)` | +| `CreateDefaultCacheFileSystemParameters(remoteSvc, decryptSvc, root)` | `CreateDefaultSandboxFileSystemParameters(remoteService, root)` | +| `CreateDefaultWebServerFileSystemParameters(webDecryptSvc, disableCache)` | `CreateDefaultWebServerFileSystemParameters(disableCache)` | +| `CreateDefaultWebRemoteFileSystemParameters(remoteSvc, webDecryptSvc, disableCache)` | `CreateDefaultWebRemoteFileSystemParameters(remoteService, disableCache)` | +| `FileSystemParametersDefine.XXX` 常量 | `EFileSystemParameter.Xxx` 枚举 | +| `IRemoteServices` | `IRemoteService` | +| `IManifestRestoreServices` | `IManifestDecryptor` | +| `EOverwriteInstallClearMode` | `EInstallCleanupMode` | +| `AddParameter(FileSystemParametersDefine.REMOTE_SERVICES, remoteSvc)` | 自动包装为 `IRemoteService` | +| `AddParameter(FileSystemParametersDefine.MANIFEST_SERVICES, manifestSvc)` | 自动包装为 `IManifestDecryptor` | +| `AddParameter(FileSystemParametersDefine.INSTALL_CLEAR_MODE, oldMode)` | 自动转换为 `EInstallCleanupMode` | + +### 1.10 其他旧类型 + +| v2.3 类型 | v3 对应 | +|----------|---------| +| `InitializeParameters` 及子类 | `EditorSimulateModeOptions` 等 Options 类 | +| `InitializationOperation` | `InitializePackageOperation` | +| `DestroyOperation` | `DestroyPackageOperation` | +| `UpdatePackageManifestOperation` | `LoadPackageManifestOperation` | +| `PreDownloadContentOperation` | `PrefetchManifestOperation` | +| `GameAsyncOperation` | 已移除(用 `AsyncOperationBase`) | +| `ImportFileInfo` | `ImportBundleInfo` | +| `DownloaderFinishData` | `DownloadCompletedEventArgs` | +| `DownloadUpdateData` | `DownloadProgressChangedEventArgs` | +| `DownloadErrorData` | `DownloadErrorEventArgs` | +| `DownloadFileData` | `DownloadFileStartedEventArgs` | +| `DownloadStatus` | 已移除 | + +--- + +## 二、需要手动迁移的项(无法自动兼容) + +### 2.1 默认包裹快捷 API(已彻底移除) + +v2.3 中 `YooAssets.SetDefaultPackage()` 及其关联的约 50 个静态快捷方法已在 v3 中**完全移除,不提供兼容**: + +```csharp +// v2.3 写法 -- 不再支持 +YooAssets.SetDefaultPackage(package); +YooAssets.LoadAssetAsync("Assets/Prefabs/Hero.prefab"); + +// v3 写法 -- 必须通过 ResourcePackage 实例调用 +var package = YooAssets.GetPackage("DefaultPackage"); +package.LoadAssetAsync("Assets/Prefabs/Hero.prefab"); +``` + +**迁移建议**:全局搜索 `YooAssets.Load`、`YooAssets.GetAssetInfo`、`YooAssets.SetDefaultPackage` 等调用,替换为 `package.Xxx(...)` 形式。 + +### 2.2 DownloadError 委托名冲突 + +v2.3 的 `DownloaderOperation.DownloadError` 委托类型与 v3 的 `DownloadError` event 同名,兼容层已将旧委托重命名为 `DownloadErrorDelegate`。 + +### 2.3 LoadSceneAsync 的 suspendLoad 参数语义反转 + +v2.3 的 `LoadSceneAsync(..., bool suspendLoad, ...)` 与 v3 的 `LoadSceneAsync(..., bool allowSceneActivation, ...)` 参数类型签名完全相同,仅参数名和语义相反(`suspendLoad=true` 等价于 `allowSceneActivation=false`)。由于方法签名冲突,无法通过兼容层自动处理。 + +```csharp +// v2.3 写法 +package.LoadSceneAsync("scene", LoadSceneMode.Single, LocalPhysicsMode.None, suspendLoad: true, 100); + +// v3 写法 -- 注意 bool 语义反转 +package.LoadSceneAsync("scene", LoadSceneMode.Single, LocalPhysicsMode.None, allowSceneActivation: false, 100); +``` + +### 2.4 ClearCacheFilesOperation 类型名冲突 + +v2.3 的 `ClearCacheFilesOperation` 与 v3 内部同名类冲突,无法提供兼容包装类。如果旧代码中显式引用了该类型名,需改为 `ClearCacheOperation`。通过 `package.ClearCacheFilesAsync(...)` 调用并用 `var` 接收返回值的写法不受影响。 + +### 2.5 UnloadAllAssetsOptions 写法变更 + +v2.3 是 `class` + 公有可变字段,v3 是 `readonly struct` + 构造函数。此场景极少出现。 + +### 2.6 文件系统参数迁移 + +#### 解密服务接口重构(必须手动迁移) + +v2.3 的 `IDecryptionServices` 和 `IWebDecryptionServices` 在 v3 中已拆分为多个专用接口: + +| v2.3 | v3 | +|------|-----| +| `IDecryptionServices.LoadAssetBundle()` | `IBundleOffsetDecryptor` 或 `IBundleStreamDecryptor` | +| `IDecryptionServices.LoadAssetBundleAsync()` | 同上 | +| `IDecryptionServices.LoadAssetBundleFallback()` | `IBundleMemoryDecryptor` | +| `IDecryptionServices.ReadFileData()` / `ReadFileText()` | 已移除 | +| `IWebDecryptionServices` | 已移除,无替代 | + +兼容层保留了 `IDecryptionServices`、`IWebDecryptionServices` 及相关 `DecryptFileInfo` / `DecryptResult` 类型签名以避免编译错误,但**不会自动转换为 v3 解密器**。旧工厂方法中传入的 `decryptionServices` 参数会被忽略。 + +```csharp +// v2.3 写法 +var fsp = FileSystemParameters.CreateDefaultBuildinFileSystemParameters(myDecryptSvc); + +// 兼容层编译通过,但 myDecryptSvc 不生效! +// 迁移方法:实现 IBundleOffsetDecryptor 等新接口,通过 EFileSystemParameter 添加 +var fsp = FileSystemParameters.CreateDefaultBuiltinFileSystemParameters(); +fsp.AddParameter(EFileSystemParameter.AssetbundleDecryptor, myNewDecryptor); +``` + +#### 已移除的参数常量 + +以下 `FileSystemParametersDefine` 常量在 v3 中无稳定等价参数,兼容层保留了常量值但 v3 文件系统不会识别: + +- `APPEND_FILE_EXTENSION` — 已移除 +- `DISABLE_CATALOG_FILE` — 已移除 +- `COPY_LOCAL_FILE_SERVICES` — 已移除 +- `RESUME_DOWNLOAD_RESPONSE_CODES` — 已移除 + +#### 旧内部文件系统类名 + +v2.3 中通过字符串引用的内部文件系统类名在 v3 中已变更: + +| v2.3 类名 | v3 类名 | +|-----------|---------| +| `DefaultEditorFileSystem` | `EditorFileSystem` | +| `DefaultBuildinFileSystem` | `BuiltinFileSystem` | +| `DefaultCacheFileSystem` | `SandboxFileSystem` | +| `DefaultWebServerFileSystem` | `WebServerFileSystem` | +| `DefaultWebRemoteFileSystem` | `WebRemoteFileSystem` | + +如果旧代码中手写了类名字符串(如 `new FileSystemParameters("YooAsset.DefaultCacheFileSystem", root)`),需改为 v3 工厂方法或更新类名。 + diff --git a/Assets/YooAsset/Samples~/Mini Game/Scenes/WechatFileSystemTest.unity.meta b/Assets/YooAsset/Runtime/Compatibility/MIGRATION_GUIDE.md.meta similarity index 62% rename from Assets/YooAsset/Samples~/Mini Game/Scenes/WechatFileSystemTest.unity.meta rename to Assets/YooAsset/Runtime/Compatibility/MIGRATION_GUIDE.md.meta index fa3fed06..d2c66785 100644 --- a/Assets/YooAsset/Samples~/Mini Game/Scenes/WechatFileSystemTest.unity.meta +++ b/Assets/YooAsset/Runtime/Compatibility/MIGRATION_GUIDE.md.meta @@ -1,6 +1,6 @@ fileFormatVersion: 2 -guid: 2aba4dc1069712d4da0976a70c62e040 -DefaultImporter: +guid: f0c6ef1d5368f6a4ca479c94b91ceb81 +TextScriptImporter: externalObjects: {} userData: assetBundleName: diff --git a/Assets/YooAsset/Runtime/DiagnosticSystem/DiagnosticReport/DiagnosticPackageData.cs b/Assets/YooAsset/Runtime/DiagnosticSystem/DiagnosticReport/DiagnosticPackageData.cs index 27530d51..e507917b 100644 --- a/Assets/YooAsset/Runtime/DiagnosticSystem/DiagnosticReport/DiagnosticPackageData.cs +++ b/Assets/YooAsset/Runtime/DiagnosticSystem/DiagnosticReport/DiagnosticPackageData.cs @@ -9,7 +9,9 @@ namespace YooAsset [Serializable] internal class DiagnosticPackageData { + [NonSerialized] private readonly Dictionary _bundleInfoDict = new Dictionary(); + [NonSerialized] private bool _isParsed = false; /// diff --git a/Assets/YooAsset/Runtime/DownloadSystem/DownloadUrlHelper.cs b/Assets/YooAsset/Runtime/DownloadSystem/DownloadUrlHelper.cs index 90b07c93..bd38c90f 100644 --- a/Assets/YooAsset/Runtime/DownloadSystem/DownloadUrlHelper.cs +++ b/Assets/YooAsset/Runtime/DownloadSystem/DownloadUrlHelper.cs @@ -19,24 +19,11 @@ namespace YooAsset if (string.IsNullOrEmpty(filePath)) throw new YooInternalException("File path is null or empty."); - if (IsLocalFileUrl(filePath)) - return EscapeSpecialCharacters(filePath); - string url; - -#if UNITY_WEBGL - url = filePath; -#elif UNITY_ANDROID - url = new System.Uri(filePath).ToString(); -#elif UNITY_OPENHARMONY - // 注意:由于鸿蒙系统的特殊性,需要判断双形态 - if (UnityEngine.Application.streamingAssetsPath.StartsWith("jar:file://")) - url = StringUtility.Format("jar:file://{0}", filePath); + if (IsLocalFileUrl(filePath)) + url = filePath; else - url = new System.Uri(filePath).ToString(); -#else - url = new System.Uri(filePath).ToString(); -#endif + url = CreateLocalFileUrl(filePath); return EscapeSpecialCharacters(url); } @@ -60,6 +47,20 @@ namespace YooAsset return false; } + private static string CreateLocalFileUrl(string filePath) + { +#if UNITY_WEBGL + return filePath; +#elif UNITY_OPENHARMONY + // 注意:由于鸿蒙系统的特殊性,需要判断双形态 + if (UnityEngine.Application.streamingAssetsPath.StartsWith("jar:file://")) + return $"jar:file://{filePath}"; + else + return new System.Uri(filePath).ToString(); +#else + return new System.Uri(filePath).ToString(); +#endif + } private static string EscapeSpecialCharacters(string url) { // 处理特殊字符:用户设备路径可能包含特殊字符导致 URL 无法正确识别 diff --git a/Assets/YooAsset/Runtime/FileSystem/FileSystemParameters.cs b/Assets/YooAsset/Runtime/FileSystem/FileSystemParameters.cs index 83a350be..0e744a59 100644 --- a/Assets/YooAsset/Runtime/FileSystem/FileSystemParameters.cs +++ b/Assets/YooAsset/Runtime/FileSystem/FileSystemParameters.cs @@ -6,7 +6,7 @@ namespace YooAsset /// /// 提供文件系统的创建参数与工厂方法 /// - public class FileSystemParameters + public partial class FileSystemParameters { internal readonly Dictionary _createParameters = new Dictionary(100); diff --git a/Assets/YooAsset/Runtime/FileSystem/Services/WebGameFileSystem/WebGameFileSystem.cs b/Assets/YooAsset/Runtime/FileSystem/Services/WebGameFileSystem/WebGameFileSystem.cs index fc6fc30d..a1cbb017 100644 --- a/Assets/YooAsset/Runtime/FileSystem/Services/WebGameFileSystem/WebGameFileSystem.cs +++ b/Assets/YooAsset/Runtime/FileSystem/Services/WebGameFileSystem/WebGameFileSystem.cs @@ -165,7 +165,7 @@ namespace YooAsset // 创建默认的下载后台接口 if (DownloadBackend == null) - DownloadBackend = new UnityWebRequestBackend(null); + DownloadBackend = new UnityWebRequestBackend(); // 创建默认的下载重试策略 if (DownloadRetryPolicy == null) diff --git a/Assets/YooAsset/Runtime/ResourceManager/Handles/AllAssetsHandle.cs b/Assets/YooAsset/Runtime/ResourceManager/Handles/AllAssetsHandle.cs index b18817dc..533ae2ac 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Handles/AllAssetsHandle.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Handles/AllAssetsHandle.cs @@ -6,7 +6,7 @@ namespace YooAsset /// /// 全资源句柄,用于加载资源包内所有资源对象。 /// - public sealed class AllAssetsHandle : HandleBase + public sealed partial class AllAssetsHandle : HandleBase { private System.Action _callback; diff --git a/Assets/YooAsset/Runtime/ResourceManager/Handles/AssetHandle.cs b/Assets/YooAsset/Runtime/ResourceManager/Handles/AssetHandle.cs index faca862a..71675eeb 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Handles/AssetHandle.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Handles/AssetHandle.cs @@ -5,7 +5,7 @@ namespace YooAsset /// /// 资源句柄,用于管理单个资源对象的加载和访问。 /// - public sealed class AssetHandle : HandleBase + public sealed partial class AssetHandle : HandleBase { private System.Action _callback; diff --git a/Assets/YooAsset/Runtime/ResourceManager/Handles/HandleBase.cs b/Assets/YooAsset/Runtime/ResourceManager/Handles/HandleBase.cs index ddf33581..7fbd3148 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Handles/HandleBase.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Handles/HandleBase.cs @@ -6,7 +6,7 @@ namespace YooAsset /// /// 资源句柄基类,提供资源加载状态查询和释放功能。 /// - public abstract class HandleBase : IEnumerator, IDisposable + public abstract partial class HandleBase : IEnumerator, IDisposable { private readonly AssetInfo _assetInfo; diff --git a/Assets/YooAsset/Runtime/ResourceManager/Handles/RawFileHandle.cs b/Assets/YooAsset/Runtime/ResourceManager/Handles/RawFileHandle.cs index b172ea80..6bc57dfc 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Handles/RawFileHandle.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Handles/RawFileHandle.cs @@ -4,7 +4,7 @@ namespace YooAsset /// /// 原生文件句柄,用于访问未经 Unity 处理的原始文件。 /// - public sealed class RawFileHandle : HandleBase + public sealed partial class RawFileHandle : HandleBase { private System.Action _callback; diff --git a/Assets/YooAsset/Runtime/ResourceManager/Handles/SceneHandle.cs b/Assets/YooAsset/Runtime/ResourceManager/Handles/SceneHandle.cs index be6046d0..a466f606 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Handles/SceneHandle.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Handles/SceneHandle.cs @@ -5,7 +5,7 @@ namespace YooAsset /// /// 场景句柄,用于管理场景的加载、激活和卸载。 /// - public sealed class SceneHandle : HandleBase + public sealed partial class SceneHandle : HandleBase { private System.Action _callback; diff --git a/Assets/YooAsset/Runtime/ResourceManager/Handles/SubAssetsHandle.cs b/Assets/YooAsset/Runtime/ResourceManager/Handles/SubAssetsHandle.cs index 0f3a38a9..9e1deb0b 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Handles/SubAssetsHandle.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Handles/SubAssetsHandle.cs @@ -6,7 +6,7 @@ namespace YooAsset /// /// 子资源句柄,用于管理资源包内子资源对象的加载和访问。 /// - public sealed class SubAssetsHandle : HandleBase + public sealed partial class SubAssetsHandle : HandleBase { private System.Action _callback; diff --git a/Assets/YooAsset/Runtime/ResourceManager/Operations/InstantiateOperation.cs b/Assets/YooAsset/Runtime/ResourceManager/Operations/InstantiateOperation.cs index 443f5202..b9c20da9 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Operations/InstantiateOperation.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Operations/InstantiateOperation.cs @@ -35,10 +35,12 @@ namespace YooAsset _handle = handle; _options = options; } + /// protected override void InternalStart() { _steps = ESteps.LoadObject; } + /// protected override void InternalUpdate() { if (_steps == ESteps.None || _steps == ESteps.Done) @@ -140,10 +142,12 @@ namespace YooAsset } #endif } + /// protected override void InternalWaitForCompletion() { ExecuteBatch(); } + /// protected override string InternalGetDescription() { var assetInfo = _handle.GetAssetInfo(); diff --git a/Assets/YooAsset/Runtime/ResourceManager/Operations/UnloadAllAssetsOperation.cs b/Assets/YooAsset/Runtime/ResourceManager/Operations/UnloadAllAssetsOperation.cs index 27bc696b..277c529a 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Operations/UnloadAllAssetsOperation.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Operations/UnloadAllAssetsOperation.cs @@ -28,10 +28,12 @@ namespace YooAsset _resourceManager = resourceManager; _options = options; } + /// protected override void InternalStart() { _steps = ESteps.CheckOptions; } + /// protected override void InternalUpdate() { if (_steps == ESteps.None || _steps == ESteps.Done) diff --git a/Assets/YooAsset/Runtime/ResourceManager/Operations/UnloadSceneOperation.cs b/Assets/YooAsset/Runtime/ResourceManager/Operations/UnloadSceneOperation.cs index 34dbac79..c21c96ec 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Operations/UnloadSceneOperation.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Operations/UnloadSceneOperation.cs @@ -42,10 +42,12 @@ namespace YooAsset throw new YooInternalException($"Unexpected provider type: '{provider.GetType().Name}'."); } } + /// protected override void InternalStart() { _steps = ESteps.CheckError; } + /// protected override void InternalUpdate() { if (_steps == ESteps.None || _steps == ESteps.Done) @@ -106,6 +108,7 @@ namespace YooAsset SetResult(); } } + /// protected override string InternalGetDescription() { return $"SceneName: {_provider.LoadedSceneName}"; diff --git a/Assets/YooAsset/Runtime/ResourceManager/Operations/UnloadUnusedAssetsOperation.cs b/Assets/YooAsset/Runtime/ResourceManager/Operations/UnloadUnusedAssetsOperation.cs index d31f4ce5..241bd067 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Operations/UnloadUnusedAssetsOperation.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Operations/UnloadUnusedAssetsOperation.cs @@ -22,11 +22,13 @@ namespace YooAsset _resourceManager = resourceManager; _options = options; } + /// protected override void InternalStart() { _steps = ESteps.UnloadUnused; _loopCounter = _options.MaxLoopCount; } + /// protected override void InternalUpdate() { if (_steps == ESteps.None || _steps == ESteps.Done) @@ -51,10 +53,12 @@ namespace YooAsset } } } + /// protected override void InternalWaitForCompletion() { ExecuteBatch(); } + /// protected override string InternalGetDescription() { return $"MaxLoopCount: {_options.MaxLoopCount}"; diff --git a/Assets/YooAsset/Runtime/ResourcePackage/Operations/ClearCacheOperation.cs b/Assets/YooAsset/Runtime/ResourcePackage/Operations/ClearCacheOperation.cs index eb84031b..283f4bf2 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/Operations/ClearCacheOperation.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/Operations/ClearCacheOperation.cs @@ -28,10 +28,12 @@ namespace YooAsset _host = host; _options = options; } + /// protected override void InternalStart() { _steps = ESteps.Prepare; } + /// protected override void InternalUpdate() { if (_steps == ESteps.None || _steps == ESteps.Done) @@ -98,6 +100,7 @@ namespace YooAsset } } } + /// protected override string InternalGetDescription() { return $"ClearMethod: {_options.ClearMethod}"; diff --git a/Assets/YooAsset/Runtime/ResourcePackage/Operations/DestroyPackageOperation.cs b/Assets/YooAsset/Runtime/ResourcePackage/Operations/DestroyPackageOperation.cs index c0f88e92..300952c4 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/Operations/DestroyPackageOperation.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/Operations/DestroyPackageOperation.cs @@ -26,11 +26,12 @@ namespace YooAsset _resourcePackage = resourcePackage; _options = options; } - + /// protected override void InternalStart() { _steps = ESteps.CheckInitStatus; } + /// protected override void InternalUpdate() { if (_steps == ESteps.None || _steps == ESteps.Done) @@ -99,6 +100,7 @@ namespace YooAsset SetResult(); } } + /// protected override string InternalGetDescription() { return $"PackageVersion: {_resourcePackage.GetPackageVersion()}"; diff --git a/Assets/YooAsset/Runtime/ResourcePackage/Operations/DownloaderOperation.cs b/Assets/YooAsset/Runtime/ResourcePackage/Operations/DownloaderOperation.cs index 9d94a1d4..1841f162 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/Operations/DownloaderOperation.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/Operations/DownloaderOperation.cs @@ -6,7 +6,7 @@ namespace YooAsset /// /// 下载操作基类,提供资源下载、暂停、恢复和取消功能。 /// - public abstract class DownloaderOperation : AsyncOperationBase + public abstract partial class DownloaderOperation : AsyncOperationBase { private enum ESteps { @@ -99,11 +99,13 @@ namespace YooAsset // 统计下载信息 CalculateStatistics(); } + /// protected override void InternalStart() { YooLogger.Log($"Beginning download of {TotalDownloadCount} files ({TotalDownloadBytes} bytes)."); _steps = ESteps.Check; } + /// protected override void InternalUpdate() { if (_steps == ESteps.None || _steps == ESteps.Done) diff --git a/Assets/YooAsset/Runtime/ResourcePackage/Operations/InitializePackageOperation.cs b/Assets/YooAsset/Runtime/ResourcePackage/Operations/InitializePackageOperation.cs index c3b7123a..4db81d1e 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/Operations/InitializePackageOperation.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/Operations/InitializePackageOperation.cs @@ -29,10 +29,12 @@ namespace YooAsset _package = package; _options = options; } + /// protected override void InternalStart() { _steps = ESteps.SetPlayMode; } + /// protected override void InternalUpdate() { if (_steps == ESteps.None || _steps == ESteps.Done) @@ -137,6 +139,7 @@ namespace YooAsset } } } + /// protected override string InternalGetDescription() { return $"PlayMode: {_playMode}"; diff --git a/Assets/YooAsset/Runtime/ResourcePackage/Operations/InitializePackageOptions.cs b/Assets/YooAsset/Runtime/ResourcePackage/Operations/InitializePackageOptions.cs index fe744b09..c70597bc 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/Operations/InitializePackageOptions.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/Operations/InitializePackageOptions.cs @@ -7,8 +7,6 @@ namespace YooAsset /// public abstract class InitializePackageOptions { - protected InitializePackageOptions() { } - /// /// 同时加载Bundle文件的最大并发数 /// diff --git a/Assets/YooAsset/Runtime/ResourcePackage/Operations/Internal/InitializeFileSystemOperation.cs b/Assets/YooAsset/Runtime/ResourcePackage/Operations/Internal/InitializeFileSystemOperation.cs index 142e1e49..58aad6ac 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/Operations/Internal/InitializeFileSystemOperation.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/Operations/Internal/InitializeFileSystemOperation.cs @@ -28,10 +28,12 @@ namespace YooAsset _host = host; _parametersList = parametersList; } + /// protected override void InternalStart() { _steps = ESteps.Prepare; } + /// protected override void InternalUpdate() { if (_steps == ESteps.None || _steps == ESteps.Done) diff --git a/Assets/YooAsset/Runtime/ResourcePackage/Operations/LoadPackageManifestOperation.cs b/Assets/YooAsset/Runtime/ResourcePackage/Operations/LoadPackageManifestOperation.cs index 49b9e5b8..99087763 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/Operations/LoadPackageManifestOperation.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/Operations/LoadPackageManifestOperation.cs @@ -25,10 +25,12 @@ namespace YooAsset _host = host; _options = options; } + /// protected override void InternalStart() { _steps = ESteps.CheckParams; } + /// protected override void InternalUpdate() { if (_steps == ESteps.None || _steps == ESteps.Done) @@ -95,6 +97,7 @@ namespace YooAsset } } } + /// protected override string InternalGetDescription() { return $"PackageVersion: {_options.PackageVersion}"; diff --git a/Assets/YooAsset/Runtime/ResourcePackage/Operations/PrefetchManifestOperation.cs b/Assets/YooAsset/Runtime/ResourcePackage/Operations/PrefetchManifestOperation.cs index ee5639e3..be5159f9 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/Operations/PrefetchManifestOperation.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/Operations/PrefetchManifestOperation.cs @@ -30,10 +30,12 @@ namespace YooAsset _host = host; _options = options; } + /// protected override void InternalStart() { _steps = ESteps.CheckParams; } + /// protected override void InternalUpdate() { if (_steps == ESteps.None || _steps == ESteps.Done) diff --git a/Assets/YooAsset/Runtime/ResourcePackage/Operations/RequestPackageVersionOperation.cs b/Assets/YooAsset/Runtime/ResourcePackage/Operations/RequestPackageVersionOperation.cs index 7b0291c0..77511d8f 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/Operations/RequestPackageVersionOperation.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/Operations/RequestPackageVersionOperation.cs @@ -29,10 +29,12 @@ namespace YooAsset _host = host; _options = options; } + /// protected override void InternalStart() { _steps = ESteps.RequestPackageVersion; } + /// protected override void InternalUpdate() { if (_steps == ESteps.None || _steps == ESteps.Done) diff --git a/Assets/YooAsset/Runtime/ResourcePackage/PackageBundle.cs b/Assets/YooAsset/Runtime/ResourcePackage/PackageBundle.cs index 1c076685..90590c4c 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/PackageBundle.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/PackageBundle.cs @@ -72,11 +72,16 @@ namespace YooAsset /// [NonSerialized] public readonly List ReferrerBundleIDs = new List(10); + [NonSerialized] private readonly HashSet _referrerBundleIDs = new HashSet(); + [NonSerialized] private PackageManifest _manifest; + [NonSerialized] private bool _isInitialized; + [NonSerialized] private int _bundleType; + [NonSerialized] private string _fileName; @@ -166,6 +171,7 @@ namespace YooAsset } #region 调试信息 + [NonSerialized] private List _debugReferrerBundleNames; /// diff --git a/Assets/YooAsset/Runtime/ResourcePackage/PackageManifest.cs b/Assets/YooAsset/Runtime/ResourcePackage/PackageManifest.cs index e428189e..1cfa774c 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/PackageManifest.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/PackageManifest.cs @@ -401,7 +401,7 @@ namespace YooAsset /// /// 将资源GUID转换为资源信息 /// - /// 资源GUID + /// 资源GUID /// 资源类型 /// 返回资源信息对象,如果转换失败会返回一个无效的资源信息。 public AssetInfo ConvertAssetGuidToAssetInfo(string assetGuid, System.Type assetType) diff --git a/Assets/YooAsset/Runtime/ResourcePackage/ResourcePackage.cs b/Assets/YooAsset/Runtime/ResourcePackage/ResourcePackage.cs index 05e26f55..57459511 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/ResourcePackage.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/ResourcePackage.cs @@ -9,7 +9,7 @@ namespace YooAsset /// /// 资源包裹类 /// - public class ResourcePackage + public partial class ResourcePackage { private InitializePackageOperation _initializeOp; private ResourceManager _resourceManager; diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/Test.meta b/Assets/YooAsset/Samples~/Extension Sample/Editor/AssetReference.meta similarity index 77% rename from Assets/YooAsset/Samples~/Mini Game/Runtime/Test.meta rename to Assets/YooAsset/Samples~/Extension Sample/Editor/AssetReference.meta index 941ef797..be8d6749 100644 --- a/Assets/YooAsset/Samples~/Mini Game/Runtime/Test.meta +++ b/Assets/YooAsset/Samples~/Extension Sample/Editor/AssetReference.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: cda191ef75dc59f408545d8f7d3644b0 +guid: 682ac5046f4686946b0003a449638651 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Assets/YooAsset/Samples~/Extension Sample/Editor/AssetReference/GameObjectReferenceDrawer.cs b/Assets/YooAsset/Samples~/Extension Sample/Editor/AssetReference/GameObjectReferenceDrawer.cs new file mode 100644 index 00000000..a7bd5581 --- /dev/null +++ b/Assets/YooAsset/Samples~/Extension Sample/Editor/AssetReference/GameObjectReferenceDrawer.cs @@ -0,0 +1,61 @@ +using UnityEngine; +using UnityEditor; + +[CustomPropertyDrawer(typeof(GameObjectReference))] +public class GameObjectReferenceDrawer : PropertyDrawer +{ + private const float LineSpacing = 2f; + + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + SerializedProperty packageNameProp = property.FindPropertyRelative("_packageName"); + SerializedProperty assetGUIDProp = property.FindPropertyRelative("_assetGUID"); + + EditorGUI.BeginProperty(position, label, property); + { + float lineHeight = EditorGUIUtility.singleLineHeight; + Rect line = new Rect(position.x, position.y, position.width, lineHeight); + + // 绘制 PackageName + packageNameProp.stringValue = EditorGUI.TextField(line, "Package Name", packageNameProp.stringValue); + + // 加载 GameObject + string assetGUID = assetGUIDProp.stringValue; + GameObject current = null; + if (string.IsNullOrEmpty(assetGUID) == false) + { + string assetPath = AssetDatabase.GUIDToAssetPath(assetGUID); + if (string.IsNullOrEmpty(assetPath) == false) + current = AssetDatabase.LoadAssetAtPath(assetPath); + } + + // 绘制 GameObject + line.y += lineHeight + LineSpacing; + GameObject newAsset = (GameObject)EditorGUI.ObjectField(line, "Game Object", current, typeof(GameObject), false); + if (newAsset != current) + { + if (newAsset == null) + { + assetGUIDProp.stringValue = ""; + } + else + { + string newPath = AssetDatabase.GetAssetPath(newAsset); + if (string.IsNullOrEmpty(newPath) == false) + assetGUIDProp.stringValue = AssetDatabase.AssetPathToGUID(newPath); + } + } + + // 绘制 AssetGUID + line.y += lineHeight + LineSpacing; + EditorGUI.BeginDisabledGroup(true); + EditorGUI.TextField(line, "Asset GUID", assetGUIDProp.stringValue); + EditorGUI.EndDisabledGroup(); + } + EditorGUI.EndProperty(); + } + public override float GetPropertyHeight(SerializedProperty property, GUIContent label) + { + return EditorGUIUtility.singleLineHeight * 3 + LineSpacing * 2; + } +} diff --git a/Assets/YooAsset/Samples~/Extension Sample/Editor/AssetReference/GameObjectReferenceDrawer.cs.meta b/Assets/YooAsset/Samples~/Extension Sample/Editor/AssetReference/GameObjectReferenceDrawer.cs.meta new file mode 100644 index 00000000..e47ae1b3 --- /dev/null +++ b/Assets/YooAsset/Samples~/Extension Sample/Editor/AssetReference/GameObjectReferenceDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 53eb285fc3a7b614089a000f8c9c738c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/YooAsset/Samples~/Extension Sample/Editor/ClearBuildCache/ClearBuildCache.cs b/Assets/YooAsset/Samples~/Extension Sample/Editor/ClearBuildCache/ClearBuildCache.cs index d4fffd95..54eda403 100644 --- a/Assets/YooAsset/Samples~/Extension Sample/Editor/ClearBuildCache/ClearBuildCache.cs +++ b/Assets/YooAsset/Samples~/Extension Sample/Editor/ClearBuildCache/ClearBuildCache.cs @@ -1,17 +1,31 @@ -using System; +using System; using System.IO; using UnityEditor; using UnityEngine; namespace YooAsset.Editor { + /// + /// 提供构建缓存清理菜单入口 + /// internal class ClearBuildCacheWindow { + private const string SBPEditorAssemblyName = "Unity.ScriptableBuildPipeline.Editor"; + private const string SBPBuildCacheTypeName = "UnityEditor.Build.Pipeline.Utilities.BuildCache"; + [MenuItem("Tools/Clear Build Cache", false, 2)] public static void OpenWindow() { // 清空SBP构建缓存 - UnityEditor.Build.Pipeline.Utilities.BuildCache.PurgeCache(false); + var buildCacheType = Type.GetType($"{SBPBuildCacheTypeName}, {SBPEditorAssemblyName}"); + if (buildCacheType != null) + { + EditorAssemblyUtility.InvokePublicStaticMethod(buildCacheType, "PurgeCache", false); + } + else + { + Debug.LogWarning($"Failed to find type: {SBPBuildCacheTypeName}"); + } // 删除AssetDependDB文件 string projectPath = YooAsset.Editor.EditorPathUtility.GetProjectPath(); @@ -20,6 +34,8 @@ namespace YooAsset.Editor { File.Delete(databaseFilePath); } + + Debug.Log("Clear build cache succeeded !"); } } } \ No newline at end of file diff --git a/Assets/YooAsset/Samples~/Extension Sample/Editor/CreateBuildinCatalog.meta b/Assets/YooAsset/Samples~/Extension Sample/Editor/CreateBuiltinCatalog.meta similarity index 100% rename from Assets/YooAsset/Samples~/Extension Sample/Editor/CreateBuildinCatalog.meta rename to Assets/YooAsset/Samples~/Extension Sample/Editor/CreateBuiltinCatalog.meta diff --git a/Assets/YooAsset/Samples~/Extension Sample/Editor/CreateBuildinCatalog/CreateBuildinCatalogWindow.cs b/Assets/YooAsset/Samples~/Extension Sample/Editor/CreateBuiltinCatalog/CreateBuiltinCatalogWindow.cs similarity index 69% rename from Assets/YooAsset/Samples~/Extension Sample/Editor/CreateBuildinCatalog/CreateBuildinCatalogWindow.cs rename to Assets/YooAsset/Samples~/Extension Sample/Editor/CreateBuiltinCatalog/CreateBuiltinCatalogWindow.cs index d4ae39fd..68d28a70 100644 --- a/Assets/YooAsset/Samples~/Extension Sample/Editor/CreateBuildinCatalog/CreateBuildinCatalogWindow.cs +++ b/Assets/YooAsset/Samples~/Extension Sample/Editor/CreateBuiltinCatalog/CreateBuiltinCatalogWindow.cs @@ -1,4 +1,4 @@ -using System.IO; +using System.IO; using System.Collections.Generic; using System.Linq; using UnityEngine; @@ -6,16 +6,19 @@ using UnityEditor; namespace YooAsset.Editor { - public class CreateBuildinCatalogWindow : EditorWindow + /// + /// 提供内置资源清单生成工具窗口 + /// + public class CreateBuiltinCatalogWindow : EditorWindow { - static CreateBuildinCatalogWindow _thisInstance; + static CreateBuiltinCatalogWindow _thisInstance; - [MenuItem("Tools/内置清单生成工具(Catalog)", false, 101)] + [MenuItem("Tools/Builtin Catalog Generator", false, 101)] static void ShowWindow() { if (_thisInstance == null) { - _thisInstance = EditorWindow.GetWindow(typeof(CreateBuildinCatalogWindow), false, "内置清单生成工具", true) as CreateBuildinCatalogWindow; + _thisInstance = EditorWindow.GetWindow(typeof(CreateBuiltinCatalogWindow), false, "Builtin Catalog Generator", true) as CreateBuiltinCatalogWindow; _thisInstance.minSize = new Vector2(800, 600); } _thisInstance.Show(); @@ -27,7 +30,7 @@ namespace YooAsset.Editor { GUILayout.Space(10); EditorGUILayout.BeginHorizontal(); - if (GUILayout.Button("选择内置资源目录", GUILayout.MaxWidth(150))) + if (GUILayout.Button("Select Builtin Resource Directory", GUILayout.MaxWidth(150))) { string resultPath = EditorUtility.OpenFolderPanel("Find", "Assets/", "StreamingAssets"); if (!string.IsNullOrEmpty(resultPath)) @@ -38,7 +41,7 @@ namespace YooAsset.Editor if (string.IsNullOrEmpty(_directoryRoot) == false) { - if (GUILayout.Button("生成Catalog文件", GUILayout.MaxWidth(150))) + if (GUILayout.Button("Generate Catalog File", GUILayout.MaxWidth(150))) { CreateCatalogFile(_directoryRoot); } @@ -47,6 +50,13 @@ namespace YooAsset.Editor private void CreateCatalogFile(string directoryRoot) { + // 检查目录是否存在 + if (Directory.Exists(directoryRoot) == false) + { + Debug.LogError("Selected directory does not exist."); + return; + } + // 搜索所有Package目录 List packageRoots = GetPackageRoots(directoryRoot); foreach (var packageRoot in packageRoots) @@ -55,26 +65,20 @@ namespace YooAsset.Editor string packageName = directoryInfo.Name; try { - bool result = BuiltinCatalogHelper.CreateFile(null, packageName, packageRoot); //TODO 自行处理解密 + bool result = BuiltinCatalogHelper.CreateFile(null, packageName, packageRoot); // TODO: 根据业务需求处理清单解密。 if (result == false) { - Debug.LogError($"Create package {packageName} catalog file failed ! See the detail error in console !"); + Debug.LogError($"Failed to create a catalog file for package '{packageName}'. See Console for details."); } } catch (System.Exception ex) { - Debug.LogError($"Create package {packageName} catalog file failed ! {ex.Message}"); + Debug.LogError($"Failed to create a catalog file for package '{packageName}': {ex.Message}."); } } } private List GetPackageRoots(string rootPath) { - // 检查目录是否存在 - if (Directory.Exists(rootPath) == false) - { - throw new DirectoryNotFoundException($"目录不存在: {rootPath}"); - } - // 搜索所有 .version 文件(包含子目录) string[] versionFiles = Directory.GetFiles( rootPath, diff --git a/Assets/YooAsset/Samples~/Extension Sample/Editor/CreateBuildinCatalog/CreateBuildinCatalogWindow.cs.meta b/Assets/YooAsset/Samples~/Extension Sample/Editor/CreateBuiltinCatalog/CreateBuiltinCatalogWindow.cs.meta similarity index 100% rename from Assets/YooAsset/Samples~/Extension Sample/Editor/CreateBuildinCatalog/CreateBuildinCatalogWindow.cs.meta rename to Assets/YooAsset/Samples~/Extension Sample/Editor/CreateBuiltinCatalog/CreateBuiltinCatalogWindow.cs.meta diff --git a/Assets/YooAsset/Samples~/Extension Sample/Editor/CreateBuildinCatalog/CreateEmptyCatalogWindow.cs b/Assets/YooAsset/Samples~/Extension Sample/Editor/CreateBuiltinCatalog/CreateEmptyCatalogWindow.cs similarity index 71% rename from Assets/YooAsset/Samples~/Extension Sample/Editor/CreateBuildinCatalog/CreateEmptyCatalogWindow.cs rename to Assets/YooAsset/Samples~/Extension Sample/Editor/CreateBuiltinCatalog/CreateEmptyCatalogWindow.cs index c135a177..a6315b0f 100644 --- a/Assets/YooAsset/Samples~/Extension Sample/Editor/CreateBuildinCatalog/CreateEmptyCatalogWindow.cs +++ b/Assets/YooAsset/Samples~/Extension Sample/Editor/CreateBuiltinCatalog/CreateEmptyCatalogWindow.cs @@ -1,4 +1,4 @@ -using System.IO; +using System.IO; using System.Collections.Generic; using System.Linq; using UnityEngine; @@ -6,16 +6,19 @@ using UnityEditor; namespace YooAsset.Editor { + /// + /// 提供空资源清单生成工具窗口 + /// public class CreateEmptyCatalogWindow : EditorWindow { static CreateEmptyCatalogWindow _thisInstance; - [MenuItem("Tools/空清单生成工具(Catalog)", false, 102)] + [MenuItem("Tools/Empty Catalog Generator", false, 102)] static void ShowWindow() { if (_thisInstance == null) { - _thisInstance = EditorWindow.GetWindow(typeof(CreateEmptyCatalogWindow), false, "空清单生成工具", true) as CreateEmptyCatalogWindow; + _thisInstance = EditorWindow.GetWindow(typeof(CreateEmptyCatalogWindow), false, "Empty Catalog Generator", true) as CreateEmptyCatalogWindow; _thisInstance.minSize = new Vector2(800, 600); } _thisInstance.Show(); @@ -32,9 +35,9 @@ namespace YooAsset.Editor if (string.IsNullOrEmpty(_packageName) == false) { - if (GUILayout.Button("生成空的Catalog文件", GUILayout.MaxWidth(150))) + if (GUILayout.Button("Generate Empty Catalog File", GUILayout.MaxWidth(150))) { - string outputPath = EditorDialogUtility.OpenFolderPanel("输出目录", "Assets/"); + string outputPath = EditorDialogUtility.OpenFolderPanel("Output Directory", "Assets/"); if (string.IsNullOrEmpty(outputPath) == false) { CreateEmptyCatalogFile(outputPath); @@ -50,12 +53,12 @@ namespace YooAsset.Editor bool result = BuiltinCatalogHelper.CreateEmptyFile(_packageName, string.Empty, outputPath); if (result == false) { - Debug.LogError($"Create package {_packageName} catalog file failed ! See the detail error in console !"); + Debug.LogError($"Failed to create a catalog file for package '{_packageName}'. See Console for details."); } } catch (System.Exception ex) { - Debug.LogError($"Create package {_packageName} catalog file failed ! {ex.Message}"); + Debug.LogError($"Failed to create a catalog file for package '{_packageName}': {ex.Message}."); } } } diff --git a/Assets/YooAsset/Samples~/Extension Sample/Editor/CreateBuildinCatalog/CreateEmptyCatalogWindow.cs.meta b/Assets/YooAsset/Samples~/Extension Sample/Editor/CreateBuiltinCatalog/CreateEmptyCatalogWindow.cs.meta similarity index 100% rename from Assets/YooAsset/Samples~/Extension Sample/Editor/CreateBuildinCatalog/CreateEmptyCatalogWindow.cs.meta rename to Assets/YooAsset/Samples~/Extension Sample/Editor/CreateBuiltinCatalog/CreateEmptyCatalogWindow.cs.meta diff --git a/Assets/YooAsset/Samples~/Extension Sample/Editor/CustomBuildPipeline/CustomBuildPipelineViewer.cs b/Assets/YooAsset/Samples~/Extension Sample/Editor/CustomBuildPipeline/CustomBuildPipelineViewer.cs index 291f837d..bfed374c 100644 --- a/Assets/YooAsset/Samples~/Extension Sample/Editor/CustomBuildPipeline/CustomBuildPipelineViewer.cs +++ b/Assets/YooAsset/Samples~/Extension Sample/Editor/CustomBuildPipeline/CustomBuildPipelineViewer.cs @@ -8,6 +8,9 @@ using UnityEditor.UIElements; using UnityEngine.UIElements; using YooAsset.Editor; +/// +/// 提供自定义构建管线的编辑器视图 +/// [BuildPipelineAttribute("CustomBuildPipeline")] internal class CustomBuildPipelineViewer : LegacyBuildPipelineViewer { diff --git a/Assets/YooAsset/Samples~/Extension Sample/Editor/CustomCollectRules/CustomAddressRule.cs b/Assets/YooAsset/Samples~/Extension Sample/Editor/CustomCollectRules/CustomAddressRule.cs new file mode 100644 index 00000000..11ac10ca --- /dev/null +++ b/Assets/YooAsset/Samples~/Extension Sample/Editor/CustomCollectRules/CustomAddressRule.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using UnityEngine; +using YooAsset.Editor; + +/// +/// 按文件名生成资源定位地址 +/// +[DisplayName("定位地址: 文件名.智能尾缀")] +public class AddressByFileNameAndExt : IAddressRule +{ + /// + public string GetAssetAddress(AddressRuleData data) + { + var extension = Path.GetExtension(data.AssetPath); + if (extension == ".asset") + { + var asset = UnityEditor.AssetDatabase.LoadAssetAtPath(data.AssetPath); + if (asset == null) + throw new InvalidOperationException($"Asset not found: '{data.AssetPath}'."); + + var assetType = asset.GetType(); + var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(data.AssetPath); + return fileNameWithoutExtension + $".{assetType.Name.ToLowerInvariant()}"; + } + + return Path.GetFileName(data.AssetPath); + } +} \ No newline at end of file diff --git a/Assets/YooAsset/Samples~/Extension Sample/Editor/CustomCollectRules/CustomAdressRule.cs.meta b/Assets/YooAsset/Samples~/Extension Sample/Editor/CustomCollectRules/CustomAddressRule.cs.meta similarity index 100% rename from Assets/YooAsset/Samples~/Extension Sample/Editor/CustomCollectRules/CustomAdressRule.cs.meta rename to Assets/YooAsset/Samples~/Extension Sample/Editor/CustomCollectRules/CustomAddressRule.cs.meta diff --git a/Assets/YooAsset/Samples~/Extension Sample/Editor/CustomCollectRules/CustomAdressRule.cs b/Assets/YooAsset/Samples~/Extension Sample/Editor/CustomCollectRules/CustomAdressRule.cs deleted file mode 100644 index f848951d..00000000 --- a/Assets/YooAsset/Samples~/Extension Sample/Editor/CustomCollectRules/CustomAdressRule.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using UnityEngine; -using YooAsset.Editor; - -[DisplayName("定位地址: 文件名.智能尾缀")] -public class AddressByFileNameAndExt : IAddressRule -{ - public string GetAssetAddress(AddressRuleData data) - { - var ext = Path.GetExtension(data.AssetPath); - if (ext == ".asset") - { - var a = UnityEditor.AssetDatabase.LoadAssetAtPath(data.AssetPath); - if (a == null) return ".errortype"; - var type = a.GetType(); - var dt = Path.GetFileNameWithoutExtension(data.AssetPath); - return dt + $".{type.Name.ToLowerInvariant()}"; - } - - return Path.GetFileName(data.AssetPath); - } -} \ No newline at end of file diff --git a/Assets/YooAsset/Samples~/Extension Sample/Editor/CustomCollectRules/CustomPackRule.cs b/Assets/YooAsset/Samples~/Extension Sample/Editor/CustomCollectRules/CustomPackRule.cs index 84efeed7..52c60d2b 100644 --- a/Assets/YooAsset/Samples~/Extension Sample/Editor/CustomCollectRules/CustomPackRule.cs +++ b/Assets/YooAsset/Samples~/Extension Sample/Editor/CustomCollectRules/CustomPackRule.cs @@ -1,20 +1,24 @@ -using System; +using System; using System.Collections; using System.Collections.Generic; using System.IO; using UnityEngine; using YooAsset.Editor; +/// +/// 将特效纹理按首字符分组到资源包 +/// [DisplayName("打包特效纹理(自定义)")] public class PackEffectTexture : IBundlePackRule { private const string PackDirectory = "Assets/Effect/Textures/"; + /// BundlePackRuleResult IBundlePackRule.GetPackRuleResult(BundlePackRuleData data) { string assetPath = data.AssetPath; if (assetPath.StartsWith(PackDirectory) == false) - throw new Exception($"Only support folder : {PackDirectory}"); + throw new ArgumentException($"Only support folder: {PackDirectory}", nameof(data)); string assetName = Path.GetFileName(assetPath).ToLower(); string firstChar = assetName.Substring(0, 1); @@ -24,9 +28,13 @@ public class PackEffectTexture : IBundlePackRule } } +/// +/// 按视频资源路径生成原始文件资源包 +/// [DisplayName("打包视频(自定义)")] public class PackVideo : IBundlePackRule { + /// public BundlePackRuleResult GetPackRuleResult(BundlePackRuleData data) { string bundleName = RemoveExtension(data.AssetPath); diff --git a/Assets/YooAsset/Samples~/Extension Sample/Editor/MacroSupport/MacroDefine.cs b/Assets/YooAsset/Samples~/Extension Sample/Editor/MacroSupport/MacroDefine.cs index d3bd139c..eecaf01f 100644 --- a/Assets/YooAsset/Samples~/Extension Sample/Editor/MacroSupport/MacroDefine.cs +++ b/Assets/YooAsset/Samples~/Extension Sample/Editor/MacroSupport/MacroDefine.cs @@ -1,14 +1,17 @@ -using System.Collections.Generic; +using System.Collections.Generic; #if YOO_MACRO_SUPPORT namespace YooAsset.Editor { - public class MacroDefine + /// + /// 提供 YooAsset 版本相关的脚本宏定义 + /// + public static class MacroDefine { /// - /// YooAsset版本宏定义 + /// YooAsset 版本宏定义集合 /// - public static readonly List Macros = new List() + public static IReadOnlyList Macros { get; } = new List() { "YOO_ASSET_2", "YOO_ASSET_2_3", diff --git a/Assets/YooAsset/Samples~/Extension Sample/Editor/MacroSupport/MacroProcessor.cs b/Assets/YooAsset/Samples~/Extension Sample/Editor/MacroSupport/MacroProcessor.cs index 8337801f..2eff15cf 100644 --- a/Assets/YooAsset/Samples~/Extension Sample/Editor/MacroSupport/MacroProcessor.cs +++ b/Assets/YooAsset/Samples~/Extension Sample/Editor/MacroSupport/MacroProcessor.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; @@ -8,6 +8,9 @@ using UnityEditor; #if YOO_MACRO_SUPPORT namespace YooAsset.Editor { + /// + /// 在生成 C# 工程文件时注入 YooAsset 版本宏定义 + /// [InitializeOnLoad] public class MacroProcessor : AssetPostprocessor { @@ -41,7 +44,7 @@ namespace YooAsset.Editor } /// - /// 处理宏定义 + /// 处理工程文件中的宏定义 /// private static bool ProcessDefineConstants(XmlElement element) { @@ -76,7 +79,7 @@ namespace YooAsset.Editor } /// - /// 检测工程是否引用了YooAsset + /// 检查工程是否引用了 YooAsset /// private static bool IsCSProjectReferenced(XmlElement element) { @@ -93,7 +96,11 @@ namespace YooAsset.Editor if (childNode.Name != "Reference" && childNode.Name != "ProjectReference") continue; - string include = childNode.Attributes["Include"].Value; + XmlAttribute includeAttribute = childNode.Attributes["Include"]; + if (includeAttribute == null) + continue; + + string include = includeAttribute.Value; if (include.Contains("YooAsset")) return true; } diff --git a/Assets/YooAsset/Samples~/Extension Sample/Editor/MacroSupport/RspGenerator.cs b/Assets/YooAsset/Samples~/Extension Sample/Editor/MacroSupport/RspGenerator.cs index 42c66b51..0d4e1872 100644 --- a/Assets/YooAsset/Samples~/Extension Sample/Editor/MacroSupport/RspGenerator.cs +++ b/Assets/YooAsset/Samples~/Extension Sample/Editor/MacroSupport/RspGenerator.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; @@ -9,10 +9,13 @@ using UnityEngine; #if YOO_MACRO_SUPPORT namespace YooAsset.Editor.Experiment { + /// + /// 通过 csc.rsp 文件注入 YooAsset 版本宏定义 + /// [InitializeOnLoad] public class RspGenerator { - // csc.rsp文件路径 + // Unity 编译器响应文件路径 private static string RspFilePath => Path.Combine(Application.dataPath, "csc.rsp"); static RspGenerator() @@ -21,9 +24,9 @@ namespace YooAsset.Editor.Experiment } /// - /// 更新csc.rsp文件 + /// 更新 csc.rsp 文件 /// - private static void UpdateRspFile(List addMacros, List removeMacros) + private static void UpdateRspFile(IReadOnlyList addMacros, IReadOnlyList removeMacros) { var existingDefines = new HashSet(); var otherLines = new List(); @@ -34,24 +37,26 @@ namespace YooAsset.Editor.Experiment // 2. 添加新宏 if (addMacros != null && addMacros.Count > 0) { - addMacros.ForEach(x => + foreach (var x in addMacros) { if (existingDefines.Contains(x) == false) existingDefines.Add(x); - }); + } } // 3. 移除指定宏 if (removeMacros != null && removeMacros.Count > 0) { - removeMacros.ForEach(x => + foreach (var x in removeMacros) { existingDefines.Remove(x); - }); + } } // 4. 重新生成内容 - WriteRspFile(existingDefines, otherLines); + bool changed = WriteRspFile(existingDefines, otherLines); + if (changed == false) + return; // 5. 刷新AssetDatabase AssetDatabase.Refresh(); @@ -59,7 +64,7 @@ namespace YooAsset.Editor.Experiment } /// - /// 读取csc.rsp文件,返回宏定义和其他行 + /// 读取 csc.rsp 文件中的宏定义和其他行 /// private static void ReadRspFile(HashSet defines, List others) { @@ -90,9 +95,10 @@ namespace YooAsset.Editor.Experiment } /// - /// 重新写入csc.rsp文件 + /// 重新写入 csc.rsp 文件 /// - private static void WriteRspFile(HashSet defines, List others) + /// 文件内容发生变化时返回 true + private static bool WriteRspFile(HashSet defines, List others) { StringBuilder sb = new StringBuilder(); if (others != null && others.Count > 0) @@ -108,7 +114,16 @@ namespace YooAsset.Editor.Experiment } } - File.WriteAllText(RspFilePath, sb.ToString()); + string newContent = sb.ToString(); + if (File.Exists(RspFilePath)) + { + string oldContent = File.ReadAllText(RspFilePath); + if (oldContent == newContent) + return false; + } + + File.WriteAllText(RspFilePath, newContent); + return true; } } } diff --git a/Assets/YooAsset/Samples~/Extension Sample/Editor/PackageComparator/PackageComparatorWindow.cs b/Assets/YooAsset/Samples~/Extension Sample/Editor/PackageComparator/PackageComparatorWindow.cs index 2da5a7e9..e1fe18d9 100644 --- a/Assets/YooAsset/Samples~/Extension Sample/Editor/PackageComparator/PackageComparatorWindow.cs +++ b/Assets/YooAsset/Samples~/Extension Sample/Editor/PackageComparator/PackageComparatorWindow.cs @@ -1,4 +1,4 @@ -using System.IO; +using System.IO; using System.Collections.Generic; using System.Linq; using UnityEngine; @@ -6,16 +6,19 @@ using UnityEditor; namespace YooAsset.Editor { + /// + /// 提供补丁包差异比对工具窗口 + /// public class PackageComparatorWindow : EditorWindow { static PackageComparatorWindow _thisInstance; - [MenuItem("Tools/补丁包比对工具", false, 103)] + [MenuItem("Tools/Patch Package Comparator", false, 103)] static void ShowWindow() { if (_thisInstance == null) { - _thisInstance = EditorWindow.GetWindow(typeof(PackageComparatorWindow), false, "补丁包比对工具", true) as PackageComparatorWindow; + _thisInstance = EditorWindow.GetWindow(typeof(PackageComparatorWindow), false, "Patch Package Comparator", true) as PackageComparatorWindow; _thisInstance.minSize = new Vector2(800, 600); } _thisInstance.Show(); @@ -32,7 +35,7 @@ namespace YooAsset.Editor { GUILayout.Space(10); EditorGUILayout.BeginHorizontal(); - if (GUILayout.Button("选择补丁包1", GUILayout.MaxWidth(150))) + if (GUILayout.Button("Select Patch Package 1", GUILayout.MaxWidth(150))) { string resultPath = EditorUtility.OpenFilePanel("Find", "Assets/", "bytes"); if (string.IsNullOrEmpty(resultPath)) @@ -44,7 +47,7 @@ namespace YooAsset.Editor GUILayout.Space(10); EditorGUILayout.BeginHorizontal(); - if (GUILayout.Button("选择补丁包2", GUILayout.MaxWidth(150))) + if (GUILayout.Button("Select Patch Package 2", GUILayout.MaxWidth(150))) { string resultPath = EditorUtility.OpenFilePanel("Find", "Assets/", "bytes"); if (string.IsNullOrEmpty(resultPath)) @@ -56,9 +59,18 @@ namespace YooAsset.Editor if (string.IsNullOrEmpty(_manifestPath1) == false && string.IsNullOrEmpty(_manifestPath2) == false) { - if (GUILayout.Button("比对差异", GUILayout.MaxWidth(150))) + if (GUILayout.Button("Compare Differences", GUILayout.MaxWidth(150))) { - ComparePackage(_changeList, _newList); + try + { + ComparePackage(_changeList, _newList); + } + catch (System.Exception ex) + { + _changeList.Clear(); + _newList.Clear(); + Debug.LogError($"Failed to compare patch packages: {ex.Message}."); + } } } @@ -66,7 +78,7 @@ namespace YooAsset.Editor using (new EditorGUI.DisabledScope(false)) { int totalCount = _changeList.Count; - EditorGUILayout.Foldout(true, $"差异列表 ( {totalCount} )"); + EditorGUILayout.Foldout(true, $"Changed Bundles ( {totalCount} )"); EditorGUI.indentLevel = 1; _scrollPos1 = EditorGUILayout.BeginScrollView(_scrollPos1); @@ -84,7 +96,7 @@ namespace YooAsset.Editor using (new EditorGUI.DisabledScope(false)) { int totalCount = _newList.Count; - EditorGUILayout.Foldout(true, $"新增列表 ( {totalCount} )"); + EditorGUILayout.Foldout(true, $"New Bundles ( {totalCount} )"); EditorGUI.indentLevel = 1; _scrollPos2 = EditorGUILayout.BeginScrollView(_scrollPos2); @@ -104,13 +116,13 @@ namespace YooAsset.Editor changeList.Clear(); newList.Clear(); - // 加载补丁清单1 + // 加载基准补丁清单 byte[] bytesData1 = FileUtility.ReadAllBytes(_manifestPath1); - PackageManifest manifest1 = PackageManifestHelper.DeserializeManifestFromBinary(bytesData1, null); //TODO 自行处理解密 + PackageManifest manifest1 = PackageManifestHelper.DeserializeManifestFromBinary(bytesData1, null); // TODO: 根据业务需求处理清单解密。 - // 加载补丁清单1 + // 加载待比对补丁清单 byte[] bytesData2 = FileUtility.ReadAllBytes(_manifestPath2); - PackageManifest manifest2 = PackageManifestHelper.DeserializeManifestFromBinary(bytesData2, null); //TODO 自行处理解密 + PackageManifest manifest2 = PackageManifestHelper.DeserializeManifestFromBinary(bytesData2, null); // TODO: 根据业务需求处理清单解密。 // 拷贝文件列表 foreach (var bundle2 in manifest2.BundleList) @@ -132,7 +144,7 @@ namespace YooAsset.Editor changeList.Sort((x, y) => string.Compare(x.BundleName, y.BundleName)); newList.Sort((x, y) => string.Compare(x.BundleName, y.BundleName)); - Debug.Log("资源包差异比对完成!"); + Debug.Log("Package comparison completed."); } } } diff --git a/Assets/YooAsset/Samples~/Extension Sample/Editor/PackageImporter/PackageImporterWindow.cs b/Assets/YooAsset/Samples~/Extension Sample/Editor/PackageImporter/PackageImporterWindow.cs index b45a086e..16ae8f67 100644 --- a/Assets/YooAsset/Samples~/Extension Sample/Editor/PackageImporter/PackageImporterWindow.cs +++ b/Assets/YooAsset/Samples~/Extension Sample/Editor/PackageImporter/PackageImporterWindow.cs @@ -4,16 +4,19 @@ using UnityEditor; namespace YooAsset.Editor { + /// + /// 提供补丁包导入工具窗口 + /// public class PackageImporterWindow : EditorWindow { static PackageImporterWindow _thisInstance; - [MenuItem("Tools/补丁包导入工具", false, 104)] + [MenuItem("Tools/Patch Package Importer", false, 104)] static void ShowWindow() { if (_thisInstance == null) { - _thisInstance = EditorWindow.GetWindow(typeof(PackageImporterWindow), false, "补丁包导入工具", true) as PackageImporterWindow; + _thisInstance = EditorWindow.GetWindow(typeof(PackageImporterWindow), false, "Patch Package Importer", true) as PackageImporterWindow; _thisInstance.minSize = new Vector2(800, 600); } _thisInstance.Show(); @@ -26,7 +29,12 @@ namespace YooAsset.Editor { GUILayout.Space(10); EditorGUILayout.BeginHorizontal(); - if (GUILayout.Button("选择补丁包", GUILayout.MaxWidth(150))) + _packageName = EditorGUILayout.TextField("Package Name", _packageName); + EditorGUILayout.EndHorizontal(); + + GUILayout.Space(10); + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button("Select Patch Package", GUILayout.MaxWidth(150))) { string resultPath = EditorUtility.OpenFilePanel("Find", "Assets/", "bytes"); if (!string.IsNullOrEmpty(resultPath)) @@ -37,54 +45,84 @@ namespace YooAsset.Editor if (string.IsNullOrEmpty(_manifestPath) == false) { - if (GUILayout.Button("导入补丁包(全部文件)", GUILayout.MaxWidth(150))) + if (GUILayout.Button("Import Patch Package (All Files)", GUILayout.MaxWidth(150))) { - string streamingAssetsRoot = BundleBuilderHelper.GetStreamingAssetsRoot(); - EditorFileUtility.ClearFolder(streamingAssetsRoot); - CopyPackageFiles(_manifestPath); + if (string.IsNullOrEmpty(_packageName)) + { + Debug.LogError("Package name is empty."); + return; + } + + try + { + CopyPackageFiles(_manifestPath); + } + catch (System.Exception ex) + { + Debug.LogError($"Failed to import patch package '{_packageName}': {ex.Message}."); + } + finally + { + AssetDatabase.Refresh(); + } } } } private void CopyPackageFiles(string manifestFilePath) { - string manifestFileName = Path.GetFileNameWithoutExtension(manifestFilePath); - string outputDirectory = Path.GetDirectoryName(manifestFilePath); + string sourceRoot = Path.GetDirectoryName(manifestFilePath); + if (string.IsNullOrEmpty(sourceRoot)) + throw new DirectoryNotFoundException("Patch package directory does not exist."); + + string versionFileName = YooAssetConfiguration.GetPackageVersionFileName(_packageName); + string versionSourcePath = Path.Combine(sourceRoot, versionFileName); + string packageVersion = File.ReadAllText(versionSourcePath).Trim(); + string manifestFileName = YooAssetConfiguration.GetManifestBinaryFileName(_packageName, packageVersion); + string hashFileName = YooAssetConfiguration.GetPackageHashFileName(_packageName, packageVersion); + string selectedFileName = Path.GetFileName(manifestFilePath); + if (selectedFileName != manifestFileName) + throw new InvalidDataException($"Selected manifest file '{selectedFileName}' does not match expected manifest file '{manifestFileName}'."); + + string destRoot = Path.Combine(BundleBuilderHelper.GetStreamingAssetsRoot(), _packageName); + + // 清空旧目录 + EditorFileUtility.DeleteDirectory(destRoot); + EditorFileUtility.CreateDirectory(destRoot); // 拷贝核心文件 { - string sourcePath = $"{outputDirectory}/{manifestFileName}.bytes"; - string destPath = $"{BundleBuilderHelper.GetStreamingAssetsRoot()}/{_packageName}/{manifestFileName}.bytes"; + string sourcePath = Path.Combine(sourceRoot, manifestFileName); + string destPath = Path.Combine(destRoot, manifestFileName); EditorFileUtility.CopyFile(sourcePath, destPath, true); } { - string sourcePath = $"{outputDirectory}/{manifestFileName}.hash"; - string destPath = $"{BundleBuilderHelper.GetStreamingAssetsRoot()}/{_packageName}/{manifestFileName}.hash"; + string sourcePath = Path.Combine(sourceRoot, hashFileName); + string destPath = Path.Combine(destRoot, hashFileName); EditorFileUtility.CopyFile(sourcePath, destPath, true); } { - string fileName = YooAssetConfiguration.GetPackageVersionFileName(_packageName); - string sourcePath = $"{outputDirectory}/{fileName}"; - string destPath = $"{BundleBuilderHelper.GetStreamingAssetsRoot()}/{_packageName}/{fileName}"; + string sourcePath = versionSourcePath; + string destPath = Path.Combine(destRoot, versionFileName); EditorFileUtility.CopyFile(sourcePath, destPath, true); } // 加载补丁清单 byte[] bytesData = FileUtility.ReadAllBytes(manifestFilePath); - PackageManifest manifest = PackageManifestHelper.DeserializeManifestFromBinary(bytesData, null); //TODO 自行处理解密 + PackageManifest manifest = PackageManifestHelper.DeserializeManifestFromBinary(bytesData, null); // TODO: 根据业务需求处理清单解密。 // 拷贝文件列表 int fileCount = 0; foreach (var packageBundle in manifest.BundleList) { fileCount++; - string sourcePath = $"{outputDirectory}/{packageBundle.GetFileName()}"; - string destPath = $"{BundleBuilderHelper.GetStreamingAssetsRoot()}/{_packageName}/{packageBundle.GetFileName()}"; + string fileName = packageBundle.GetFileName(); + string sourcePath = Path.Combine(sourceRoot, fileName); + string destPath = Path.Combine(destRoot, fileName); EditorFileUtility.CopyFile(sourcePath, destPath, true); } - Debug.Log($"补丁包拷贝完成,一共拷贝了{fileCount}个资源文件"); - AssetDatabase.Refresh(); + Debug.Log($"Patch package copy completed. Copied {fileCount} bundle files."); } } } \ No newline at end of file diff --git a/Assets/YooAsset/Samples~/Extension Sample/Editor/PreprocessBuild/PreprocessBuildCatalog.cs b/Assets/YooAsset/Samples~/Extension Sample/Editor/PreprocessBuild/PreprocessBuildCatalog.cs index bbf2a6d8..238459bb 100644 --- a/Assets/YooAsset/Samples~/Extension Sample/Editor/PreprocessBuild/PreprocessBuildCatalog.cs +++ b/Assets/YooAsset/Samples~/Extension Sample/Editor/PreprocessBuild/PreprocessBuildCatalog.cs @@ -5,23 +5,26 @@ using YooAsset.Editor; namespace YooAsset { + /// + /// 在应用构建前生成内置资源清单 + /// public class PreprocessBuildCatalog : UnityEditor.Build.IPreprocessBuildWithReport { + /// + /// 构建预处理回调顺序 + /// public int callbackOrder { get { return 0; } } - /// - /// 在构建应用程序前自动生成内置资源目录文件。 - /// 原理:搜索StreamingAssets目录下的所有资源文件,将这些文件信息写入文件,然后在运行时做查询用途。 - /// + /// public void OnPreprocessBuild(UnityEditor.Build.Reporting.BuildReport report) { - YooLogger.Log("Begin to create catalog file !"); + YooLogger.Log("Starting catalog file generation."); string rootPath = BundleBuilderHelper.GetStreamingAssetsRoot(); DirectoryInfo rootDirectory = new DirectoryInfo(rootPath); if (rootDirectory.Exists == false) { - Debug.LogWarning($"Can not found StreamingAssets root directory : {rootPath}"); + Debug.LogWarning("StreamingAssets root directory does not exist."); return; } @@ -30,18 +33,18 @@ namespace YooAsset foreach (var subDirectory in subDirectories) { string packageName = subDirectory.Name; - string pacakgeDirectory = subDirectory.FullName; + string packageDirectory = subDirectory.FullName; try { - bool result = BuiltinCatalogHelper.CreateFile(null, packageName, pacakgeDirectory); //TODO 自行处理解密 + bool result = BuiltinCatalogHelper.CreateFile(null, packageName, packageDirectory); // TODO: 根据业务需求处理清单解密。 if (result == false) { - Debug.LogError($"Create package {packageName} catalog file failed ! See the detail error in console !"); + Debug.LogError($"Failed to create a catalog file for package '{packageName}'. See Console for details."); } } catch (System.Exception ex) { - Debug.LogError($"Create package {packageName} catalog file failed ! {ex.Message}"); + Debug.LogError($"Failed to create a catalog file for package '{packageName}': {ex.Message}."); } } } diff --git a/Assets/YooAsset/Samples~/Extension Sample/Editor/ShaderVariantCollector/ShaderVariantCollectionHelper.cs b/Assets/YooAsset/Samples~/Extension Sample/Editor/ShaderVariantCollector/ShaderVariantCollectionHelper.cs index 6650922c..98644572 100644 --- a/Assets/YooAsset/Samples~/Extension Sample/Editor/ShaderVariantCollector/ShaderVariantCollectionHelper.cs +++ b/Assets/YooAsset/Samples~/Extension Sample/Editor/ShaderVariantCollector/ShaderVariantCollectionHelper.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; @@ -7,28 +7,51 @@ using UnityEngine.Rendering; using UnityEditor; using YooAsset.Editor; +/// +/// 封装 Unity 编辑器中的 ShaderVariantCollection 反射调用 +/// public static class ShaderVariantCollectionHelper { + /// + /// 清空当前编辑器记录的着色器变种集合 + /// public static void ClearCurrentShaderVariantCollection() { EditorAssemblyUtility.InvokeNonPublicStaticMethod(typeof(ShaderUtil), "ClearCurrentShaderVariantCollection"); } + + /// + /// 保存当前编辑器记录的着色器变种集合 + /// + /// 保存目标路径 public static void SaveCurrentShaderVariantCollection(string savePath) { EditorAssemblyUtility.InvokeNonPublicStaticMethod(typeof(ShaderUtil), "SaveCurrentShaderVariantCollection", savePath); } + + /// + /// 当前着色器变种集合中的着色器数量 + /// + /// 着色器数量 public static int GetCurrentShaderVariantCollectionShaderCount() { return (int)EditorAssemblyUtility.InvokeNonPublicStaticMethod(typeof(ShaderUtil), "GetCurrentShaderVariantCollectionShaderCount"); } + + /// + /// 当前着色器变种集合中的变种数量 + /// + /// 变种数量 public static int GetCurrentShaderVariantCollectionVariantCount() { return (int)EditorAssemblyUtility.InvokeNonPublicStaticMethod(typeof(ShaderUtil), "GetCurrentShaderVariantCollectionVariantCount"); } /// - /// 获取着色器的变种总数量 + /// 获取指定着色器资源的变种总数量 /// + /// 着色器资源路径 + /// 变种总数量的字符串表示 public static string GetShaderVariantCount(string assetPath) { Shader shader = AssetDatabase.LoadAssetAtPath(assetPath); diff --git a/Assets/YooAsset/Samples~/Extension Sample/Editor/ShaderVariantCollector/ShaderVariantCollectionManifest.cs b/Assets/YooAsset/Samples~/Extension Sample/Editor/ShaderVariantCollector/ShaderVariantCollectionManifest.cs index 7175ce2a..71bd5775 100644 --- a/Assets/YooAsset/Samples~/Extension Sample/Editor/ShaderVariantCollector/ShaderVariantCollectionManifest.cs +++ b/Assets/YooAsset/Samples~/Extension Sample/Editor/ShaderVariantCollector/ShaderVariantCollectionManifest.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; @@ -7,50 +7,70 @@ using UnityEngine; using UnityEngine.Rendering; using UnityEditor; +/// +/// 着色器变种集合的可序列化清单 +/// [Serializable] public class ShaderVariantCollectionManifest { + /// + /// 单个着色器变种的序列化信息 + /// [Serializable] public class ShaderVariantElement : IComparable { + /// + /// 用于稳定排序的组合键 + /// public string SortValue { private set; get; } /// - /// Pass type to use in this variant. + /// 变种使用的渲染通道类型 /// public PassType PassType; /// - /// Array of shader keywords to use in this variant. + /// 变种使用的着色器关键字数组 /// public string[] Keywords; + /// + /// 生成排序键 + /// public void MakeSortValue() { string combineKeyword = string.Empty; for (int i = 0; i < Keywords.Length; i++) { if (i == 0) - combineKeyword = Keywords[0]; + combineKeyword = Keywords[i]; else - combineKeyword = $"{combineKeyword}+{Keywords[0]}"; + combineKeyword = $"{combineKeyword}+{Keywords[i]}"; } SortValue = $"{PassType}+{combineKeyword}"; } + + /// public int CompareTo(ShaderVariantElement other) { return SortValue.CompareTo(other.SortValue); } } + /// + /// 单个着色器及其变种列表的序列化信息 + /// [Serializable] public class ShaderVariantInfo : IComparable { + /// + /// 用于稳定排序的组合键 + /// public string SortValue { private set; get; } /// - /// 着色器资源路径. + /// 着色器资源路径 /// public string AssetPath; @@ -69,10 +89,15 @@ public class ShaderVariantCollectionManifest /// public List ShaderVariantElements = new List(1000); + /// + /// 生成排序键 + /// public void MakeSortValue() { SortValue = AssetPath + "+" + ShaderName; } + + /// public int CompareTo(ShaderVariantInfo other) { return SortValue.CompareTo(other.SortValue); @@ -81,33 +106,36 @@ public class ShaderVariantCollectionManifest /// - /// Number of shaders in this collection + /// 清单中的着色器总数 /// public int ShaderTotalCount; /// - /// Number of total varians in this collection + /// 清单中的变种总数 /// public int VariantTotalCount; /// - /// Shader variants info list. + /// 着色器变种信息列表 /// public List ShaderVariantInfos = new List(1000); /// /// 添加着色器变种信息 /// + /// 着色器资源路径 + /// 着色器名称 + /// 渲染通道类型 + /// 着色器关键字数组 public void AddShaderVariant(string assetPath, string shaderName, PassType passType, string[] keywords) { - // 排序Keyword列表 - List temper = new List(keywords); - temper.Sort(); + List sortedKeywords = new List(keywords); + sortedKeywords.Sort(); var info = GetOrCreateShaderVariantInfo(assetPath, shaderName); ShaderVariantElement element = new ShaderVariantElement(); element.PassType = passType; - element.Keywords = temper.ToArray(); + element.Keywords = sortedKeywords.ToArray(); element.MakeSortValue(); info.ShaderVariantElements.Add(element); info.ShaderVariantCount++; @@ -126,20 +154,22 @@ public class ShaderVariantCollectionManifest } if (selectList.Count != 1) - throw new Exception("Should never get here !"); + throw new InvalidOperationException($"Unexpected duplicate ShaderVariantInfo entries (count={selectList.Count})."); return selectList[0]; } - /// - /// 解析SVC文件并将数据写入到清单 + /// 从 ShaderVariantCollection 提取清单数据 /// + /// 待解析的着色器变种集合 + /// 提取后的着色器变种清单 public static ShaderVariantCollectionManifest Extract(ShaderVariantCollection svc) { + if (svc == null) + throw new ArgumentNullException(nameof(svc)); + var manifest = new ShaderVariantCollectionManifest(); - manifest.ShaderTotalCount = ShaderVariantCollectionHelper.GetCurrentShaderVariantCollectionShaderCount(); - manifest.VariantTotalCount = ShaderVariantCollectionHelper.GetCurrentShaderVariantCollectionVariantCount(); using (var so = new SerializedObject(svc)) { @@ -149,30 +179,23 @@ public class ShaderVariantCollectionManifest for (int i = 0; i < shaderArray.arraySize; ++i) { var shaderRef = shaderArray.FindPropertyRelative($"data[{i}].first"); + var shader = shaderRef.objectReferenceValue as Shader; + if (shader == null) + throw new InvalidOperationException("Invalid shader in ShaderVariantCollection file."); + + string shaderAssetPath = AssetDatabase.GetAssetPath(shader); + string shaderName = shader.name; + + // 添加变种信息 var shaderVariantsArray = shaderArray.FindPropertyRelative($"data[{i}].second.variants"); - if (shaderRef != null && shaderRef.propertyType == SerializedPropertyType.ObjectReference && shaderVariantsArray != null && shaderVariantsArray.isArray) + for (int j = 0; j < shaderVariantsArray.arraySize; ++j) { - var shader = shaderRef.objectReferenceValue as Shader; - if (shader == null) - { - throw new Exception("Invalid shader in ShaderVariantCollection file."); - } + var propKeywords = shaderVariantsArray.FindPropertyRelative($"Array.data[{j}].keywords"); + var propPassType = shaderVariantsArray.FindPropertyRelative($"Array.data[{j}].passType"); - string shaderAssetPath = AssetDatabase.GetAssetPath(shader); - string shaderName = shader.name; - - // 添加变种信息 - for (int j = 0; j < shaderVariantsArray.arraySize; ++j) - { - var propKeywords = shaderVariantsArray.FindPropertyRelative($"Array.data[{j}].keywords"); - var propPassType = shaderVariantsArray.FindPropertyRelative($"Array.data[{j}].passType"); - if (propKeywords != null && propPassType != null && propKeywords.propertyType == SerializedPropertyType.String) - { - string[] keywords = propKeywords.stringValue.Split(' '); - PassType pathType = (PassType)propPassType.intValue; - manifest.AddShaderVariant(shaderAssetPath, shaderName, pathType, keywords); - } - } + string[] keywords = propKeywords.stringValue.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); + PassType passType = (PassType)propPassType.intValue; + manifest.AddShaderVariant(shaderAssetPath, shaderName, passType, keywords); } } } @@ -185,6 +208,13 @@ public class ShaderVariantCollectionManifest shaderVariantInfo.ShaderVariantElements.Sort(); } + // 统计数量 + foreach (var shaderVariantInfo in manifest.ShaderVariantInfos) + { + manifest.VariantTotalCount += shaderVariantInfo.ShaderVariantElements.Count; + } + manifest.ShaderTotalCount = manifest.ShaderVariantInfos.Count; + return manifest; } } \ No newline at end of file diff --git a/Assets/YooAsset/Samples~/Extension Sample/Editor/ShaderVariantCollector/ShaderVariantCollector.cs b/Assets/YooAsset/Samples~/Extension Sample/Editor/ShaderVariantCollector/ShaderVariantCollector.cs index 127dfe5d..e2b22cb2 100644 --- a/Assets/YooAsset/Samples~/Extension Sample/Editor/ShaderVariantCollector/ShaderVariantCollector.cs +++ b/Assets/YooAsset/Samples~/Extension Sample/Editor/ShaderVariantCollector/ShaderVariantCollector.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; @@ -8,6 +8,9 @@ using UnityEditor; using UnityEditor.SceneManagement; using YooAsset.Editor; +/// +/// 收集资源包裹中材质产生的着色器变种 +/// public static class ShaderVariantCollector { private enum ESteps @@ -34,21 +37,33 @@ public static class ShaderVariantCollector /// - /// 开始收集 + /// 启动着色器变种收集流程 /// + /// 收集结果保存路径,扩展名必须为 .shadervariants。 + /// 参与收集的资源包裹名称 + /// 每批处理的材质数量 + /// 收集完成后的回调 public static void Run(string savePath, string packageName, int processMaxNum, Action completedCallback) { if (_steps != ESteps.None) return; + if (EditorSceneUtility.HasDirtyScenes()) + { + UnityEngine.Debug.LogError("Unsaved scenes detected. Save all scenes before collecting shader variants."); + return; + } + if (Path.HasExtension(savePath) == false) savePath = $"{savePath}.shadervariants"; if (Path.GetExtension(savePath) != ".shadervariants") - throw new System.Exception("Shader variant file extension is invalid."); + throw new System.ArgumentException("Shader variant file extension is invalid.", nameof(savePath)); if (string.IsNullOrEmpty(packageName)) - throw new System.Exception("Package name is null or empty !"); + throw new System.ArgumentNullException(nameof(packageName)); + if (processMaxNum <= 0) + throw new System.ArgumentOutOfRangeException(nameof(processMaxNum), "Process capacity must be greater than zero."); - // 注意:先删除再保存,否则ShaderVariantCollection内容将无法及时刷新 + // Unity 对同名 ShaderVariantCollection 的刷新存在延迟,先删除旧资源再写入新结果。 AssetDatabase.DeleteAsset(savePath); EditorFileUtility.CreateFileDirectory(savePath); _savePath = savePath; @@ -67,6 +82,17 @@ public static class ShaderVariantCollector } private static void EditorUpdate() + { + try + { + InternalUpdate(); + } + catch (Exception ex) + { + Finish(false, ex); + } + } + private static void InternalUpdate() { if (_steps == ESteps.None) return; @@ -75,14 +101,14 @@ public static class ShaderVariantCollector { ShaderVariantCollectionHelper.ClearCurrentShaderVariantCollection(); _steps = ESteps.CollectAllMaterial; - return; //等待一帧 + return; // 等待一帧,让编辑器完成清理。 } if (_steps == ESteps.CollectAllMaterial) { _allMaterials = GetAllMaterials(); _steps = ESteps.CollectVariants; - return; //等待一帧 + return; // 等待一帧,让材质列表收集结果稳定。 } if (_steps == ESteps.CollectVariants) @@ -119,7 +145,7 @@ public static class ShaderVariantCollector if (_steps == ESteps.WaitingDone) { - // 注意:一定要延迟保存才会起效 + // Unity 需要等待若干帧后才能把当前变种集合写入资源文件。 if (_elapsedTime.ElapsedMilliseconds > WaitMilliseconds) { _elapsedTime.Stop(); @@ -129,9 +155,7 @@ public static class ShaderVariantCollector ShaderVariantCollectionHelper.SaveCurrentShaderVariantCollection(_savePath); CreateManifest(); - UnityEngine.Debug.Log($"搜集SVC完毕!"); - EditorApplication.update -= EditorUpdate; - _completedCallback?.Invoke(); + Finish(true); } } } @@ -164,7 +188,7 @@ public static class ShaderVariantCollector result.Add(assetPath); } } - EditorDialogUtility.DisplayProgressBar("搜集所有材质球", ++progressValue, collectResult.CollectAssets.Count); + EditorDialogUtility.DisplayProgressBar("Collect All Materials", ++progressValue, collectResult.CollectAssets.Count); } EditorDialogUtility.ClearProgressBar(); @@ -175,7 +199,7 @@ public static class ShaderVariantCollector { Camera camera = Camera.main; if (camera == null) - throw new System.Exception("Not found main camera."); + throw new System.InvalidOperationException("Main camera is missing."); // 设置主相机 float aspect = camera.aspect; @@ -208,13 +232,19 @@ public static class ShaderVariantCollector { x++; } - EditorDialogUtility.DisplayProgressBar("照射所有材质球", ++progressValue, materials.Count); + EditorDialogUtility.DisplayProgressBar("Render All Materials", ++progressValue, materials.Count); } EditorDialogUtility.ClearProgressBar(); } private static GameObject CreateSphere(string assetPath, Vector3 position, int index) { var material = AssetDatabase.LoadAssetAtPath(assetPath); + if (material == null) + { + UnityEngine.Debug.LogWarning($"Material not found: '{assetPath}'."); + return null; + } + var shader = material.shader; if (shader == null) return null; @@ -229,11 +259,12 @@ public static class ShaderVariantCollector { foreach (var go in _allSpheres) { - GameObject.DestroyImmediate(go); + if (go != null) + GameObject.DestroyImmediate(go); } _allSpheres.Clear(); - // 尝试释放编辑器加载的资源 + // 材质扫描会加载编辑器资源,收集结束后主动释放以降低内存占用。 EditorUtility.UnloadUnusedAssetsImmediate(true); } private static void CreateManifest() @@ -251,4 +282,39 @@ public static class ShaderVariantCollector AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate); } + private static void Finish(bool success, Exception exception = null) + { + try + { + if (success) + UnityEngine.Debug.Log("Shader variant collection completed."); + else + UnityEngine.Debug.LogError($"Shader variant collection failed: {exception}."); + + _completedCallback?.Invoke(); + } + finally + { + Cleanup(); + } + } + private static void Cleanup() + { + EditorApplication.update -= EditorUpdate; + EditorDialogUtility.ClearProgressBar(); + + if (_elapsedTime != null) + { + _elapsedTime.Stop(); + _elapsedTime = null; + } + + DestroyAllSpheres(); + _savePath = null; + _packageName = null; + _processMaxNum = 0; + _completedCallback = null; + _allMaterials = null; + _steps = ESteps.None; + } } \ No newline at end of file diff --git a/Assets/YooAsset/Samples~/Extension Sample/Editor/ShaderVariantCollector/ShaderVariantCollectorSetting.cs b/Assets/YooAsset/Samples~/Extension Sample/Editor/ShaderVariantCollector/ShaderVariantCollectorSetting.cs index 62fecc01..b81b6beb 100644 --- a/Assets/YooAsset/Samples~/Extension Sample/Editor/ShaderVariantCollector/ShaderVariantCollectorSetting.cs +++ b/Assets/YooAsset/Samples~/Extension Sample/Editor/ShaderVariantCollector/ShaderVariantCollectorSetting.cs @@ -1,29 +1,54 @@ -using UnityEngine; +using UnityEngine; using UnityEditor; +/// +/// 保存着色器变种收集工具的编辑器偏好设置 +/// public class ShaderVariantCollectorSetting : ScriptableObject { private const string DefaultSavePath = "Assets/MyShaderVariants.shadervariants"; - public static string GeFileSavePath(string packageName) + /// + /// 查询收集结果保存路径 + /// + /// 资源包裹名称 + /// 收集结果保存路径 + public static string GetFileSavePath(string packageName) { - string key = $"{Application.productName}_{packageName}_GeFileSavePath"; + string key = $"{Application.productName}_{packageName}_GetFileSavePath"; return EditorPrefs.GetString(key, DefaultSavePath); } + + /// + /// 设置收集结果保存路径 + /// + /// 资源包裹名称 + /// 收集结果保存路径 public static void SetFileSavePath(string packageName, string savePath) { - string key = $"{Application.productName}_{packageName}_GeFileSavePath"; + string key = $"{Application.productName}_{packageName}_GetFileSavePath"; EditorPrefs.SetString(key, savePath); } - public static int GeProcessCapacity(string packageName) + /// + /// 查询单批处理容量 + /// + /// 资源包裹名称 + /// 单批处理容量 + public static int GetProcessCapacity(string packageName) { - string key = $"{Application.productName}_{packageName}_GeProcessCapacity"; + string key = $"{Application.productName}_{packageName}_GetProcessCapacity"; return EditorPrefs.GetInt(key, 1000); } + + /// + /// 设置单批处理容量 + /// + /// 资源包裹名称 + /// 单批处理容量 public static void SetProcessCapacity(string packageName, int capacity) { - string key = $"{Application.productName}_{packageName}_GeProcessCapacity"; + string key = $"{Application.productName}_{packageName}_GetProcessCapacity"; EditorPrefs.SetInt(key, capacity); } } \ No newline at end of file diff --git a/Assets/YooAsset/Samples~/Extension Sample/Editor/ShaderVariantCollector/ShaderVariantCollectorWindow.cs b/Assets/YooAsset/Samples~/Extension Sample/Editor/ShaderVariantCollector/ShaderVariantCollectorWindow.cs index 1285e7c8..49417572 100644 --- a/Assets/YooAsset/Samples~/Extension Sample/Editor/ShaderVariantCollector/ShaderVariantCollectorWindow.cs +++ b/Assets/YooAsset/Samples~/Extension Sample/Editor/ShaderVariantCollector/ShaderVariantCollectorWindow.cs @@ -1,140 +1,115 @@ -using System; -using System.Linq; using System.Collections.Generic; using UnityEditor; using UnityEngine; -using UnityEditor.UIElements; -using UnityEngine.UIElements; using YooAsset.Editor; +/// +/// 提供着色器变种收集工具窗口 +/// public class ShaderVariantCollectorWindow : EditorWindow { - [MenuItem("Tools/着色器变种收集器", false, 100)] + [MenuItem("Tools/Shader Variant Collector", false, 100)] public static void OpenWindow() { - ShaderVariantCollectorWindow window = GetWindow("着色器变种收集工具", true); + ShaderVariantCollectorWindow window = GetWindow("Shader Variant Collector", true); window.minSize = new Vector2(800, 600); } - private Button _collectButton; - private TextField _collectOutputField; - private Label _currentShaderCountField; - private Label _currentVariantCountField; - private SliderInt _processCapacitySlider; - private PopupField _packageField; - private List _packageNames; + private int _packageIndex; private string _currentPackageName; + private string _collectOutputPath; + private int _processCapacity; - public void CreateGUI() + private void OnEnable() { - try + _packageNames = GetBuildPackageNames(); + if (_packageNames.Count > 0) { - VisualElement root = this.rootVisualElement; - - // 加载布局文件 - var visualAsset = UxmlLoader.LoadWindowUxml(); - if (visualAsset == null) - return; - - visualAsset.CloneTree(root); - - // 包裹名称列表 - _packageNames = GetBuildPackageNames(); - _currentPackageName = _packageNames[0]; - - // 文件输出目录 - _collectOutputField = root.Q("CollectOutput"); - _collectOutputField.SetValueWithoutNotify(ShaderVariantCollectorSetting.GeFileSavePath(_currentPackageName)); - _collectOutputField.RegisterValueChangedCallback(evt => - { - ShaderVariantCollectorSetting.SetFileSavePath(_currentPackageName, _collectOutputField.value); - }); - - // 收集的包裹 - var packageContainer = root.Q("PackageContainer"); - if (_packageNames.Count > 0) - { - int defaultIndex = GetDefaultPackageIndex(_currentPackageName); - _packageField = new PopupField(_packageNames, defaultIndex); - _packageField.label = "Package"; - _packageField.style.width = 350; - _packageField.RegisterValueChangedCallback(evt => - { - _currentPackageName = _packageField.value; - }); - packageContainer.Add(_packageField); - } - else - { - _packageField = new PopupField(); - _packageField.label = "Package"; - _packageField.style.width = 350; - packageContainer.Add(_packageField); - } - - // 容器值 - _processCapacitySlider = root.Q("ProcessCapacity"); - _processCapacitySlider.SetValueWithoutNotify(ShaderVariantCollectorSetting.GeProcessCapacity(_currentPackageName)); -#if !UNITY_2020_3_OR_NEWER - _processCapacitySlider.label = $"Capacity ({_processCapacitySlider.value})"; - _processCapacitySlider.RegisterValueChangedCallback(evt => - { - ShaderVariantCollectorSetting.SetProcessCapacity(_currentPackageName, _processCapacitySlider.value); - _processCapacitySlider.label = $"Capacity ({_processCapacitySlider.value})"; - }); -#else - _processCapacitySlider.RegisterValueChangedCallback(evt => - { - ShaderVariantCollectorSetting.SetProcessCapacity(_currentPackageName, _processCapacitySlider.value); - }); -#endif - - _currentShaderCountField = root.Q