Compare commits

...

83 Commits

Author SHA1 Message Date
何冠峰
101236db8a Update CHANGELOG.md 2025-10-30 20:49:54 +08:00
何冠峰
37de007b3f Update package.json 2025-10-30 20:49:51 +08:00
何冠峰
d570ba8d74 fix #661 2025-10-30 18:31:06 +08:00
何冠峰
2a956099ae 移除程序集里冗余引用 2025-10-30 11:25:21 +08:00
何冠峰
74037a5a29 fix #670 2025-10-28 19:16:51 +08:00
何冠峰
861f850a32 Merge branch 'dev' of https://github.com/tuyoogame/YooAsset into dev 2025-10-27 17:42:32 +08:00
何冠峰
8b1b5f988a fix #669 2025-10-27 17:42:29 +08:00
何冠峰
efafd1173f Merge pull request #667 from yueh0607/fix/chinese-input-textfield
Fix Chinese input issue in TextField by enabling isDelayed
2025-10-27 09:50:52 +08:00
yzp
03e49ff1fb Fix Chinese input issue in TextField by enabling isDelayed
Fixed an issue where Chinese IME candidate characters were being incorrectly inserted into TextFields (PackageDesc, GroupDesc, etc.), causing garbled text like "默认包baobabmo'rmom".

The fix sets `isDelayed = true` on all TextFields in AssetBundleCollectorWindow, which defers value change callbacks until the user completes input (by pressing Enter or losing focus), thus avoiding interference from IME candidate characters.

Modified TextFields:
- PackageName
- PackageDesc
- GroupName
- GroupDesc
- GroupTags
- User Data (collector)
- Asset Tags (collector)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-26 00:01:48 +08:00
何冠峰
ea34be1f00 fix #646 2025-10-15 17:27:08 +08:00
何冠峰
831a9981e3 Update SearchCacheFilesOperation.cs 2025-10-14 16:58:06 +08:00
何冠峰
9de4aaa658 Merge pull request #656 from AlanLiu90/dev
优化SearchCacheFilesOperation
2025-10-14 16:43:07 +08:00
Alan Liu
3579a23bd5 优化SearchCacheFilesOperation 2025-10-13 18:55:49 +08:00
何冠峰
c865ddc7f2 feat #650 2025-10-10 10:20:02 +08:00
何冠峰
0bde506aec feat #648 2025-10-09 19:10:26 +08:00
何冠峰
15005b3d30 sample : 程序集宏支持
YOO_MACRO_SUPPORT开启扩展代码
2025-10-09 19:07:03 +08:00
何冠峰
4caf733ac6 fix #652 2025-10-09 16:17:44 +08:00
何冠峰
014b17f5cb feat #643 2025-10-09 16:14:31 +08:00
何冠峰
f3ebda0c04 refactor : 重构资源清单反序列化逻辑 2025-09-30 15:35:32 +08:00
何冠峰
5602addaca fix #645
修复极端情况下Shader变种收集不完整的问题
2025-09-24 16:37:46 +08:00
何冠峰
c4ae67aa8e perf: 资源扫描不再主动生成报告文件 2025-09-23 11:08:55 +08:00
何冠峰
bbcc3bf971 style : 修改代码注释说明 2025-09-19 10:05:45 +08:00
何冠峰
8b0e75b9b3 feat : 扩展Taptap小游戏文件类 2025-09-19 10:05:16 +08:00
何冠峰
b1f02049cc Update CHANGELOG.md 2025-09-17 16:59:24 +08:00
何冠峰
512886cdf6 Update package.json 2025-09-17 16:58:59 +08:00
何冠峰
0c3ccc5c2f refactor: 适配引擎版本 2025-09-17 16:49:21 +08:00
何冠峰
b0ea03170f refactor : 移除下载器的timeout参数
可以使用看门狗机制代替。
2025-09-17 15:53:22 +08:00
何冠峰
2c3b890329 feat #642 2025-09-17 15:39:47 +08:00
何冠峰
0f39cb9444 update space shooter 2025-09-17 10:53:56 +08:00
何冠峰
8acc16d3f6 perf #632 2025-09-17 10:53:40 +08:00
何冠峰
fd1715a89b fix 修正无效警告 2025-09-17 10:51:24 +08:00
何冠峰
0934c813d1 fix #644 2025-09-13 18:18:31 +08:00
何冠峰
be71d38cd8 update AssetBundleBuilder 2025-09-11 19:20:16 +08:00
何冠峰
4cdfde31da update AssetArtScanner 2025-09-11 19:19:55 +08:00
何冠峰
0133549ef8 feat #638
修复问题,防止游离的Bundle加载任务出现。
2025-09-11 14:03:42 +08:00
何冠峰
81d9eb47c8 feat #638 2025-09-11 11:07:13 +08:00
何冠峰
5fde689f1f feat #640 2025-09-10 21:19:58 +08:00
何冠峰
5d51bfe751 feat #639
修复问题
2025-09-10 21:00:51 +08:00
何冠峰
ed86edd2b0 feat #639 2025-09-10 20:15:52 +08:00
何冠峰
f627b5b59a Update CHANGELOG.md 2025-09-10 12:05:31 +08:00
何冠峰
549ec74519 Update CHANGELOG.md 2025-09-09 20:06:53 +08:00
何冠峰
247ee31348 Update package.json 2025-09-09 20:06:31 +08:00
何冠峰
90d3a53bc3 fix #631 2025-09-09 19:06:17 +08:00
何冠峰
19f1d67a61 feat : 弱引用资源句柄 2025-09-09 18:31:02 +08:00
何冠峰
a71c46d1c4 feat : 构建过程图集依赖计算增加开关 2025-09-08 19:00:55 +08:00
何冠峰
82d7bc8fef fix #614 增加Taptap小游戏扩展类 2025-08-30 18:09:28 +08:00
何冠峰
cc85099253 update mini game
重构相关代码,使用通用逻辑
2025-08-30 17:38:26 +08:00
何冠峰
d392b02bd4 refactor : 重构了Web文件系统公共类
方便小游戏共用基础代码。
2025-08-30 17:30:29 +08:00
何冠峰
a5138b9846 feat : 在SBP构建管线里,自动建立主资源对象对图集的依赖关系 2025-08-29 19:06:55 +08:00
何冠峰
e1b6458c26 update space shooter 2025-08-29 19:04:29 +08:00
何冠峰
0f73dc3047 update sample 2025-08-28 22:08:02 +08:00
何冠峰
a85e49c22a fix #625 2025-08-28 22:07:00 +08:00
何冠峰
6b291de922 fix #617 2025-08-28 19:02:08 +08:00
何冠峰
a4b1300195 fix #623 2025-08-28 10:40:13 +08:00
何冠峰
6f34951a74 refactor #627 2025-08-28 10:27:37 +08:00
何冠峰
c798250258 feat : CRC工具类增加获取整形值的方法 2025-08-27 19:19:00 +08:00
何冠峰
6fc82bb55a feat : 新增配置参数控制缓存文件验证最大并发数 2025-08-27 18:03:53 +08:00
何冠峰
c22cf5ffeb fix #620 2025-08-27 16:04:18 +08:00
何冠峰
36bc24f9fd fix #622 2025-08-27 10:29:13 +08:00
何冠峰
addb0ecdfe build #621 2025-08-27 10:27:12 +08:00
何冠峰
89e23e0df8 perf : 优化异步操作系统的繁忙检测机制
默认情况下不必检测
2025-08-16 16:53:28 +08:00
何冠峰
e2f582834e fix #611 2025-08-13 10:29:41 +08:00
何冠峰
d2c2844f61 update mini game
移除冗余代码
2025-08-13 10:29:25 +08:00
何冠峰
1de64278ad sample : 新增生成内置清单文件的页面工具 2025-08-04 18:36:43 +08:00
何冠峰
227f2332a9 refactor : 重构内置文件的加载和拷贝逻辑。
优先使用File类拷贝文件
2025-08-04 17:26:57 +08:00
何冠峰
131614687c Update LICENSE 2025-07-30 14:18:26 +08:00
何冠峰
b8ec902f60 perf : IsUnpackBundleFile方法设置为虚方法 2025-07-29 14:34:59 +08:00
何冠峰
eb3e29b6ad style : 修改形参注释 2025-07-29 14:33:54 +08:00
何冠峰
11ed9d391a build : 预留构建Mono脚本资源包方法。 2025-07-25 16:09:29 +08:00
何冠峰
9cd50bc7f3 fix : 修复构建页面扩展类缺少指定属性报错的问题。 2025-07-25 15:43:37 +08:00
何冠峰
e92505ba88 samples : 增加自定义构建页面的扩展示例 2025-07-25 15:42:17 +08:00
何冠峰
06a670730c Update README.md 2025-07-25 14:50:13 +08:00
何冠峰
ccd21e56cb sample : 更新UniTask扩展库的说明文档 2025-07-24 16:35:22 +08:00
何冠峰
522bcc529a update UniTask sample 2025-07-24 14:56:58 +08:00
何冠峰
2254ac9f5e update UniTask sample
更新说明文档
2025-07-24 14:45:52 +08:00
何冠峰
956b3db71d Merge pull request #601 from GodChouyu/dev
UniTask示例删除UniTask源码,修改为扩展支持。
2025-07-24 11:31:33 +08:00
何冠峰
fb56959c61 style : 统一小游戏编码规范和命名规范 2025-07-24 11:21:37 +08:00
何冠峰
b9b9f4e37d feat : 新增支付宝小游戏文件系统扩展类 2025-07-24 11:18:29 +08:00
GodChouyu
c050d6d172 UniTask示例删除UniTask源码,修改为扩展支持。 2025-07-24 10:15:17 +08:00
何冠峰
baf76a454b Update CHANGELOG.md 2025-07-23 18:49:13 +08:00
何冠峰
385d343262 Update package.json 2025-07-23 18:49:02 +08:00
何冠峰
1f5ad24d44 test : 完善测试用例代码 2025-07-23 18:46:54 +08:00
何冠峰
fefc0043cf fix : 修正小游戏脚本编译错误 2025-07-23 18:46:12 +08:00
571 changed files with 5373 additions and 73989 deletions

View File

@@ -2,7 +2,250 @@
All notable changes to this package will be documented in this file.
## [2.3.13] - 2025-07-23
## [2.3.17] - 2025-10-30
**非常重要**:修复了#627优化导致的资源清单CRC值为空的问题
该问题会导致下载的损坏文件验证通过。
影响范围v2.3.15版本v2.3.16版本。
**非常重要**(#661) 修复了Package销毁过程中遇到正在加载的AssetBundle会导致无法卸载的问题。
该问题是偶现引擎会提示AssetBundle已经加载无法加载新的文件导致资源对象加载失败
影响范围:所有版本!
### Improvements
- 重构并统一了资源清单的反序列化逻辑。
### Fixed
- (#645) 修复了着色器变种收集工具,在极端情况下变种收集不完整的问题。
- (#646) 修复了EditorSimulateMode模式下开启模拟下载tag不生效的问题。
- (#667) 修复了所有编辑器窗口针对中文IME的输入问题。
- (#670) 修复了Catalog文件生成过程中白名单未考虑自定义清单前缀名。
### Improvements
- (#650) 解决互相依赖的资源包无法卸载的问题。需要开启宏定义YOOASSET_EXPERIMENTAL
- (#655) 优化了初始化的时候缓存文件搜索效率。安卓平台性能提升1倍IOS平台性能提升3倍。
### Added
- (#643) 新增构建参数,可以节省资源清单运行时内存
```csharp
class ScriptableBuildParameters
{
/// <summary>
/// 使用可寻址地址代替资源路径
/// 说明:开启此项可以节省运行时清单占用的内存!
/// </summary>
public bool ReplaceAssetPathWithAddress = false;
}
```
- (#648) 新增初始化参数,可以自动释放引用计数为零的资源包
```csharp
class InitializeParameters
{
/// <summary>
/// 当资源引用计数为零的时候自动释放资源包
/// </summary>
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
{
/// <summary>
/// 模拟虚拟下载模式
/// </summary>
public bool VirtualDownloadMode { private set; get; } = false;
/// <summary>
/// 模拟虚拟下载的网速(单位:字节)
/// </summary>
public int VirtualDownloadSpeed { private set; get; } = 1024;
}
```
- (#640) 新增了文件系统参数VIRTUAL_WEBGL_MODE
编辑器下不需要构建AB也可以模拟小游戏开发环境等同真机运行环境。
```csharp
class DefaultEditorFIleSystem
{
/// <summary>
/// 模拟WebGL平台模式
/// </summary>
public bool VirtualWebGLMode { private set; get; } = false;
}
```
- (#642) 新增了文件系统参数DOWNLOAD_WATCH_DOG_TIME
监控时间范围内,如果没有接收到任何下载数据,那么直接终止任务!
```csharp
class DefaultCacheFIleSystem
{
/// <summary>
/// 自定义参数:下载任务的看门狗机制监控时间
/// </summary>
public int DownloadWatchDogTime { private set; get; } = int.MaxValue;
}
```
### Changed
- 下载器参数timeout移除。
可以使用文件系统的看门狗机制代替。
- (#632) IFilterRule接口变动。
收集器可以指定搜寻的资源类型,在收集目录资产量巨大的情况下,可以极大加快打包速度!
```csharp
public interface IFilterRule
{
/// <summary>
/// 搜寻的资源类型
/// 说明:使用引擎方法搜索获取所有资源列表
/// </summary>
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
/// <summary>
/// 启用弱引用资源句柄
/// </summary>
public bool UseWeakReferenceHandle = false;
```
- 内置文件系统和缓存文件系统新增初始化参数FILE_VERIFY_MAX_CONCURRENCY
```csharp
/// <summary>
/// 自定义参数:初始化的时候缓存文件校验最大并发数
/// </summary>
public int FileVerifyMaxConcurrency { private set; get; }
```
- (#623) 内置构建管线新增构建参数StripUnityVersion
```csharp
/// <summary>
/// 从文件头里剥离Unity版本信息
/// </summary>
public bool StripUnityVersion = false;
```
- 可编程构建管线新增构建参数TrackSpriteAtlasDependencies
```csharp
/// <summary>
/// 自动建立资源对象对图集的依赖关系
/// </summary>
public bool TrackSpriteAtlasDependencies = false;
```
- (#617) 新增资源收集配置参数SupportExtensionless
在不需要模糊加载模式的前提下,关闭此选项,可以降低运行时内存大小。
该选项默认开启!
```csharp
public class CollectCommand
{
/// <summary>
/// 支持无后缀名的资源定位地址
/// </summary>
public bool SupportExtensionless { set; get; }
}
```
- (#625) 异步操作系统类新增监听方法。
```csharp
class OperationSystem
{
/// <summary>
/// 监听任务开始
/// </summary>
public static void RegisterStartCallback(Action<string, AsyncOperationBase> callback);
/// <summary>
/// 监听任务结束
/// </summary>
public static void RegisterFinishCallback(Action<string, AsyncOperationBase> callback);
}
```
## [2.3.14] - 2025-07-23
**重要****所有下载相关的超时参数timeout已更新判定逻辑**

View File

@@ -32,21 +32,14 @@ namespace YooAsset.Editor
// 开始扫描工作
ScanReport report = scanner.RunScanner();
// 检测报告合法性
report.CheckError();
// 保存扫描结果
string saveDirectory = scanner.SaveDirectory;
if (string.IsNullOrEmpty(saveDirectory))
saveDirectory = "Assets/";
string filePath = $"{saveDirectory}/{scanner.ScannerName}_{scanner.ScannerDesc}.json";
ScanReportConfig.ExportJsonConfig(filePath, report);
return new ScannerResult(filePath, report);
// 返回扫描结果
return new ScannerResult(report);
}
catch (Exception e)
{
return new ScannerResult(e.StackTrace);
return new ScannerResult(e.Message, e.StackTrace);
}
}

View File

@@ -294,6 +294,11 @@ namespace YooAsset.Editor
_scannerListView.itemsSource = filterItems;
_scannerListView.Rebuild();
}
if (_lastModifyScannerIndex >= 0 && _lastModifyScannerIndex < _scannerListView.itemsSource.Count)
{
_scannerListView.selectedIndex = _lastModifyScannerIndex;
}
}
private List<AssetArtScanner> FilterScanners()
{

View File

@@ -3,11 +3,6 @@ namespace YooAsset.Editor
{
public class ScannerResult
{
/// <summary>
/// 生成的报告文件路径
/// </summary>
public string ReprotFilePath { private set; get; }
/// <summary>
/// 报告对象
/// </summary>
@@ -18,6 +13,11 @@ namespace YooAsset.Editor
/// </summary>
public string ErrorInfo { private set; get; }
/// <summary>
/// 错误堆栈
/// </summary>
public string ErrorStack { private set; get; }
/// <summary>
/// 是否成功
/// </summary>
@@ -33,15 +33,14 @@ namespace YooAsset.Editor
}
public ScannerResult(string error)
public ScannerResult(string error, string stack)
{
ErrorInfo = error;
ErrorStack = stack;
}
public ScannerResult(string filePath, ScanReport report)
public ScannerResult(ScanReport report)
{
ReprotFilePath = filePath;
Report = report;
ErrorInfo = string.Empty;
}
/// <summary>
@@ -55,5 +54,19 @@ namespace YooAsset.Editor
reproterWindow.ImportSingleReprotFile(Report);
}
}
/// <summary>
/// 保存报告文件
/// </summary>
public void SaveReportFile(string saveDirectory)
{
if (Report == null)
throw new System.Exception("Scan report is invalid !");
if (string.IsNullOrEmpty(saveDirectory))
saveDirectory = "Assets/";
string filePath = $"{saveDirectory}/{Report.ReportName}_{Report.ReportDesc}.json";
ScanReportConfig.ExportJsonConfig(filePath, Report);
}
}
}

View File

@@ -77,6 +77,12 @@ namespace YooAsset.Editor
foreach (var classType in viewerClassTypes)
{
var buildPipelineAttribute = EditorTools.GetAttribute<BuildPipelineAttribute>(classType);
if (buildPipelineAttribute == null)
{
Debug.LogWarning($"The class {classType.FullName} need attribute {nameof(BuildPipelineAttribute)}");
continue;
}
string pipelineName = buildPipelineAttribute.PipelineName;
if (_viewClassDic.ContainsKey(pipelineName))
{

View File

@@ -27,7 +27,7 @@ namespace YooAsset.Editor
/// <summary>
/// 文件哈希值
/// </summary>
public string PackageFileCRC { set; get; }
public uint PackageFileCRC { set; get; }
/// <summary>
/// 文件哈希值
@@ -106,7 +106,27 @@ namespace YooAsset.Editor
/// </summary>
public string[] GetAllPackAssetPaths()
{
return AllPackAssets.Select(t => t.AssetInfo.AssetPath).ToArray();
List<string> results = new List<string>(AllPackAssets.Count);
for (int i = 0; i < AllPackAssets.Count; i++)
{
var packAsset = AllPackAssets[i];
results.Add(packAsset.AssetInfo.AssetPath);
}
return results.ToArray();
}
/// <summary>
/// 获取构建的资源可寻址列表
/// </summary>
public string[] GetAllPackAssetAddress()
{
List<string> results = new List<string>(AllPackAssets.Count);
for (int i = 0; i < AllPackAssets.Count; i++)
{
var packAsset = AllPackAssets[i];
results.Add(packAsset.Address);
}
return results.ToArray();
}
/// <summary>
@@ -153,13 +173,15 @@ namespace YooAsset.Editor
/// <summary>
/// 创建AssetBundleBuild类
/// </summary>
public UnityEditor.AssetBundleBuild CreatePipelineBuild()
public UnityEditor.AssetBundleBuild CreatePipelineBuild(bool replaceAssetPathWithAddress)
{
// 注意我们不再支持AssetBundle的变种机制
AssetBundleBuild build = new AssetBundleBuild();
build.assetBundleName = BundleName;
build.assetBundleVariant = string.Empty;
build.assetNames = GetAllPackAssetPaths();
if (replaceAssetPathWithAddress)
build.addressableNames = GetAllPackAssetAddress();
return build;
}

View File

@@ -13,6 +13,11 @@ namespace YooAsset.Editor
/// </summary>
private readonly Dictionary<string, BuildBundleInfo> _bundleInfoDic = new Dictionary<string, BuildBundleInfo>(10000);
/// <summary>
/// 图集资源集合
/// </summary>
public readonly List<BuildAssetInfo> SpriteAtlasAssetList = new List<BuildAssetInfo>(10000);
/// <summary>
/// 未被依赖的资源列表
/// </summary>
@@ -60,6 +65,12 @@ namespace YooAsset.Editor
newBundleInfo.PackAsset(assetInfo);
_bundleInfoDic.Add(bundleName, newBundleInfo);
}
// 统计所有的精灵图集
if (assetInfo.AssetInfo.IsSpriteAtlas())
{
SpriteAtlasAssetList.Add(assetInfo);
}
}
/// <summary>
@@ -85,12 +96,12 @@ namespace YooAsset.Editor
/// <summary>
/// 获取构建管线里需要的数据
/// </summary>
public UnityEditor.AssetBundleBuild[] GetPipelineBuilds()
public UnityEditor.AssetBundleBuild[] GetPipelineBuilds(bool replaceAssetPathWithAddres)
{
List<UnityEditor.AssetBundleBuild> builds = new List<UnityEditor.AssetBundleBuild>(_bundleInfoDic.Count);
foreach (var bundleInfo in _bundleInfoDic.Values)
{
builds.Add(bundleInfo.CreatePipelineBuild());
builds.Add(bundleInfo.CreatePipelineBuild(replaceAssetPathWithAddres));
}
return builds.ToArray();
}

View File

@@ -2,6 +2,7 @@
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
namespace YooAsset.Editor
{
@@ -18,7 +19,7 @@ namespace YooAsset.Editor
/// <summary>
/// 创建补丁清单文件到输出目录
/// </summary>
protected void CreateManifestFile(bool processBundleDepends, bool processBundleTags, BuildContext context)
protected void CreateManifestFile(bool processBundleDepends, bool processBundleTags, bool replaceAssetPathWithAddress, BuildContext context)
{
var buildMapContext = context.GetContextObject<BuildMapContext>();
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
@@ -32,8 +33,10 @@ namespace YooAsset.Editor
PackageManifest manifest = new PackageManifest();
manifest.FileVersion = ManifestDefine.FileVersion;
manifest.EnableAddressable = buildMapContext.Command.EnableAddressable;
manifest.SupportExtensionless = buildMapContext.Command.SupportExtensionless;
manifest.LocationToLower = buildMapContext.Command.LocationToLower;
manifest.IncludeAssetGUID = buildMapContext.Command.IncludeAssetGUID;
manifest.ReplaceAssetPathWithAddress = replaceAssetPathWithAddress;
manifest.OutputNameStyle = (int)buildParameters.FileNameStyle;
manifest.BuildBundleType = buildParameters.BuildBundleType;
manifest.BuildPipeline = buildParameters.BuildPipeline;
@@ -56,7 +59,13 @@ namespace YooAsset.Editor
// 4. 处理内置资源包
if (processBundleDepends)
{
// 注意:初始化资源清单建立引用关系
manifest.Initialize();
ProcessBuiltinBundleDependency(context, manifest);
}
// 创建资源清单文本文件
{
@@ -303,15 +312,34 @@ namespace YooAsset.Editor
// 注意:如果是可编程构建管线,需要补充内置资源包
// 注意:该步骤依赖前面的操作!
var buildResultContext = context.TryGetContextObject<TaskBuilding_SBP.BuildResultContext>();
if (buildResultContext != null)
{
// 注意:初始化资源清单建立引用关系
ManifestTools.InitManifest(manifest);
ProcessBuiltinBundleReference(context, manifest, buildResultContext.BuiltinShadersBundleName);
ProcessBuiltinBundleReference(context, manifest, buildResultContext.MonoScriptsBundleName);
ProcessBuiltinBundleReference(manifest, buildResultContext.BuiltinShadersBundleName);
ProcessBuiltinBundleReference(manifest, buildResultContext.MonoScriptsBundleName);
var buildParametersContext = context.TryGetContextObject<BuildParametersContext>();
var buildParameters = buildParametersContext.Parameters;
if (buildParameters is ScriptableBuildParameters scriptableBuildParameters)
{
if (scriptableBuildParameters.TrackSpriteAtlasDependencies)
{
// 注意:检测是否开启图集模式
// 说明:需要记录主资源对象对图集的依赖关系!
if (EditorSettings.spritePackerMode != SpritePackerMode.Disabled)
{
var buildMapContext = context.GetContextObject<BuildMapContext>();
foreach (var spriteAtlasAsset in buildMapContext.SpriteAtlasAssetList)
{
string spriteAtlasBundleName = spriteAtlasAsset.BundleName;
ProcessBuiltinBundleReference(manifest, spriteAtlasBundleName);
}
}
}
}
}
}
private void ProcessBuiltinBundleReference(BuildContext context, PackageManifest manifest, string builtinBundleName)
private void ProcessBuiltinBundleReference(PackageManifest manifest, string builtinBundleName)
{
if (string.IsNullOrEmpty(builtinBundleName))
return;

View File

@@ -32,6 +32,7 @@ namespace YooAsset.Editor
// 收集器配置
buildReport.Summary.UniqueBundleName = buildMapContext.Command.UniqueBundleName;
buildReport.Summary.EnableAddressable = buildMapContext.Command.EnableAddressable;
buildReport.Summary.SupportExtensionless = buildMapContext.Command.SupportExtensionless;
buildReport.Summary.LocationToLower = buildMapContext.Command.LocationToLower;
buildReport.Summary.IncludeAssetGUID = buildMapContext.Command.IncludeAssetGUID;
buildReport.Summary.AutoCollectShaders = buildMapContext.Command.AutoCollectShaders;
@@ -53,6 +54,7 @@ namespace YooAsset.Editor
buildReport.Summary.CompressOption = builtinBuildParameters.CompressOption;
buildReport.Summary.DisableWriteTypeTree = builtinBuildParameters.DisableWriteTypeTree;
buildReport.Summary.IgnoreTypeTreeChanges = builtinBuildParameters.IgnoreTypeTreeChanges;
buildReport.Summary.ReplaceAssetPathWithAddress = builtinBuildParameters.ReplaceAssetPathWithAddress;
}
else if (buildParameters is ScriptableBuildParameters)
{
@@ -60,6 +62,7 @@ namespace YooAsset.Editor
buildReport.Summary.CompressOption = scriptableBuildParameters.CompressOption;
buildReport.Summary.DisableWriteTypeTree = scriptableBuildParameters.DisableWriteTypeTree;
buildReport.Summary.IgnoreTypeTreeChanges = scriptableBuildParameters.IgnoreTypeTreeChanges;
buildReport.Summary.ReplaceAssetPathWithAddress = scriptableBuildParameters.ReplaceAssetPathWithAddress;
buildReport.Summary.WriteLinkXML = scriptableBuildParameters.WriteLinkXML;
buildReport.Summary.CacheServerHost = scriptableBuildParameters.CacheServerHost;
buildReport.Summary.CacheServerPort = scriptableBuildParameters.CacheServerPort;

View File

@@ -63,7 +63,7 @@ namespace YooAsset.Editor
protected abstract string GetUnityHash(BuildBundleInfo bundleInfo, BuildContext context);
protected abstract uint GetUnityCRC(BuildBundleInfo bundleInfo, BuildContext context);
protected abstract string GetBundleFileHash(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext);
protected abstract string GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext);
protected abstract uint GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext);
protected abstract long GetBundleFileSize(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext);
}
}

View File

@@ -23,7 +23,8 @@ namespace YooAsset.Editor
// 开始构建
string pipelineOutputDirectory = buildParametersContext.GetPipelineOutputDirectory();
BuildAssetBundleOptions buildOptions = builtinBuildParameters.GetBundleBuildOptions();
AssetBundleManifest unityManifest = BuildPipeline.BuildAssetBundles(pipelineOutputDirectory, buildMapContext.GetPipelineBuilds(), buildOptions, buildParametersContext.Parameters.BuildTarget);
var bundleBuilds = buildMapContext.GetPipelineBuilds(builtinBuildParameters.ReplaceAssetPathWithAddress);
AssetBundleManifest unityManifest = BuildPipeline.BuildAssetBundles(pipelineOutputDirectory, bundleBuilds, buildOptions, buildParametersContext.Parameters.BuildTarget);
if (unityManifest == null)
{
string message = BuildLogger.GetErrorMessage(ErrorCode.UnityEngineBuildFailed, "UnityEngine build failed !");

View File

@@ -11,7 +11,10 @@ namespace YooAsset.Editor
void IBuildTask.Run(BuildContext context)
{
CreateManifestFile(true, true, context);
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
var builtinBuildParameters = buildParametersContext.Parameters as BuiltinBuildParameters;
bool replaceAssetPathWithAddress = builtinBuildParameters.ReplaceAssetPathWithAddress;
CreateManifestFile(true, true, replaceAssetPathWithAddress, context);
}
protected override string[] GetBundleDepends(BuildContext context, string bundleName)

View File

@@ -45,10 +45,10 @@ namespace YooAsset.Editor
string filePath = bundleInfo.PackageSourceFilePath;
return HashUtility.FileMD5(filePath);
}
protected override string GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
protected override uint GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
{
string filePath = bundleInfo.PackageSourceFilePath;
return HashUtility.FileCRC32(filePath);
return HashUtility.FileCRC32Value(filePath);
}
protected override long GetBundleFileSize(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
{

View File

@@ -12,6 +12,11 @@ namespace YooAsset.Editor
/// </summary>
public ECompressOption CompressOption = ECompressOption.Uncompressed;
/// <summary>
/// 从文件头里剥离Unity版本信息
/// </summary>
public bool StripUnityVersion = false;
/// <summary>
/// 禁止写入类型树结构(可以降低包体和内存并提高加载效率)
/// </summary>
@@ -22,6 +27,12 @@ namespace YooAsset.Editor
/// </summary>
public bool IgnoreTypeTreeChanges = true;
/// <summary>
/// 使用可寻址地址代替资源路径
/// 说明:开启此项可以节省运行时清单占用的内存!
/// </summary>
public bool ReplaceAssetPathWithAddress = false;
/// <summary>
/// 获取内置构建管线的构建选项
@@ -41,6 +52,8 @@ namespace YooAsset.Editor
if (ClearBuildCacheFiles)
opt |= BuildAssetBundleOptions.ForceRebuildAssetBundle; //Force rebuild the asset bundles
if (StripUnityVersion)
opt |= BuildAssetBundleOptions.AssetBundleStripUnityVersion; //Removes the Unity Version number in the Archive File & Serialized File headers
if (DisableWriteTypeTree)
opt |= BuildAssetBundleOptions.DisableWriteTypeTree; //Do not include type information within the asset bundle (don't write type tree).
if (IgnoreTypeTreeChanges)

View File

@@ -7,7 +7,7 @@ namespace YooAsset.Editor
{
void IBuildTask.Run(BuildContext context)
{
CreateManifestFile(false, false, context);
CreateManifestFile(false, true, false, context);
}
protected override string[] GetBundleDepends(BuildContext context, string bundleName)

View File

@@ -24,9 +24,9 @@ namespace YooAsset.Editor
string filePath = bundleInfo.PackageSourceFilePath;
return GetFilePathTempHash(filePath);
}
protected override string GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
protected override uint GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
{
return "00000000"; //8位
return 0;
}
protected override long GetBundleFileSize(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
{

View File

@@ -9,7 +9,7 @@ namespace YooAsset.Editor
{
void IBuildTask.Run(BuildContext context)
{
CreateManifestFile(false, true, context);
CreateManifestFile(false, true, false, context);
}
protected override string[] GetBundleDepends(BuildContext context, string bundleName)

View File

@@ -27,10 +27,10 @@ namespace YooAsset.Editor
string filePath = bundleInfo.PackageSourceFilePath;
return HashUtility.FileMD5(filePath);
}
protected override string GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
protected override uint GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
{
string filePath = bundleInfo.PackageSourceFilePath;
return HashUtility.FileCRC32(filePath);
return HashUtility.FileCRC32Value(filePath);
}
protected override long GetBundleFileSize(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
{

View File

@@ -24,7 +24,8 @@ namespace YooAsset.Editor
var scriptableBuildParameters = buildParametersContext.Parameters as ScriptableBuildParameters;
// 构建内容
var buildContent = new BundleBuildContent(buildMapContext.GetPipelineBuilds());
var bundleBuilds = buildMapContext.GetPipelineBuilds(scriptableBuildParameters.ReplaceAssetPathWithAddress);
var buildContent = new BundleBuildContent(bundleBuilds);
// 开始构建
IBundleBuildResults buildResults;

View File

@@ -13,7 +13,10 @@ namespace YooAsset.Editor
void IBuildTask.Run(BuildContext context)
{
CreateManifestFile(true, true, context);
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
var scriptableBuildParameters = buildParametersContext.Parameters as ScriptableBuildParameters;
bool replaceAssetPathWithAddress = scriptableBuildParameters.ReplaceAssetPathWithAddress;
CreateManifestFile(true, true, replaceAssetPathWithAddress, context);
}
protected override string[] GetBundleDepends(BuildContext context, string bundleName)

View File

@@ -45,10 +45,10 @@ namespace YooAsset.Editor
string filePath = bundleInfo.PackageSourceFilePath;
return HashUtility.FileMD5(filePath);
}
protected override string GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
protected override uint GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
{
string filePath = bundleInfo.PackageSourceFilePath;
return HashUtility.FileCRC32(filePath);
return HashUtility.FileCRC32Value(filePath);
}
protected override long GetBundleFileSize(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
{

View File

@@ -15,7 +15,7 @@ namespace YooAsset.Editor
public ECompressOption CompressOption = ECompressOption.Uncompressed;
/// <summary>
/// 从AssetBundle文件头里剥离Unity版本信息
/// 从文件头里剥离Unity版本信息
/// </summary>
public bool StripUnityVersion = false;
@@ -25,10 +25,21 @@ namespace YooAsset.Editor
public bool DisableWriteTypeTree = false;
/// <summary>
/// 忽略类型树变化
/// 忽略类型树变化(无效参数)
/// </summary>
public bool IgnoreTypeTreeChanges = true;
/// <summary>
/// 使用可寻址地址代替资源路径
/// 说明:开启此项可以节省运行时清单占用的内存!
/// </summary>
public bool ReplaceAssetPathWithAddress = false;
/// <summary>
/// 自动建立资源对象对图集的依赖关系
/// </summary>
public bool TrackSpriteAtlasDependencies = false;
/// <summary>
/// 生成代码防裁剪配置
@@ -76,10 +87,9 @@ namespace YooAsset.Editor
throw new System.NotImplementedException(CompressOption.ToString());
if (StripUnityVersion)
buildParams.ContentBuildFlags |= UnityEditor.Build.Content.ContentBuildFlags.StripUnityVersion;
buildParams.ContentBuildFlags |= UnityEditor.Build.Content.ContentBuildFlags.StripUnityVersion; // Build Flag to indicate the Unity Version should not be written to the serialized file.
if (DisableWriteTypeTree)
buildParams.ContentBuildFlags |= UnityEditor.Build.Content.ContentBuildFlags.DisableWriteTypeTree;
buildParams.ContentBuildFlags |= UnityEditor.Build.Content.ContentBuildFlags.DisableWriteTypeTree; //Do not include type information within the built content.
buildParams.UseCache = true;
buildParams.CacheServerHost = CacheServerHost;

View File

@@ -21,6 +21,11 @@ namespace YooAsset.Editor
/// </summary>
public string ErrorInfo;
/// <summary>
/// 构建失败的堆栈
/// </summary>
public string ErrorStack;
/// <summary>
/// 输出的补丁包目录
/// </summary>

View File

@@ -51,6 +51,7 @@ namespace YooAsset.Editor
EditorTools.ClearProgressBar();
buildResult.FailedTask = task.GetType().Name;
buildResult.ErrorInfo = e.ToString();
buildResult.ErrorStack = e.StackTrace;
buildResult.Success = false;
break;
}

View File

@@ -104,7 +104,6 @@ namespace YooAsset.Editor
var compressOption = AssetBundleBuilderSetting.GetPackageCompressOption(PackageName, PipelineName);
var clearBuildCache = AssetBundleBuilderSetting.GetPackageClearBuildCache(PackageName, PipelineName);
var useAssetDependencyDB = AssetBundleBuilderSetting.GetPackageUseAssetDependencyDB(PackageName, PipelineName);
var builtinShaderBundleName = GetBuiltinShaderBundleName();
ScriptableBuildParameters buildParameters = new ScriptableBuildParameters();
buildParameters.BuildOutputRoot = AssetBundleBuilderHelper.GetDefaultBuildOutputRoot();
@@ -122,10 +121,10 @@ namespace YooAsset.Editor
buildParameters.CompressOption = compressOption;
buildParameters.ClearBuildCacheFiles = clearBuildCache;
buildParameters.UseAssetDependencyDB = useAssetDependencyDB;
buildParameters.BuiltinShadersBundleName = builtinShaderBundleName;
buildParameters.EncryptionServices = CreateEncryptionServicesInstance();
buildParameters.ManifestProcessServices = CreateManifestProcessServicesInstance();
buildParameters.ManifestRestoreServices = CreateManifestRestoreServicesInstance();
buildParameters.BuiltinShadersBundleName = GetBuiltinShaderBundleName();
ScriptableBuildPipeline pipeline = new ScriptableBuildPipeline();
var buildResult = pipeline.Run(buildParameters, true);
@@ -143,6 +142,16 @@ namespace YooAsset.Editor
var packRuleResult = DefaultPackRule.CreateShadersPackRuleResult();
return packRuleResult.GetBundleName(PackageName, uniqueBundleName);
}
/// <summary>
/// Mono脚本的资源包名称
/// </summary>
protected string GetMonoScriptsBundleName()
{
var uniqueBundleName = AssetBundleCollectorSettingData.Setting.UniqueBundleName;
var packRuleResult = DefaultPackRule.CreateMonosPackRuleResult();
return packRuleResult.GetBundleName(PackageName, uniqueBundleName);
}
}
}
#endif

View File

@@ -139,10 +139,17 @@ namespace YooAsset.Editor
/// </summary>
public List<CollectAssetInfo> GetAllCollectAssets(CollectCommand command, AssetBundleCollectorGroup group)
{
// 注意:模拟构建模式下只收集主资源
if (command.SimulateBuild)
bool ignoreStaticCollector = command.IsFlagSet(ECollectFlags.IgnoreStaticCollector);
if (ignoreStaticCollector)
{
if (CollectorType != ECollectorType.MainAssetCollector)
if (CollectorType == ECollectorType.StaticAssetCollector)
return new List<CollectAssetInfo>();
}
bool ignoreDependCollector = command.IsFlagSet(ECollectFlags.IgnoreDependCollector);
if (ignoreDependCollector)
{
if (CollectorType == ECollectorType.DependAssetCollector)
return new List<CollectAssetInfo>();
}
@@ -152,8 +159,10 @@ namespace YooAsset.Editor
List<string> findAssets = new List<string>();
if (AssetDatabase.IsValidFolder(CollectPath))
{
string collectDirectory = CollectPath;
string[] findResult = EditorTools.FindAssets(EAssetSearchType.All, collectDirectory);
IFilterRule filterRuleInstance = AssetBundleCollectorSettingData.GetFilterRuleInstance(FilterRuleName);
string findAssetType = filterRuleInstance.FindAssetType;
string searchFolder = CollectPath;
string[] findResult = EditorTools.FindAssets(findAssetType, searchFolder);
findAssets.AddRange(findResult);
}
else
@@ -269,8 +278,8 @@ namespace YooAsset.Editor
}
private List<AssetInfo> GetAllDependencies(CollectCommand command, string mainAssetPath)
{
// 注意:模拟构建模式下不需要收集依赖资源
if (command.SimulateBuild)
bool ignoreGetDependencies = command.IsFlagSet(ECollectFlags.IgnoreGetDependencies);
if (ignoreGetDependencies)
return new List<AssetInfo>();
string[] depends = command.AssetDependency.GetDependencies(mainAssetPath, true);

View File

@@ -10,7 +10,7 @@ namespace YooAsset.Editor
{
public class AssetBundleCollectorConfig
{
public const string ConfigVersion = "v2.1";
public const string ConfigVersion = "v2025.8.28";
public const string XmlVersion = "Version";
public const string XmlCommon = "Common";
@@ -23,6 +23,7 @@ namespace YooAsset.Editor
public const string XmlPackageName = "PackageName";
public const string XmlPackageDesc = "PackageDesc";
public const string XmlEnableAddressable = "AutoAddressable";
public const string XmlSupportExtensionless = "SupportExtensionless";
public const string XmlLocationToLower = "LocationToLower";
public const string XmlIncludeAssetGUID = "IncludeAssetGUID";
public const string XmlIgnoreRuleName = "IgnoreRuleName";
@@ -99,6 +100,7 @@ namespace YooAsset.Editor
package.PackageName = packageElement.GetAttribute(XmlPackageName);
package.PackageDesc = packageElement.GetAttribute(XmlPackageDesc);
package.EnableAddressable = packageElement.GetAttribute(XmlEnableAddressable) == "True" ? true : false;
package.SupportExtensionless = packageElement.GetAttribute(XmlSupportExtensionless) == "True" ? true : false;
package.LocationToLower = packageElement.GetAttribute(XmlLocationToLower) == "True" ? true : false;
package.IncludeAssetGUID = packageElement.GetAttribute(XmlIncludeAssetGUID) == "True" ? true : false;
package.IgnoreRuleName = packageElement.GetAttribute(XmlIgnoreRuleName);
@@ -211,6 +213,7 @@ namespace YooAsset.Editor
packageElement.SetAttribute(XmlPackageName, package.PackageName);
packageElement.SetAttribute(XmlPackageDesc, package.PackageDesc);
packageElement.SetAttribute(XmlEnableAddressable, package.EnableAddressable.ToString());
packageElement.SetAttribute(XmlSupportExtensionless, package.SupportExtensionless.ToString());
packageElement.SetAttribute(XmlLocationToLower, package.LocationToLower.ToString());
packageElement.SetAttribute(XmlIncludeAssetGUID, package.IncludeAssetGUID.ToString());
packageElement.SetAttribute(XmlIgnoreRuleName, package.IgnoreRuleName);
@@ -275,6 +278,23 @@ namespace YooAsset.Editor
return UpdateXmlConfig(xmlDoc);
}
// v2.1 -> v2025.8.28
if (configVersion == "v2.1")
{
// 读取包裹配置
var packageNodeList = root.GetElementsByTagName(XmlPackage);
foreach (var packageNode in packageNodeList)
{
XmlElement packageElement = packageNode as XmlElement;
if (packageElement.HasAttribute(XmlSupportExtensionless) == false)
packageElement.SetAttribute(XmlSupportExtensionless, "True");
}
// 更新版本
root.SetAttribute(XmlVersion, "v2025.8.28");
return UpdateXmlConfig(xmlDoc);
}
return false;
}
}

View File

@@ -25,6 +25,11 @@ namespace YooAsset.Editor
/// </summary>
public bool EnableAddressable = false;
/// <summary>
/// 支持无后缀名的资源定位地址
/// </summary>
public bool SupportExtensionless = true;
/// <summary>
/// 资源定位地址大小写不敏感
/// </summary>

View File

@@ -111,6 +111,7 @@ namespace YooAsset.Editor
command.UniqueBundleName = UniqueBundleName;
command.UseAssetDependencyDB = useAssetDependencyDB;
command.EnableAddressable = package.EnableAddressable;
command.SupportExtensionless = package.SupportExtensionless;
command.LocationToLower = package.LocationToLower;
command.IncludeAssetGUID = package.IncludeAssetGUID;
command.AutoCollectShaders = package.AutoCollectShaders;

View File

@@ -38,6 +38,7 @@ namespace YooAsset.Editor
private VisualElement _setting2Container;
private Toggle _enableAddressableToogle;
private Toggle _supportExtensionlessToogle;
private Toggle _locationToLowerToogle;
private Toggle _includeAssetGUIDToogle;
private Toggle _autoCollectShadersToogle;
@@ -131,6 +132,17 @@ namespace YooAsset.Editor
RefreshWindow();
}
});
_supportExtensionlessToogle = root.Q<Toggle>("SupportExtensionless");
_supportExtensionlessToogle.RegisterValueChangedCallback(evt =>
{
var selectPackage = _packageListView.selectedItem as AssetBundleCollectorPackage;
if (selectPackage != null)
{
selectPackage.SupportExtensionless = evt.newValue;
AssetBundleCollectorSettingData.ModifyPackage(selectPackage);
RefreshWindow();
}
});
_locationToLowerToogle = root.Q<Toggle>("LocationToLower");
_locationToLowerToogle.RegisterValueChangedCallback(evt =>
{
@@ -224,6 +236,7 @@ namespace YooAsset.Editor
// 包裹名称
_packageNameTxt = root.Q<TextField>("PackageName");
_packageNameTxt.isDelayed = true;
_packageNameTxt.RegisterValueChangedCallback(evt =>
{
var selectPackage = _packageListView.selectedItem as AssetBundleCollectorPackage;
@@ -237,6 +250,7 @@ namespace YooAsset.Editor
// 包裹备注
_packageDescTxt = root.Q<TextField>("PackageDesc");
_packageDescTxt.isDelayed = true;
_packageDescTxt.RegisterValueChangedCallback(evt =>
{
var selectPackage = _packageListView.selectedItem as AssetBundleCollectorPackage;
@@ -274,6 +288,7 @@ namespace YooAsset.Editor
// 分组名称
_groupNameTxt = root.Q<TextField>("GroupName");
_groupNameTxt.isDelayed = true;
_groupNameTxt.RegisterValueChangedCallback(evt =>
{
var selectPackage = _packageListView.selectedItem as AssetBundleCollectorPackage;
@@ -288,6 +303,7 @@ namespace YooAsset.Editor
// 分组备注
_groupDescTxt = root.Q<TextField>("GroupDesc");
_groupDescTxt.isDelayed = true;
_groupDescTxt.RegisterValueChangedCallback(evt =>
{
var selectPackage = _packageListView.selectedItem as AssetBundleCollectorPackage;
@@ -302,6 +318,7 @@ namespace YooAsset.Editor
// 分组的资源标签
_groupTagsTxt = root.Q<TextField>("GroupTags");
_groupTagsTxt.isDelayed = true;
_groupTagsTxt.RegisterValueChangedCallback(evt =>
{
var selectPackage = _packageListView.selectedItem as AssetBundleCollectorPackage;
@@ -487,6 +504,7 @@ namespace YooAsset.Editor
_packageSettingsButton.SetEnabled(true);
_packageSettingsButton.text = $"{packageSettingName} ({selectPackage.PackageName})";
_enableAddressableToogle.SetValueWithoutNotify(selectPackage.EnableAddressable);
_supportExtensionlessToogle.SetValueWithoutNotify(selectPackage.SupportExtensionless);
_locationToLowerToogle.SetValueWithoutNotify(selectPackage.LocationToLower);
_includeAssetGUIDToogle.SetValueWithoutNotify(selectPackage.IncludeAssetGUID);
_autoCollectShadersToogle.SetValueWithoutNotify(selectPackage.AutoCollectShaders);
@@ -804,6 +822,7 @@ namespace YooAsset.Editor
var textField = new TextField();
textField.name = "TextField0";
textField.label = "User Data";
textField.isDelayed = true;
textField.style.width = 200;
elementBottom.Add(textField);
var label = textField.Q<Label>();
@@ -813,6 +832,7 @@ namespace YooAsset.Editor
var textField = new TextField();
textField.name = "TextField1";
textField.label = "Asset Tags";
textField.isDelayed = true;
textField.style.width = 100;
textField.style.marginLeft = 20;
textField.style.flexGrow = 1;
@@ -831,7 +851,7 @@ namespace YooAsset.Editor
var foldout = new Foldout();
foldout.name = "Foldout1";
foldout.value = false;
foldout.text = "Main Assets";
foldout.text = "Assets";
elementFoldout.Add(foldout);
}
@@ -864,11 +884,9 @@ namespace YooAsset.Editor
var foldout = element.Q<Foldout>("Foldout1");
foldout.RegisterValueChangedCallback(evt =>
{
if (evt.newValue)
RefreshFoldout(foldout, selectGroup, collector);
else
foldout.Clear();
RefreshFoldoutContent(foldout, selectGroup, collector);
});
RefreshFoldoutName(foldout, collector.CollectorType);
// Remove Button
var removeBtn = element.Q<Button>("Button1");
@@ -885,10 +903,7 @@ namespace YooAsset.Editor
collector.CollectPath = AssetDatabase.GetAssetPath(evt.newValue);
collector.CollectorGUID = AssetDatabase.AssetPathToGUID(collector.CollectPath);
AssetBundleCollectorSettingData.ModifyCollector(selectGroup, collector);
if (foldout.value)
{
RefreshFoldout(foldout, selectGroup, collector);
}
RefreshFoldoutContent(foldout, selectGroup, collector);
});
UIElementsTools.RefreshObjectFieldShowPath(objectField1);
@@ -899,10 +914,7 @@ namespace YooAsset.Editor
{
collector.CollectorType = EditorTools.NameToEnum<ECollectorType>(evt.newValue);
AssetBundleCollectorSettingData.ModifyCollector(selectGroup, collector);
if (foldout.value)
{
RefreshFoldout(foldout, selectGroup, collector);
}
RefreshFoldoutContent(foldout, selectGroup, collector);
if (collector.CollectorType == ECollectorType.MainAssetCollector)
textTags.SetEnabled(true);
@@ -921,10 +933,7 @@ namespace YooAsset.Editor
{
collector.AddressRuleName = evt.newValue.ClassName;
AssetBundleCollectorSettingData.ModifyCollector(selectGroup, collector);
if (foldout.value)
{
RefreshFoldout(foldout, selectGroup, collector);
}
RefreshFoldoutContent(foldout, selectGroup, collector);
});
}
@@ -937,10 +946,7 @@ namespace YooAsset.Editor
{
collector.PackRuleName = evt.newValue.ClassName;
AssetBundleCollectorSettingData.ModifyCollector(selectGroup, collector);
if (foldout.value)
{
RefreshFoldout(foldout, selectGroup, collector);
}
RefreshFoldoutContent(foldout, selectGroup, collector);
});
// Filter Rule
@@ -952,10 +958,7 @@ namespace YooAsset.Editor
{
collector.FilterRuleName = evt.newValue.ClassName;
AssetBundleCollectorSettingData.ModifyCollector(selectGroup, collector);
if (foldout.value)
{
RefreshFoldout(foldout, selectGroup, collector);
}
RefreshFoldoutContent(foldout, selectGroup, collector);
});
// UserData
@@ -976,61 +979,101 @@ namespace YooAsset.Editor
AssetBundleCollectorSettingData.ModifyCollector(selectGroup, collector);
});
}
private void RefreshFoldout(Foldout foldout, AssetBundleCollectorGroup group, AssetBundleCollector collector)
private void RefreshFoldoutName(Foldout foldout, ECollectorType collectorType, int elementNumber = -1)
{
if (collectorType == ECollectorType.MainAssetCollector)
{
if (elementNumber >= 0)
foldout.text = $"Main Assets ({elementNumber})";
else
foldout.text = $"Main Assets";
}
else if (collectorType == ECollectorType.StaticAssetCollector)
{
if (elementNumber >= 0)
foldout.text = $"Static Assets ({elementNumber})";
else
foldout.text = $"Static Assets";
}
else if (collectorType == ECollectorType.DependAssetCollector)
{
if (elementNumber >= 0)
foldout.text = $"Depend Assets ({elementNumber})";
else
foldout.text = $"Depend Assets";
}
else
{
throw new System.NotImplementedException(collectorType.ToString());
}
}
private void RefreshFoldoutContent(Foldout foldout, AssetBundleCollectorGroup group, AssetBundleCollector collector)
{
RefreshFoldoutName(foldout, collector.CollectorType);
// 折叠栏不可见
if (foldout.value == false)
{
foldout.Clear();
return;
}
// 清空旧元素
foldout.Clear();
// 检测配置是否有效
if (collector.IsValid() == false)
{
collector.CheckConfigError();
return;
}
if (collector.CollectorType == ECollectorType.MainAssetCollector || collector.CollectorType == ECollectorType.StaticAssetCollector)
List<CollectAssetInfo> collectAssetInfos = null;
try
{
List<CollectAssetInfo> collectAssetInfos = null;
IIgnoreRule ignoreRule = AssetBundleCollectorSettingData.GetIgnoreRuleInstance(_ignoreRulePopupField.value.ClassName);
string packageName = _packageNameTxt.value;
var command = new CollectCommand(packageName, ignoreRule);
command.SetFlag(ECollectFlags.IgnoreGetDependencies, true);
command.UniqueBundleName = _uniqueBundleNameToogle.value;
command.EnableAddressable = _enableAddressableToogle.value;
command.SupportExtensionless = _supportExtensionlessToogle.value;
command.LocationToLower = _locationToLowerToogle.value;
command.IncludeAssetGUID = _includeAssetGUIDToogle.value;
command.AutoCollectShaders = _autoCollectShadersToogle.value;
try
collector.CheckConfigError();
collectAssetInfos = collector.GetAllCollectAssets(command, group);
}
catch (System.Exception e)
{
Debug.LogError(e.ToString());
}
if (collectAssetInfos != null)
{
bool showAdress = false;
if (_enableAddressableToogle.value && collector.CollectorType == ECollectorType.MainAssetCollector)
showAdress = true;
RefreshFoldoutName(foldout, collector.CollectorType, collectAssetInfos.Count);
foreach (var collectAsset in collectAssetInfos)
{
IIgnoreRule ignoreRule = AssetBundleCollectorSettingData.GetIgnoreRuleInstance(_ignoreRulePopupField.value.ClassName);
string packageName = _packageNameTxt.value;
var command = new CollectCommand(packageName, ignoreRule);
command.SimulateBuild = true;
command.UniqueBundleName = _uniqueBundleNameToogle.value;
command.UseAssetDependencyDB = true;
command.EnableAddressable = _enableAddressableToogle.value;
command.LocationToLower = _locationToLowerToogle.value;
command.IncludeAssetGUID = _includeAssetGUIDToogle.value;
command.AutoCollectShaders = _autoCollectShadersToogle.value;
VisualElement elementRow = new VisualElement();
elementRow.style.flexDirection = FlexDirection.Row;
foldout.Add(elementRow);
collector.CheckConfigError();
collectAssetInfos = collector.GetAllCollectAssets(command, group);
}
catch (System.Exception e)
{
Debug.LogError(e.ToString());
}
string showInfo = collectAsset.AssetInfo.AssetPath;
if (showAdress)
showInfo = $"[{collectAsset.Address}] {collectAsset.AssetInfo.AssetPath}";
if (collectAssetInfos != null)
{
foreach (var collectAsset in collectAssetInfos)
{
VisualElement elementRow = new VisualElement();
elementRow.style.flexDirection = FlexDirection.Row;
foldout.Add(elementRow);
string showInfo = collectAsset.AssetInfo.AssetPath;
if (_enableAddressableToogle.value)
showInfo = $"[{collectAsset.Address}] {collectAsset.AssetInfo.AssetPath}";
var label = new Label();
label.text = showInfo;
label.style.width = 300;
label.style.marginLeft = 0;
label.style.flexGrow = 1;
elementRow.Add(label);
}
var label = new Label();
label.text = showInfo;
label.style.width = 300;
label.style.marginLeft = 0;
label.style.flexGrow = 1;
elementRow.Add(label);
}
}
}

View File

@@ -19,6 +19,7 @@
<ui:Button text="Package Settings" display-tooltip-when-elided="true" name="PackageSettingsButton" />
<ui:VisualElement name="PublicContainer2">
<ui:Toggle label="Enable Addressable" name="EnableAddressable" style="width: 196px; -unity-text-align: middle-left;" />
<ui:Toggle label="Support Extensionless" name="SupportExtensionless" style="width: 196px; -unity-text-align: middle-left;" />
<ui:Toggle label="Location To Lower" name="LocationToLower" style="width: 196px; -unity-text-align: middle-left;" />
<ui:Toggle label="Include Asset GUID" name="IncludeAssetGUID" style="width: 196px; -unity-text-align: middle-left;" />
<ui:Toggle label="Auto Collect Shaders" name="AutoCollectShaders" value="true" style="width: 196px; -unity-text-align: middle-left;" />

View File

@@ -1,6 +1,26 @@

namespace YooAsset.Editor
{
public enum ECollectFlags
{
None = 0,
/// <summary>
/// 不收集依赖资源
/// </summary>
IgnoreGetDependencies = 1 << 0,
/// <summary>
/// 忽略静态收集器
/// </summary>
IgnoreStaticCollector = 1 << 1,
/// <summary>
/// 忽略依赖收集器
/// </summary>
IgnoreDependCollector = 1 << 2,
}
public class CollectCommand
{
/// <summary>
@@ -17,7 +37,20 @@ namespace YooAsset.Editor
/// <summary>
/// 模拟构建模式
/// </summary>
public bool SimulateBuild { set; get; }
public bool SimulateBuild
{
set
{
SetFlag(ECollectFlags.IgnoreGetDependencies, value);
SetFlag(ECollectFlags.IgnoreStaticCollector, value);
SetFlag(ECollectFlags.IgnoreDependCollector, value);
}
}
/// <summary>
/// 窗口收集模式
/// </summary>
public int CollectFlags { set; get; } = 0;
/// <summary>
/// 资源包名唯一化
@@ -34,6 +67,11 @@ namespace YooAsset.Editor
/// </summary>
public bool EnableAddressable { set; get; }
/// <summary>
/// 支持无后缀名的资源定位地址
/// </summary>
public bool SupportExtensionless { set; get; }
/// <summary>
/// 资源定位地址大小写不敏感
/// </summary>
@@ -65,5 +103,24 @@ namespace YooAsset.Editor
PackageName = packageName;
IgnoreRule = ignoreRule;
}
/// <summary>
/// 设置标记位
/// </summary>
public void SetFlag(ECollectFlags flag, bool isOn)
{
if (isOn)
CollectFlags |= (int)flag; // 开启指定标志位
else
CollectFlags &= ~(int)flag; // 关闭指定标志位
}
/// <summary>
/// 查询标记位
/// </summary>
public bool IsFlagSet(ECollectFlags flag)
{
return (CollectFlags & (int)flag) != 0;
}
}
}

View File

@@ -23,7 +23,13 @@ namespace YooAsset.Editor
public interface IFilterRule
{
/// <summary>
/// 是否为收集资源
/// 搜寻的资源类型
/// 说明:使用引擎方法搜索获取所有资源列表
/// </summary>
string FindAssetType { get; }
/// <summary>
/// 验证搜寻的资源是否为收集资源
/// </summary>
/// <returns>如果收集该资源返回TRUE</returns>
bool IsCollectAsset(FilterRuleData data);

View File

@@ -9,6 +9,11 @@ namespace YooAsset.Editor
[DisplayName("收集所有资源")]
public class CollectAll : IFilterRule
{
public string FindAssetType
{
get { return EAssetSearchType.All.ToString(); }
}
public bool IsCollectAsset(FilterRuleData data)
{
return true;
@@ -18,6 +23,11 @@ namespace YooAsset.Editor
[DisplayName("收集场景")]
public class CollectScene : IFilterRule
{
public string FindAssetType
{
get { return EAssetSearchType.Scene.ToString(); }
}
public bool IsCollectAsset(FilterRuleData data)
{
string extension = Path.GetExtension(data.AssetPath);
@@ -28,6 +38,11 @@ namespace YooAsset.Editor
[DisplayName("收集预制体")]
public class CollectPrefab : IFilterRule
{
public string FindAssetType
{
get { return EAssetSearchType.Prefab.ToString(); }
}
public bool IsCollectAsset(FilterRuleData data)
{
return Path.GetExtension(data.AssetPath) == ".prefab";
@@ -37,6 +52,11 @@ namespace YooAsset.Editor
[DisplayName("收集精灵类型的纹理")]
public class CollectSprite : IFilterRule
{
public string FindAssetType
{
get { return EAssetSearchType.Sprite.ToString(); }
}
public bool IsCollectAsset(FilterRuleData data)
{
var mainAssetType = AssetDatabase.GetMainAssetTypeAtPath(data.AssetPath);
@@ -58,6 +78,11 @@ namespace YooAsset.Editor
[DisplayName("收集着色器")]
public class CollectShader : IFilterRule
{
public string FindAssetType
{
get { return EAssetSearchType.Shader.ToString(); }
}
public bool IsCollectAsset(FilterRuleData data)
{
return Path.GetExtension(data.AssetPath) == ".shader";
@@ -67,6 +92,11 @@ namespace YooAsset.Editor
[DisplayName("收集着色器变种集合")]
public class CollectShaderVariants : IFilterRule
{
public string FindAssetType
{
get { return EAssetSearchType.All.ToString(); }
}
public bool IsCollectAsset(FilterRuleData data)
{
return Path.GetExtension(data.AssetPath) == ".shadervariants";

View File

@@ -17,16 +17,25 @@ namespace YooAsset.Editor
public const string RawFileExtension = "rawfile";
/// <summary>
/// Unity着色器资源包名称
/// 默认的Unity着色器资源包名称
/// </summary>
public const string ShadersBundleName = "unityshaders";
/// <summary>
/// 默认的Unity脚本资源包名称
/// </summary>
public const string MonosBundleName = "unitymonos";
public static PackRuleResult CreateShadersPackRuleResult()
{
PackRuleResult result = new PackRuleResult(ShadersBundleName, AssetBundleFileExtension);
return result;
}
public static PackRuleResult CreateMonosPackRuleResult()
{
PackRuleResult result = new PackRuleResult(MonosBundleName, AssetBundleFileExtension);
return result;
}
}
/// <summary>

View File

@@ -26,7 +26,7 @@ namespace YooAsset.Editor
/// <summary>
/// 文件校验码
/// </summary>
public string FileCRC;
public uint FileCRC;
/// <summary>
/// 文件大小(字节数)

View File

@@ -61,6 +61,7 @@ namespace YooAsset.Editor
// 收集器配置
public bool UniqueBundleName;
public bool EnableAddressable;
public bool SupportExtensionless;
public bool LocationToLower;
public bool IncludeAssetGUID;
public bool AutoCollectShaders;
@@ -80,6 +81,7 @@ namespace YooAsset.Editor
public ECompressOption CompressOption;
public bool DisableWriteTypeTree;
public bool IgnoreTypeTreeChanges;
public bool ReplaceAssetPathWithAddress;
public bool WriteLinkXML = true;
public string CacheServerHost;
public int CacheServerPort;

View File

@@ -55,6 +55,7 @@ namespace YooAsset.Editor
BindListViewHeader("Collect Settings");
BindListViewItem("Unique Bundle Name", $"{buildReport.Summary.UniqueBundleName}");
BindListViewItem("Enable Addressable", $"{buildReport.Summary.EnableAddressable}");
BindListViewItem("Support Extensionless", $"{buildReport.Summary.SupportExtensionless}");
BindListViewItem("Location To Lower", $"{buildReport.Summary.LocationToLower}");
BindListViewItem("Include Asset GUID", $"{buildReport.Summary.IncludeAssetGUID}");
BindListViewItem("Auto Collect Shaders", $"{buildReport.Summary.AutoCollectShaders}");
@@ -73,6 +74,7 @@ namespace YooAsset.Editor
BindListViewItem("CompressOption", $"{buildReport.Summary.CompressOption}");
BindListViewItem("DisableWriteTypeTree", $"{buildReport.Summary.DisableWriteTypeTree}");
BindListViewItem("IgnoreTypeTreeChanges", $"{buildReport.Summary.IgnoreTypeTreeChanges}");
BindListViewItem("ReplaceAssetPathWithAddress", $"{buildReport.Summary.ReplaceAssetPathWithAddress}");
BindListViewItem(string.Empty, string.Empty);
BindListViewHeader("Build Results");

View File

@@ -62,6 +62,17 @@ namespace YooAsset.Editor
return false;
}
/// <summary>
/// 是否为图集资源
/// </summary>
public bool IsSpriteAtlas()
{
if (AssetType == typeof(UnityEngine.U2D.SpriteAtlas))
return true;
else
return false;
}
public int CompareTo(AssetInfo other)
{
return this.AssetPath.CompareTo(other.AssetPath);

View File

@@ -39,6 +39,7 @@ namespace YooAsset.Editor
Shader,
Sprite,
Texture,
RenderTexture,
VideoClip,
}

View File

@@ -169,6 +169,28 @@ namespace YooAsset.Editor
/// <param name="searchInFolders">指定搜索的文件夹列表</param>
/// <returns>返回搜集到的资源路径列表</returns>
public static string[] FindAssets(EAssetSearchType searchType, string[] searchInFolders)
{
return FindAssets(searchType.ToString(), searchInFolders);
}
/// <summary>
/// 搜集资源
/// </summary>
/// <param name="searchType">搜集的资源类型</param>
/// <param name="searchInFolder">指定搜索的文件夹</param>
/// <returns>返回搜集到的资源路径列表</returns>
public static string[] FindAssets(EAssetSearchType searchType, string searchInFolder)
{
return FindAssets(searchType.ToString(), new string[] { searchInFolder });
}
/// <summary>
/// 搜集资源
/// </summary>
/// <param name="searchType">搜集的资源类型</param>
/// <param name="searchInFolders">指定搜索的文件夹列表</param>
/// <returns>返回搜集到的资源路径列表</returns>
public static string[] FindAssets(string searchType, string[] searchInFolders)
{
// 注意AssetDatabase.FindAssets()不支持末尾带分隔符的文件夹路径
for (int i = 0; i < searchInFolders.Length; i++)
@@ -179,7 +201,7 @@ namespace YooAsset.Editor
// 注意:获取指定目录下的所有资源对象(包括子文件夹)
string[] guids;
if (searchType == EAssetSearchType.All)
if (string.IsNullOrEmpty(searchType) || searchType == EAssetSearchType.All.ToString())
guids = AssetDatabase.FindAssets(string.Empty, searchInFolders);
else
guids = AssetDatabase.FindAssets($"t:{searchType}", searchInFolders);
@@ -206,7 +228,7 @@ namespace YooAsset.Editor
/// <param name="searchType">搜集的资源类型</param>
/// <param name="searchInFolder">指定搜索的文件夹</param>
/// <returns>返回搜集到的资源路径列表</returns>
public static string[] FindAssets(EAssetSearchType searchType, string searchInFolder)
public static string[] FindAssets(string searchType, string searchInFolder)
{
return FindAssets(searchType, new string[] { searchInFolder });
}

View File

@@ -37,13 +37,17 @@ namespace YooAsset
string url;
// 获取对应平台的URL地址
// 说明:苹果不同设备上操作系统不同。
// 说明iPhone和iPod对应的是iOS系统。
// 说明iPad对应的是iPadOS系统。
// 说明AppleTV对应的是tvOS系统。
#if UNITY_EDITOR_OSX
url = StringUtility.Format("file://{0}", path);
#elif UNITY_EDITOR
#elif UNITY_EDITOR_WIN
url = StringUtility.Format("file:///{0}", path);
#elif UNITY_WEBGL
url = path;
#elif UNITY_IPHONE
#elif UNITY_IOS || UNITY_IPHONE
url = StringUtility.Format("file://{0}", path);
#elif UNITY_ANDROID
if (path.StartsWith("jar:file://"))
@@ -65,12 +69,17 @@ namespace YooAsset
else
url = StringUtility.Format("file://{0}", path);
}
#elif UNITY_STANDALONE_OSX
url = new System.Uri(path).ToString();
#elif UNITY_STANDALONE || UNITY_WSA
#elif UNITY_WSA
url = StringUtility.Format("file:///{0}", path);
#elif UNITY_TVOS
url = StringUtility.Format("file:///{0}", path);
#elif UNITY_STANDALONE_OSX
url = new System.Uri(path).ToString();
#elif UNITY_STANDALONE_WIN
url = StringUtility.Format("file:///{0}", path);
#elif UNITY_STANDALONE_LINUX
url = StringUtility.Format("file:///root/{0}", path);
#else
throw new System.NotImplementedException();
#endif

View File

@@ -0,0 +1,65 @@
using UnityEngine.Networking;
using UnityEngine;
namespace YooAsset
{
internal class UnityVirtualBundleRequestOperation : UnityWebRequestOperation
{
protected enum ESteps
{
None,
Download,
Done,
}
private readonly PackageBundle _bundle;
private readonly int _downloadSpeed;
private ESteps _steps = ESteps.None;
internal UnityVirtualBundleRequestOperation(PackageBundle packageBundle, int downloadSpeed, string url) : base(url)
{
_bundle = packageBundle;
_downloadSpeed = downloadSpeed;
}
internal override void InternalStart()
{
_steps = ESteps.Download;
}
internal override void InternalUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.Download)
{
// 模拟下载进度
float progress = 0;
if (DownloadedBytes > 0)
progress = DownloadedBytes / _bundle.FileSize;
long downloadBytes = (long)((double)_downloadSpeed * Time.deltaTime);
Progress = progress;
DownloadProgress = progress;
DownloadedBytes += downloadBytes;
if (DownloadedBytes < _bundle.FileSize)
return;
Progress = 1f;
DownloadProgress = 1f;
DownloadedBytes = _bundle.FileSize;
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
}
internal override void InternalWaitForAsyncComplete()
{
if (_steps != ESteps.Done)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Try load bundle {_bundle.BundleName} from remote !";
}
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 8ac57bde14f2e1a4e9323751a7157ed7
guid: 9e71e850eded0da43906cb4f7cb75629
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -63,14 +63,19 @@ namespace YooAsset
{
"link.xml",
"buildlogtep.json",
$"{packageName}.version",
$"{packageName}_{packageVersion}.bytes",
$"{packageName}_{packageVersion}.hash",
$"{packageName}_{packageVersion}.json",
$"{packageName}_{packageVersion}.report",
DefaultBuildinFileSystemDefine.BuildinCatalogJsonFileName,
DefaultBuildinFileSystemDefine.BuildinCatalogBinaryFileName
};
string packageVersionFileName = YooAssetSettingsData.GetPackageVersionFileName(packageName);
string packageHashFileName = YooAssetSettingsData.GetPackageHashFileName(packageName, packageVersion);
string manifestBinaryFIleName = YooAssetSettingsData.GetManifestBinaryFileName(packageName, packageVersion);
string manifestJsonFIleName = YooAssetSettingsData.GetManifestJsonFileName(packageName, packageVersion);
string reportFileName = YooAssetSettingsData.GetBuildReportFileName(packageName, packageVersion);
whiteFileList.Add(packageVersionFileName);
whiteFileList.Add(packageHashFileName);
whiteFileList.Add(manifestBinaryFIleName);
whiteFileList.Add(manifestJsonFIleName);
whiteFileList.Add(reportFileName);
// 记录所有内置资源文件
DirectoryInfo rootDirectory = new DirectoryInfo(packageDirectory);

View File

@@ -53,15 +53,20 @@ namespace YooAsset
}
#region
/// <summary>
/// 自定义参数:覆盖安装缓存清理模式
/// </summary>
public EOverwriteInstallClearMode InstallClearMode { private set; get; } = EOverwriteInstallClearMode.ClearAllManifestFiles;
/// <summary>
/// 自定义参数:初始化的时候缓存文件校验级别
/// </summary>
public EFileVerifyLevel FileVerifyLevel { private set; get; } = EFileVerifyLevel.Middle;
/// <summary>
/// 自定义参数:覆盖安装缓存清理模式
/// 自定义参数:初始化的时候缓存文件校验最大并发数
/// </summary>
public EOverwriteInstallClearMode InstallClearMode { private set; get; } = EOverwriteInstallClearMode.ClearAllManifestFiles;
public int FileVerifyMaxConcurrency { private set; get; } = int.MaxValue;
/// <summary>
/// 自定义参数:数据文件追加文件格式
@@ -85,7 +90,7 @@ namespace YooAsset
public string CopyBuildinPackageManifestDestRoot { private set; get; }
/// <summary>
/// 自定义参数:解密方法
/// 自定义参数:解密服务接口的实例
/// </summary>
public IDecryptionServices DecryptionServices { private set; get; }
@@ -95,7 +100,7 @@ namespace YooAsset
public IManifestRestoreServices ManifestServices { private set; get; }
/// <summary>
/// 自定义参数:拷贝内置文件服务
/// 自定义参数:拷贝内置文件接口的实例
/// </summary>
public ICopyLocalFileServices CopyLocalFileServices { private set; get; }
#endregion
@@ -156,13 +161,18 @@ namespace YooAsset
public virtual void SetParameter(string name, object value)
{
if (name == FileSystemParametersDefine.FILE_VERIFY_LEVEL)
if (name == FileSystemParametersDefine.INSTALL_CLEAR_MODE)
{
InstallClearMode = (EOverwriteInstallClearMode)value;
}
else if (name == FileSystemParametersDefine.FILE_VERIFY_LEVEL)
{
FileVerifyLevel = (EFileVerifyLevel)value;
}
else if (name == FileSystemParametersDefine.INSTALL_CLEAR_MODE)
else if (name == FileSystemParametersDefine.FILE_VERIFY_MAX_CONCURRENCY)
{
InstallClearMode = (EOverwriteInstallClearMode)value;
int convertValue = Convert.ToInt32(value);
FileVerifyMaxConcurrency = Mathf.Clamp(convertValue, 1, int.MaxValue);
}
else if (name == FileSystemParametersDefine.APPEND_FILE_EXTENSION)
{
@@ -210,8 +220,9 @@ namespace YooAsset
var remoteServices = new DefaultUnpackRemoteServices(_packageRoot);
_unpackFileSystem = new DefaultUnpackFileSystem();
_unpackFileSystem.SetParameter(FileSystemParametersDefine.REMOTE_SERVICES, remoteServices);
_unpackFileSystem.SetParameter(FileSystemParametersDefine.FILE_VERIFY_LEVEL, FileVerifyLevel);
_unpackFileSystem.SetParameter(FileSystemParametersDefine.INSTALL_CLEAR_MODE, InstallClearMode);
_unpackFileSystem.SetParameter(FileSystemParametersDefine.FILE_VERIFY_LEVEL, FileVerifyLevel);
_unpackFileSystem.SetParameter(FileSystemParametersDefine.FILE_VERIFY_MAX_CONCURRENCY, FileVerifyMaxConcurrency);
_unpackFileSystem.SetParameter(FileSystemParametersDefine.APPEND_FILE_EXTENSION, AppendFileExtension);
_unpackFileSystem.SetParameter(FileSystemParametersDefine.DECRYPTION_SERVICES, DecryptionServices);
_unpackFileSystem.SetParameter(FileSystemParametersDefine.COPY_LOCAL_FILE_SERVICES, CopyLocalFileServices);
@@ -335,6 +346,27 @@ namespace YooAsset
#endif
}
/// <summary>
/// 是否属于解压资源包文件
/// </summary>
protected virtual bool IsUnpackBundleFile(PackageBundle bundle)
{
if (Belong(bundle) == false)
return false;
#if UNITY_ANDROID || UNITY_OPENHARMONY
if (bundle.Encrypted)
return true;
if (bundle.BundleType == (int)EBuildBundleType.RawBundle)
return true;
return false;
#else
return false;
#endif
}
#region
protected string GetDefaultBuildinPackageRoot(string packageName)
{
@@ -370,27 +402,6 @@ namespace YooAsset
return PathUtility.Combine(_packageRoot, DefaultBuildinFileSystemDefine.BuildinCatalogBinaryFileName);
}
/// <summary>
/// 是否属于解压资源包文件
/// </summary>
protected bool IsUnpackBundleFile(PackageBundle bundle)
{
if (Belong(bundle) == false)
return false;
#if UNITY_ANDROID
if (bundle.Encrypted)
return true;
if (bundle.BundleType == (int)EBuildBundleType.RawBundle)
return true;
return false;
#else
return false;
#endif
}
/// <summary>
/// 记录文件信息
/// </summary>

View File

@@ -8,14 +8,18 @@ namespace YooAsset
private enum ESteps
{
None,
CopyBuildinManifest,
LoadBuildinPackageVersion,
CopyBuildinPackageHash,
CopyBuildinPackageManifest,
InitUnpackFileSystem,
LoadCatalogFile,
Done,
}
private readonly DefaultBuildinFileSystem _fileSystem;
private CopyBuildinPackageManifestOperation _copyBuildinPackageManifestOp;
private RequestBuildinPackageVersionOperation _requestBuildinPackageVersionOp;
private CopyBuildinFileOperation _copyBuildinHashFileOp;
private CopyBuildinFileOperation _copyBuildinManifestFileOp;
private FSInitializeFileSystemOperation _initUnpackFIleSystemOp;
private LoadBuildinCatalogFileOperation _loadBuildinCatalogFileOp;
private ESteps _steps = ESteps.None;
@@ -32,7 +36,7 @@ namespace YooAsset
Error = $"{nameof(DefaultBuildinFileSystem)} is not support WEBGL platform !";
#else
if (_fileSystem.CopyBuildinPackageManifest)
_steps = ESteps.CopyBuildinManifest;
_steps = ESteps.LoadBuildinPackageVersion;
else
_steps = ESteps.InitUnpackFileSystem;
#endif
@@ -42,20 +46,76 @@ namespace YooAsset
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.CopyBuildinManifest)
if (_steps == ESteps.LoadBuildinPackageVersion)
{
if (_copyBuildinPackageManifestOp == null)
if (_requestBuildinPackageVersionOp == null)
{
_copyBuildinPackageManifestOp = new CopyBuildinPackageManifestOperation(_fileSystem);
_copyBuildinPackageManifestOp.StartOperation();
AddChildOperation(_copyBuildinPackageManifestOp);
_requestBuildinPackageVersionOp = new RequestBuildinPackageVersionOperation(_fileSystem);
_requestBuildinPackageVersionOp.StartOperation();
AddChildOperation(_requestBuildinPackageVersionOp);
}
_copyBuildinPackageManifestOp.UpdateOperation();
if (_copyBuildinPackageManifestOp.IsDone == false)
_requestBuildinPackageVersionOp.UpdateOperation();
if (_requestBuildinPackageVersionOp.IsDone == false)
return;
if (_copyBuildinPackageManifestOp.Status == EOperationStatus.Succeed)
if (_requestBuildinPackageVersionOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.CopyBuildinPackageHash;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _requestBuildinPackageVersionOp.Error;
}
}
if (_steps == ESteps.CopyBuildinPackageHash)
{
if (_copyBuildinHashFileOp == null)
{
string packageVersion = _requestBuildinPackageVersionOp.PackageVersion;
string destFilePath = GetCopyPackageHashDestPath(packageVersion);
string sourceFilePath = _fileSystem.GetBuildinPackageHashFilePath(packageVersion);
_copyBuildinHashFileOp = new CopyBuildinFileOperation(sourceFilePath, destFilePath);
_copyBuildinHashFileOp.StartOperation();
AddChildOperation(_copyBuildinHashFileOp);
}
_copyBuildinHashFileOp.UpdateOperation();
if (_copyBuildinHashFileOp.IsDone == false)
return;
if (_copyBuildinHashFileOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.CopyBuildinPackageManifest;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _copyBuildinHashFileOp.Error;
}
}
if (_steps == ESteps.CopyBuildinPackageManifest)
{
if (_copyBuildinManifestFileOp == null)
{
string packageVersion = _requestBuildinPackageVersionOp.PackageVersion;
string destFilePath = GetCopyPackageManifestDestPath(packageVersion);
string sourceFilePath = _fileSystem.GetBuildinPackageManifestFilePath(packageVersion);
_copyBuildinManifestFileOp = new CopyBuildinFileOperation(sourceFilePath, destFilePath);
_copyBuildinManifestFileOp.StartOperation();
AddChildOperation(_copyBuildinManifestFileOp);
}
_copyBuildinManifestFileOp.UpdateOperation();
if (_copyBuildinManifestFileOp.IsDone == false)
return;
if (_copyBuildinManifestFileOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.InitUnpackFileSystem;
}
@@ -63,7 +123,7 @@ namespace YooAsset
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _copyBuildinPackageManifestOp.Error;
Error = _copyBuildinManifestFileOp.Error;
}
}
@@ -116,6 +176,30 @@ namespace YooAsset
if (_loadBuildinCatalogFileOp.Status == EOperationStatus.Succeed)
{
var catalog = _loadBuildinCatalogFileOp.Catalog;
if (catalog == null)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = "Fatal error : catalog is null !";
return;
}
if (catalog.PackageName != _fileSystem.PackageName)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Catalog file package name {catalog.PackageName} cannot match the file system package name {_fileSystem.PackageName}";
return;
}
foreach (var wrapper in catalog.Wrappers)
{
var fileWrapper = new DefaultBuildinFileSystem.FileWrapper(wrapper.FileName);
_fileSystem.RecordCatalogFile(wrapper.BundleGUID, fileWrapper);
}
YooLogger.Log($"Package '{_fileSystem.PackageName}' buildin catalog files count : {catalog.Wrappers.Count}");
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
@@ -127,5 +211,28 @@ namespace YooAsset
}
}
}
private string GetCopyManifestFileRoot()
{
string destRoot = _fileSystem.CopyBuildinPackageManifestDestRoot;
if (string.IsNullOrEmpty(destRoot))
{
string defaultCacheRoot = YooAssetSettingsData.GetYooDefaultCacheRoot();
destRoot = PathUtility.Combine(defaultCacheRoot, _fileSystem.PackageName, DefaultCacheFileSystemDefine.ManifestFilesFolderName);
}
return destRoot;
}
private string GetCopyPackageHashDestPath(string packageVersion)
{
string fileRoot = GetCopyManifestFileRoot();
string fileName = YooAssetSettingsData.GetPackageHashFileName(_fileSystem.PackageName, packageVersion);
return PathUtility.Combine(fileRoot, fileName);
}
private string GetCopyPackageManifestDestPath(string packageVersion)
{
string fileRoot = GetCopyManifestFileRoot();
string fileName = YooAssetSettingsData.GetManifestBinaryFileName(_fileSystem.PackageName, packageVersion);
return PathUtility.Combine(fileRoot, fileName);
}
}
}

View File

@@ -0,0 +1,102 @@
using System;
using System.IO;
namespace YooAsset
{
internal class CopyBuildinFileOperation : AsyncOperationBase
{
private enum ESteps
{
None,
CheckFileExist,
TryCopyFile,
UnpackFile,
Done,
}
private UnityWebFileRequestOperation _webFileRequestOp;
private readonly string _sourceFilePath;
private readonly string _destFilePath;
private ESteps _steps = ESteps.None;
public CopyBuildinFileOperation(string sourceFilePath, string destFilePath)
{
_sourceFilePath = sourceFilePath;
_destFilePath = destFilePath;
}
internal override void InternalStart()
{
_steps = ESteps.CheckFileExist;
}
internal override void InternalUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.CheckFileExist)
{
if (File.Exists(_destFilePath))
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.TryCopyFile;
}
}
if (_steps == ESteps.TryCopyFile)
{
if (File.Exists(_sourceFilePath))
{
try
{
var directory = Path.GetDirectoryName(_destFilePath);
if (Directory.Exists(directory) == false)
Directory.CreateDirectory(directory);
File.Copy(_sourceFilePath, _destFilePath, true);
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
catch (Exception ex)
{
YooLogger.Warning($"Failed copy buildin file : {ex.Message}");
_steps = ESteps.UnpackFile;
}
}
else
{
_steps = ESteps.UnpackFile;
}
}
if (_steps == ESteps.UnpackFile)
{
if (_webFileRequestOp == null)
{
string url = DownloadSystemHelper.ConvertToWWWPath(_sourceFilePath);
_webFileRequestOp = new UnityWebFileRequestOperation(url, _destFilePath, 60);
_webFileRequestOp.StartOperation();
AddChildOperation(_webFileRequestOp);
}
_webFileRequestOp.UpdateOperation();
if (_webFileRequestOp.IsDone == false)
return;
if (_webFileRequestOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _webFileRequestOp.Error;
}
}
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 69f62f6b4185d06498f96aa272e9b926
guid: bf44368bc5c2bf1479c36d82e931c295
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -1,173 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
namespace YooAsset
{
internal class CopyBuildinPackageManifestOperation : AsyncOperationBase
{
private enum ESteps
{
None,
RequestPackageVersion,
CheckHashFile,
UnpackHashFile,
CheckManifestFile,
UnpackManifestFile,
Done,
}
private readonly DefaultBuildinFileSystem _fileSystem;
private RequestBuildinPackageVersionOperation _requestBuildinPackageVersionOp;
private UnityWebFileRequestOperation _hashWebFileRequestOp;
private UnityWebFileRequestOperation _manifestWebFileRequestOp;
private string _buildinPackageVersion;
private ESteps _steps = ESteps.None;
public CopyBuildinPackageManifestOperation(DefaultBuildinFileSystem fileSystem)
{
_fileSystem = fileSystem;
}
internal override void InternalStart()
{
_steps = ESteps.RequestPackageVersion;
}
internal override void InternalUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.RequestPackageVersion)
{
if (_requestBuildinPackageVersionOp == null)
{
_requestBuildinPackageVersionOp = new RequestBuildinPackageVersionOperation(_fileSystem);
_requestBuildinPackageVersionOp.StartOperation();
AddChildOperation(_requestBuildinPackageVersionOp);
}
_requestBuildinPackageVersionOp.UpdateOperation();
if (_requestBuildinPackageVersionOp.IsDone == false)
return;
if (_requestBuildinPackageVersionOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.CheckHashFile;
_buildinPackageVersion = _requestBuildinPackageVersionOp.PackageVersion;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _requestBuildinPackageVersionOp.Error;
}
}
if (_steps == ESteps.CheckHashFile)
{
string hashFilePath = GetCopyPackageHashDestPath(_buildinPackageVersion);
if (File.Exists(hashFilePath))
{
_steps = ESteps.CheckManifestFile;
return;
}
_steps = ESteps.UnpackHashFile;
}
if (_steps == ESteps.UnpackHashFile)
{
if (_hashWebFileRequestOp == null)
{
string sourcePath = _fileSystem.GetBuildinPackageHashFilePath(_buildinPackageVersion);
string destPath = GetCopyPackageHashDestPath(_buildinPackageVersion);
string url = DownloadSystemHelper.ConvertToWWWPath(sourcePath);
_hashWebFileRequestOp = new UnityWebFileRequestOperation(url, destPath, 60);
_hashWebFileRequestOp.StartOperation();
AddChildOperation(_hashWebFileRequestOp);
}
_hashWebFileRequestOp.UpdateOperation();
if (_hashWebFileRequestOp.IsDone == false)
return;
if (_hashWebFileRequestOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.CheckManifestFile;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _hashWebFileRequestOp.Error;
}
}
if (_steps == ESteps.CheckManifestFile)
{
string manifestFilePath = GetCopyPackageManifestDestPath(_buildinPackageVersion);
if (File.Exists(manifestFilePath))
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
return;
}
_steps = ESteps.UnpackManifestFile;
}
if (_steps == ESteps.UnpackManifestFile)
{
if (_manifestWebFileRequestOp == null)
{
string sourcePath = _fileSystem.GetBuildinPackageManifestFilePath(_buildinPackageVersion);
string destPath = GetCopyPackageManifestDestPath(_buildinPackageVersion);
string url = DownloadSystemHelper.ConvertToWWWPath(sourcePath);
_manifestWebFileRequestOp = new UnityWebFileRequestOperation(url, destPath, 60);
_manifestWebFileRequestOp.StartOperation();
AddChildOperation(_manifestWebFileRequestOp);
}
_manifestWebFileRequestOp.UpdateOperation();
if (_manifestWebFileRequestOp.IsDone == false)
return;
if (_manifestWebFileRequestOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _manifestWebFileRequestOp.Error;
}
}
}
private string GetCopyManifestFileRoot()
{
string destRoot = _fileSystem.CopyBuildinPackageManifestDestRoot;
if (string.IsNullOrEmpty(destRoot))
{
string defaultCacheRoot = YooAssetSettingsData.GetYooDefaultCacheRoot();
destRoot = PathUtility.Combine(defaultCacheRoot, _fileSystem.PackageName, DefaultCacheFileSystemDefine.ManifestFilesFolderName);
}
return destRoot;
}
private string GetCopyPackageHashDestPath(string packageVersion)
{
string fileRoot = GetCopyManifestFileRoot();
string fileName = YooAssetSettingsData.GetPackageHashFileName(_fileSystem.PackageName, packageVersion);
return PathUtility.Combine(fileRoot, fileName);
}
private string GetCopyPackageManifestDestPath(string packageVersion)
{
string fileRoot = GetCopyManifestFileRoot();
string fileName = YooAssetSettingsData.GetManifestBinaryFileName(_fileSystem.PackageName, packageVersion);
return PathUtility.Combine(fileRoot, fileName);
}
}
}

View File

@@ -1,4 +1,5 @@
using System;
using System.IO;
namespace YooAsset
{
@@ -7,29 +8,50 @@ namespace YooAsset
private enum ESteps
{
None,
RequestData,
TryLoadFileData,
RequestFileData,
LoadCatalog,
Done,
}
private readonly DefaultBuildinFileSystem _fileSystem;
private UnityWebDataRequestOperation _webDataRequestOp;
private byte[] _fileData;
private ESteps _steps = ESteps.None;
/// <summary>
/// 内置资源目录
/// </summary>
public DefaultBuildinFileCatalog Catalog;
internal LoadBuildinCatalogFileOperation(DefaultBuildinFileSystem fileSystem)
{
_fileSystem = fileSystem;
}
internal override void InternalStart()
{
_steps = ESteps.RequestData;
_steps = ESteps.TryLoadFileData;
}
internal override void InternalUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.RequestData)
if (_steps == ESteps.TryLoadFileData)
{
string filePath = _fileSystem.GetCatalogBinaryFileLoadPath();
if (File.Exists(filePath))
{
_fileData = File.ReadAllBytes(filePath);
_steps = ESteps.LoadCatalog;
}
else
{
_steps = ESteps.RequestFileData;
}
}
if (_steps == ESteps.RequestFileData)
{
if (_webDataRequestOp == null)
{
@@ -46,6 +68,7 @@ namespace YooAsset
if (_webDataRequestOp.Status == EOperationStatus.Succeed)
{
_fileData = _webDataRequestOp.Result;
_steps = ESteps.LoadCatalog;
}
else
@@ -60,22 +83,7 @@ namespace YooAsset
{
try
{
var catalog = CatalogTools.DeserializeFromBinary(_webDataRequestOp.Result);
if (catalog.PackageName != _fileSystem.PackageName)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Catalog file package name {catalog.PackageName} cannot match the file system package name {_fileSystem.PackageName}";
return;
}
foreach (var wrapper in catalog.Wrappers)
{
var fileWrapper = new DefaultBuildinFileSystem.FileWrapper(wrapper.FileName);
_fileSystem.RecordCatalogFile(wrapper.BundleGUID, fileWrapper);
}
YooLogger.Log($"Package '{_fileSystem.PackageName}' buildin catalog files count : {catalog.Wrappers.Count}");
Catalog = CatalogTools.DeserializeFromBinary(_fileData);
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}

View File

@@ -1,4 +1,5 @@

using System.IO;
namespace YooAsset
{
internal class LoadBuildinPackageManifestOperation : AsyncOperationBase
@@ -6,6 +7,7 @@ namespace YooAsset
private enum ESteps
{
None,
TryLoadFileData,
RequestFileData,
VerifyFileData,
LoadManifest,
@@ -17,6 +19,7 @@ namespace YooAsset
private readonly string _packageHash;
private UnityWebDataRequestOperation _webDataRequestOp;
private DeserializeManifestOperation _deserializer;
private byte[] _fileData;
private ESteps _steps = ESteps.None;
/// <summary>
@@ -33,13 +36,27 @@ namespace YooAsset
}
internal override void InternalStart()
{
_steps = ESteps.RequestFileData;
_steps = ESteps.TryLoadFileData;
}
internal override void InternalUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.TryLoadFileData)
{
string filePath = _fileSystem.GetBuildinPackageManifestFilePath(_packageVersion);
if (File.Exists(filePath))
{
_fileData = File.ReadAllBytes(filePath);
_steps = ESteps.VerifyFileData;
}
else
{
_steps = ESteps.RequestFileData;
}
}
if (_steps == ESteps.RequestFileData)
{
if (_webDataRequestOp == null)
@@ -57,6 +74,7 @@ namespace YooAsset
if (_webDataRequestOp.Status == EOperationStatus.Succeed)
{
_fileData = _webDataRequestOp.Result;
_steps = ESteps.VerifyFileData;
}
else
@@ -69,7 +87,7 @@ namespace YooAsset
if (_steps == ESteps.VerifyFileData)
{
if (ManifestTools.VerifyManifestData(_webDataRequestOp.Result, _packageHash))
if (ManifestTools.VerifyManifestData(_fileData, _packageHash))
{
_steps = ESteps.LoadManifest;
}
@@ -85,7 +103,7 @@ namespace YooAsset
{
if (_deserializer == null)
{
_deserializer = new DeserializeManifestOperation(_fileSystem.ManifestServices, _webDataRequestOp.Result);
_deserializer = new DeserializeManifestOperation(_fileSystem.ManifestServices, _fileData);
_deserializer.StartOperation();
AddChildOperation(_deserializer);
}

View File

@@ -1,4 +1,5 @@

using System.IO;
namespace YooAsset
{
internal class RequestBuildinPackageHashOperation : AsyncOperationBase
@@ -6,7 +7,9 @@ namespace YooAsset
private enum ESteps
{
None,
TryLoadPackageHash,
RequestPackageHash,
CheckResult,
Done,
}
@@ -28,13 +31,27 @@ namespace YooAsset
}
internal override void InternalStart()
{
_steps = ESteps.RequestPackageHash;
_steps = ESteps.TryLoadPackageHash;
}
internal override void InternalUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.TryLoadPackageHash)
{
string filePath = _fileSystem.GetBuildinPackageHashFilePath(_packageVersion);
if (File.Exists(filePath))
{
PackageHash = File.ReadAllText(filePath);
_steps = ESteps.CheckResult;
}
else
{
_steps = ESteps.RequestPackageHash;
}
}
if (_steps == ESteps.RequestPackageHash)
{
if (_webTextRequestOp == null)
@@ -53,17 +70,7 @@ namespace YooAsset
if (_webTextRequestOp.Status == EOperationStatus.Succeed)
{
PackageHash = _webTextRequestOp.Result;
if (string.IsNullOrEmpty(PackageHash))
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Buildin package hash file content is empty !";
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
_steps = ESteps.CheckResult;
}
else
{
@@ -72,6 +79,21 @@ namespace YooAsset
Error = _webTextRequestOp.Error;
}
}
if (_steps == ESteps.CheckResult)
{
if (string.IsNullOrEmpty(PackageHash))
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Buildin package hash file content is empty !";
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
}
}
}
}

View File

@@ -1,4 +1,5 @@

using System.IO;
namespace YooAsset
{
internal class RequestBuildinPackageVersionOperation : AsyncOperationBase
@@ -6,7 +7,9 @@ namespace YooAsset
private enum ESteps
{
None,
TryLoadPackageVersion,
RequestPackageVersion,
CheckResult,
Done,
}
@@ -26,13 +29,27 @@ namespace YooAsset
}
internal override void InternalStart()
{
_steps = ESteps.RequestPackageVersion;
_steps = ESteps.TryLoadPackageVersion;
}
internal override void InternalUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.TryLoadPackageVersion)
{
string filePath = _fileSystem.GetBuildinPackageVersionFilePath();
if (File.Exists(filePath))
{
PackageVersion = File.ReadAllText(filePath);
_steps = ESteps.CheckResult;
}
else
{
_steps = ESteps.RequestPackageVersion;
}
}
if (_steps == ESteps.RequestPackageVersion)
{
if (_webTextRequestOp == null)
@@ -51,17 +68,7 @@ namespace YooAsset
if (_webTextRequestOp.Status == EOperationStatus.Succeed)
{
PackageVersion = _webTextRequestOp.Result;
if (string.IsNullOrEmpty(PackageVersion))
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Buildin package version file content is empty !";
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
_steps = ESteps.CheckResult;
}
else
{
@@ -70,6 +77,21 @@ namespace YooAsset
Error = _webTextRequestOp.Error;
}
}
if (_steps == ESteps.CheckResult)
{
if (string.IsNullOrEmpty(PackageVersion))
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Buildin package version file content is empty !";
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
}
}
}
}

View File

@@ -2,6 +2,7 @@
using System.IO;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace YooAsset
{
@@ -56,19 +57,24 @@ namespace YooAsset
#region
/// <summary>
/// 自定义参数:远程服务接口
/// 自定义参数:远程服务接口的实例类
/// </summary>
public IRemoteServices RemoteServices { private set; get; }
/// <summary>
/// 自定义参数:覆盖安装缓存清理模式
/// </summary>
public EOverwriteInstallClearMode InstallClearMode { private set; get; } = EOverwriteInstallClearMode.ClearAllManifestFiles;
/// <summary>
/// 自定义参数:初始化的时候缓存文件校验级别
/// </summary>
public EFileVerifyLevel FileVerifyLevel { private set; get; } = EFileVerifyLevel.Middle;
/// <summary>
/// 自定义参数:覆盖安装缓存清理模式
/// 自定义参数:初始化的时候缓存文件校验最大并发数
/// </summary>
public EOverwriteInstallClearMode InstallClearMode { private set; get; } = EOverwriteInstallClearMode.ClearAllManifestFiles;
public int FileVerifyMaxConcurrency { private set; get; } = int.MaxValue;
/// <summary>
/// 自定义参数:数据文件追加文件格式
@@ -90,6 +96,11 @@ namespace YooAsset
/// </summary>
public int DownloadMaxRequestPerFrame { private set; get; } = int.MaxValue;
/// <summary>
/// 自定义参数:下载任务的看门狗机制监控时间
/// </summary>
public int DownloadWatchDogTime { private set; get; } = int.MaxValue;
/// <summary>
/// 自定义参数:启用断点续传的最小尺寸
/// </summary>
@@ -101,7 +112,7 @@ namespace YooAsset
public List<long> ResumeDownloadResponseCodes { private set; get; } = null;
/// <summary>
/// 自定义参数:解密方法
/// 自定义参数:解密服务接口的实例
/// </summary>
public IDecryptionServices DecryptionServices { private set; get; }
@@ -111,7 +122,7 @@ namespace YooAsset
public IManifestRestoreServices ManifestServices { private set; get; }
/// <summary>
/// 自定义参数:拷贝内置文件服务
/// 自定义参数:拷贝内置文件接口的实例
/// </summary>
public ICopyLocalFileServices CopyLocalFileServices { private set; get; }
#endregion
@@ -215,13 +226,18 @@ namespace YooAsset
{
RemoteServices = (IRemoteServices)value;
}
else if (name == FileSystemParametersDefine.INSTALL_CLEAR_MODE)
{
InstallClearMode = (EOverwriteInstallClearMode)value;
}
else if (name == FileSystemParametersDefine.FILE_VERIFY_LEVEL)
{
FileVerifyLevel = (EFileVerifyLevel)value;
}
else if (name == FileSystemParametersDefine.INSTALL_CLEAR_MODE)
else if (name == FileSystemParametersDefine.FILE_VERIFY_MAX_CONCURRENCY)
{
InstallClearMode = (EOverwriteInstallClearMode)value;
int convertValue = Convert.ToInt32(value);
FileVerifyMaxConcurrency = Mathf.Clamp(convertValue, 1, int.MaxValue);
}
else if (name == FileSystemParametersDefine.APPEND_FILE_EXTENSION)
{
@@ -233,11 +249,18 @@ namespace YooAsset
}
else if (name == FileSystemParametersDefine.DOWNLOAD_MAX_CONCURRENCY)
{
DownloadMaxConcurrency = Convert.ToInt32(value);
int convertValue = Convert.ToInt32(value);
DownloadMaxConcurrency = Mathf.Clamp(convertValue, 1, int.MaxValue);
}
else if (name == FileSystemParametersDefine.DOWNLOAD_MAX_REQUEST_PER_FRAME)
{
DownloadMaxRequestPerFrame = Convert.ToInt32(value);
int convertValue = Convert.ToInt32(value);
DownloadMaxRequestPerFrame = Mathf.Clamp(convertValue, 1, int.MaxValue);
}
else if (name == FileSystemParametersDefine.DOWNLOAD_WATCH_DOG_TIME)
{
int convertValue = Convert.ToInt32(value);
DownloadWatchDogTime = Mathf.Clamp(convertValue, 1, int.MaxValue);
}
else if (name == FileSystemParametersDefine.RESUME_DOWNLOAD_MINMUM_SIZE)
{
@@ -493,22 +516,22 @@ namespace YooAsset
}
private readonly BufferWriter _sharedBuffer = new BufferWriter(1024);
public void WriteBundleInfoFile(string filePath, string dataFileCRC, long dataFileSize)
public void WriteBundleInfoFile(string filePath, uint dataFileCRC, long dataFileSize)
{
using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.Read))
{
_sharedBuffer.Clear();
_sharedBuffer.WriteUTF8(dataFileCRC);
_sharedBuffer.WriteUInt32(dataFileCRC);
_sharedBuffer.WriteInt64(dataFileSize);
_sharedBuffer.WriteToStream(fs);
fs.Flush();
}
}
public void ReadBundleInfoFile(string filePath, out string dataFileCRC, out long dataFileSize)
public void ReadBundleInfoFile(string filePath, out uint dataFileCRC, out long dataFileSize)
{
byte[] binaryData = FileUtility.ReadAllBytes(filePath);
BufferReader buffer = new BufferReader(binaryData);
dataFileCRC = buffer.ReadUTF8();
dataFileCRC = buffer.ReadUInt32();
dataFileSize = buffer.ReadInt64();
}
#endregion

View File

@@ -7,10 +7,10 @@ namespace YooAsset
{
public string InfoFilePath { private set; get; }
public string DataFilePath { private set; get; }
public string DataFileCRC { private set; get; }
public uint DataFileCRC { private set; get; }
public long DataFileSize { private set; get; }
public RecordFileElement(string infoFilePath, string dataFilePath, string dataFileCRC, long dataFileSize)
public RecordFileElement(string infoFilePath, string dataFilePath, uint dataFileCRC, long dataFileSize)
{
InfoFilePath = infoFilePath;
DataFilePath = dataFilePath;

View File

@@ -4,7 +4,7 @@ namespace YooAsset
internal class TempFileElement
{
public string TempFilePath { private set; get; }
public string TempFileCRC { private set; get; }
public uint TempFileCRC { private set; get; }
public long TempFileSize { private set; get; }
/// <summary>
@@ -12,7 +12,7 @@ namespace YooAsset
/// </summary>
public volatile int Result = 0;
public TempFileElement(string filePath, string fileCRC, long fileSize)
public TempFileElement(string filePath, uint fileCRC, long fileSize)
{
TempFilePath = filePath;
TempFileCRC = fileCRC;

View File

@@ -10,7 +10,7 @@ namespace YooAsset
public string DataFilePath { private set; get; }
public string InfoFilePath { private set; get; }
public string DataFileCRC;
public uint DataFileCRC;
public long DataFileSize;
/// <summary>

View File

@@ -11,6 +11,7 @@ namespace YooAsset
None,
CheckExist,
DownloadFile,
AbortDownload,
LoadAssetBundle,
CheckResult,
Done,
@@ -63,6 +64,17 @@ namespace YooAsset
}
}
if (_steps == ESteps.DownloadFile)
{
// 中断下载
if (AbortDownloadFile)
{
if (_downloadFileOp != null)
_downloadFileOp.AbortOperation();
_steps = ESteps.AbortDownload;
}
}
if (_steps == ESteps.DownloadFile)
{
if (_downloadFileOp == null)
@@ -94,6 +106,23 @@ namespace YooAsset
}
}
if (_steps == ESteps.AbortDownload)
{
if (_downloadFileOp != null)
{
if (IsWaitForAsyncComplete)
_downloadFileOp.WaitForAsyncComplete();
_downloadFileOp.UpdateOperation();
if (_downloadFileOp.IsDone == false)
return;
}
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = "Abort download file !";
}
if (_steps == ESteps.LoadAssetBundle)
{
if (_bundle.Encrypted)
@@ -251,6 +280,7 @@ namespace YooAsset
None,
CheckExist,
DownloadFile,
AbortDownload,
LoadCacheRawBundle,
Done,
}
@@ -310,6 +340,17 @@ namespace YooAsset
}
}
if (_steps == ESteps.DownloadFile)
{
// 中断下载
if (AbortDownloadFile)
{
if (_downloadFileOp != null)
_downloadFileOp.AbortOperation();
_steps = ESteps.AbortDownload;
}
}
if (_steps == ESteps.DownloadFile)
{
if (_downloadFileOp == null)
@@ -341,6 +382,23 @@ namespace YooAsset
}
}
if (_steps == ESteps.AbortDownload)
{
if (_downloadFileOp != null)
{
if (IsWaitForAsyncComplete)
_downloadFileOp.WaitForAsyncComplete();
_downloadFileOp.UpdateOperation();
if (_downloadFileOp.IsDone == false)
return;
}
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = "Abort download file !";
}
if (_steps == ESteps.LoadCacheRawBundle)
{
string filePath = _fileSystem.GetCacheBundleFileLoadPath(_bundle);

View File

@@ -16,7 +16,7 @@ namespace YooAsset
}
private readonly DefaultCacheFileSystem _fileSystem;
private IEnumerator<DirectoryInfo> _filesEnumerator = null;
private IEnumerator<string> _filesEnumerator = null;
private float _verifyStartTime;
private ESteps _steps = ESteps.None;
@@ -42,11 +42,11 @@ namespace YooAsset
if (_steps == ESteps.Prepare)
{
DirectoryInfo rootDirectory = new DirectoryInfo(_fileSystem.GetCacheBundleFilesRoot());
if (rootDirectory.Exists)
string rootDirectory = _fileSystem.GetCacheBundleFilesRoot();
if (Directory.Exists(rootDirectory))
{
var directorieInfos = rootDirectory.EnumerateDirectories();
_filesEnumerator = directorieInfos.GetEnumerator();
var directories = Directory.EnumerateDirectories(rootDirectory);
_filesEnumerator = directories.GetEnumerator();
}
_steps = ESteps.SearchFiles;
}
@@ -76,15 +76,15 @@ namespace YooAsset
break;
var rootFoder = _filesEnumerator.Current;
var childDirectories = rootFoder.GetDirectories();
var childDirectories = Directory.EnumerateDirectories(rootFoder);
foreach (var chidDirectory in childDirectories)
{
string bundleGUID = chidDirectory.Name;
string bundleGUID = Path.GetFileName(chidDirectory);
if (_fileSystem.IsRecordBundleFile(bundleGUID))
continue;
// 创建验证元素类
string fileRootPath = chidDirectory.FullName;
string fileRootPath = chidDirectory;
string dataFilePath = $"{fileRootPath}/{DefaultCacheFileSystemDefine.BundleDataFileName}";
string infoFilePath = $"{fileRootPath}/{DefaultCacheFileSystemDefine.BundleInfoFileName}";
@@ -108,17 +108,15 @@ namespace YooAsset
return isFindItem;
}
private string FindDataFileExtension(DirectoryInfo directoryInfo)
private string FindDataFileExtension(string directory)
{
string dataFileExtension = string.Empty;
var fileInfos = directoryInfo.GetFiles();
foreach (var fileInfo in fileInfos)
string searchPattern = DefaultCacheFileSystemDefine.BundleDataFileName + "*";
var dataFiles = Directory.EnumerateFiles(directory, searchPattern);
foreach (var filePath in dataFiles)
{
if (fileInfo.Name.StartsWith(DefaultCacheFileSystemDefine.BundleDataFileName))
{
dataFileExtension = fileInfo.Extension;
break;
}
dataFileExtension = Path.GetExtension(filePath);
break;
}
return dataFileExtension;
}

View File

@@ -17,6 +17,11 @@ namespace YooAsset
protected readonly PackageBundle _bundle;
protected readonly string _tempFilePath;
private bool _watchDogInit = false;
private bool _watchDogAborted = false;
private ulong _lastDownloadBytes;
private double _lastGetDataTime;
/// <summary>
/// 引用计数
/// </summary>
@@ -33,6 +38,47 @@ namespace YooAsset
return $"RefCount : {RefCount}";
}
/// <summary>
/// 更新看门狗监测
/// 说明:监控时间范围内,如果没有接收到任何下载数据,那么直接终止任务!
/// </summary>
protected void UpdateWatchDog()
{
if (_fileSystem.DownloadWatchDogTime == int.MaxValue)
return;
if (_watchDogAborted)
return;
#if UNITY_2020_3_OR_NEWER
double realtimeSinceStartup = UnityEngine.Time.realtimeSinceStartupAsDouble;
#else
double realtimeSinceStartup = UnityEngine.Time.realtimeSinceStartup;
#endif
if (_watchDogInit == false)
{
_watchDogInit = true;
_lastDownloadBytes = 0;
_lastGetDataTime = realtimeSinceStartup;
}
if (_webRequest.downloadedBytes != _lastDownloadBytes)
{
_lastDownloadBytes = _webRequest.downloadedBytes;
_lastGetDataTime = realtimeSinceStartup;
}
else
{
double deltaTime = realtimeSinceStartup - _lastGetDataTime;
if (deltaTime > _fileSystem.DownloadWatchDogTime)
{
_watchDogAborted = true;
InternalAbort(); //终止网络请求
}
}
}
/// <summary>
/// 减少引用计数
/// </summary>

View File

@@ -4,7 +4,7 @@ using UnityEngine.Networking;
namespace YooAsset
{
internal class UnityDownloadLocalFileOperation : UnityDownloadFileOperation
internal sealed class UnityDownloadLocalFileOperation : UnityDownloadFileOperation
{
private VerifyTempFileOperation _verifyOperation;
private ESteps _steps = ESteps.None;
@@ -42,6 +42,8 @@ namespace YooAsset
DownloadProgress = _webRequest.downloadProgress;
DownloadedBytes = (long)_webRequest.downloadedBytes;
Progress = DownloadProgress;
UpdateWatchDog();
if (_webRequest.isDone == false)
return;

View File

@@ -39,6 +39,8 @@ namespace YooAsset
DownloadProgress = _webRequest.downloadProgress;
DownloadedBytes = (long)_webRequest.downloadedBytes;
Progress = DownloadProgress;
UpdateWatchDog();
if (_webRequest.isDone == false)
return;

View File

@@ -56,6 +56,8 @@ namespace YooAsset
DownloadProgress = _webRequest.downloadProgress;
DownloadedBytes = _fileOriginLength + (long)_webRequest.downloadedBytes;
Progress = DownloadProgress;
UpdateWatchDog();
if (_webRequest.isDone == false)
return;

View File

@@ -54,11 +54,13 @@ namespace YooAsset
// 设置同时验证的最大数
ThreadPool.GetMaxThreads(out int workerThreads, out int ioThreads);
YooLogger.Log($"Work threads : {workerThreads}, IO threads : {ioThreads}");
_verifyMaxNum = Math.Min(workerThreads, ioThreads);
int threads = Math.Min(workerThreads, ioThreads);
_verifyMaxNum = Math.Min(threads, _fileSystem.FileVerifyMaxConcurrency);
_verifyTotalCount = fileCount;
if (_verifyMaxNum < 1)
_verifyMaxNum = 1;
YooLogger.Log($"Verify max concurrency : {_verifyMaxNum}");
_verifyingList = new List<VerifyFileElement>(_verifyMaxNum);
_steps = ESteps.UpdateVerify;
}

View File

@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
namespace YooAsset
{
@@ -7,6 +8,7 @@ namespace YooAsset
/// </summary>
internal class DefaultEditorFileSystem : IFileSystem
{
protected readonly Dictionary<string, string> _records = new Dictionary<string, string>(10000);
protected string _packageRoot;
/// <summary>
@@ -37,15 +39,30 @@ namespace YooAsset
}
#region
/// <summary>
/// 模拟WebGL平台模式
/// </summary>
public bool VirtualWebGLMode { private set; get; } = false;
/// <summary>
/// 模拟虚拟下载模式
/// </summary>
public bool VirtualDownloadMode { private set; get; } = false;
/// <summary>
/// 模拟虚拟下载的网速(单位:字节)
/// </summary>
public int VirtualDownloadSpeed { private set; get; } = 1024;
/// <summary>
/// 异步模拟加载最小帧数
/// </summary>
public int _asyncSimulateMinFrame = 1;
public int AsyncSimulateMinFrame { private set; get; } = 1;
/// <summary>
/// 异步模拟加载最大帧数
/// </summary>
public int _asyncSimulateMaxFrame = 1;
public int AsyncSimulateMaxFrame { private set; get; } = 1;
#endregion
public DefaultEditorFileSystem()
@@ -73,7 +90,10 @@ namespace YooAsset
}
public virtual FSDownloadFileOperation DownloadFileAsync(PackageBundle bundle, DownloadFileOptions options)
{
throw new System.NotImplementedException();
string mainURL = bundle.BundleName;
options.SetURL(mainURL, mainURL);
var downloader = new DownloadVirtualBundleOperation(this, bundle, options);
return downloader;
}
public virtual FSLoadBundleOperation LoadBundleFile(PackageBundle bundle)
{
@@ -92,13 +112,25 @@ namespace YooAsset
public virtual void SetParameter(string name, object value)
{
if (name == FileSystemParametersDefine.ASYNC_SIMULATE_MIN_FRAME)
if (name == FileSystemParametersDefine.VIRTUAL_WEBGL_MODE)
{
_asyncSimulateMinFrame = Convert.ToInt32(value);
VirtualWebGLMode = Convert.ToBoolean(value);
}
else if (name == FileSystemParametersDefine.VIRTUAL_DOWNLOAD_MODE)
{
VirtualDownloadMode = Convert.ToBoolean(value);
}
else if (name == FileSystemParametersDefine.VIRTUAL_DOWNLOAD_SPEED)
{
VirtualDownloadSpeed = Convert.ToInt32(value);
}
else if (name == FileSystemParametersDefine.ASYNC_SIMULATE_MIN_FRAME)
{
AsyncSimulateMinFrame = Convert.ToInt32(value);
}
else if (name == FileSystemParametersDefine.ASYNC_SIMULATE_MAX_FRAME)
{
_asyncSimulateMaxFrame = Convert.ToInt32(value);
AsyncSimulateMaxFrame = Convert.ToInt32(value);
}
else
{
@@ -124,11 +156,21 @@ namespace YooAsset
}
public virtual bool Exists(PackageBundle bundle)
{
return true;
if (VirtualDownloadMode)
{
return _records.ContainsKey(bundle.BundleGUID);
}
else
{
return true;
}
}
public virtual bool NeedDownload(PackageBundle bundle)
{
return false;
if (Belong(bundle) == false)
return false;
return Exists(bundle) == false;
}
public virtual bool NeedUnpack(PackageBundle bundle)
{
@@ -165,6 +207,11 @@ namespace YooAsset
}
#region
public void RecordDownloadFile(PackageBundle bundle)
{
if (_records.ContainsKey(bundle.BundleGUID) == false)
_records.Add(bundle.BundleGUID, bundle.BundleName);
}
public string GetEditorPackageVersionFilePath()
{
string fileName = YooAssetSettingsData.GetPackageVersionFileName(PackageName);
@@ -182,12 +229,12 @@ namespace YooAsset
}
public int GetAsyncSimulateFrame()
{
if (_asyncSimulateMinFrame > _asyncSimulateMaxFrame)
if (AsyncSimulateMinFrame > AsyncSimulateMaxFrame)
{
_asyncSimulateMinFrame = _asyncSimulateMaxFrame;
AsyncSimulateMinFrame = AsyncSimulateMaxFrame;
}
return UnityEngine.Random.Range(_asyncSimulateMinFrame, _asyncSimulateMaxFrame + 1);
return UnityEngine.Random.Range(AsyncSimulateMinFrame, AsyncSimulateMaxFrame + 1);
}
#endregion
}

View File

@@ -6,7 +6,9 @@ namespace YooAsset
protected enum ESteps
{
None,
CheckExist,
DownloadFile,
AbortDownload,
LoadAssetBundle,
CheckResult,
Done,
@@ -14,6 +16,7 @@ namespace YooAsset
private readonly DefaultEditorFileSystem _fileSystem;
private readonly PackageBundle _bundle;
protected FSDownloadFileOperation _downloadFileOp;
private int _asyncSimulateFrame;
private ESteps _steps = ESteps.None;
@@ -24,26 +27,102 @@ namespace YooAsset
}
internal override void InternalStart()
{
_steps = ESteps.DownloadFile;
_steps = ESteps.CheckExist;
_asyncSimulateFrame = _fileSystem.GetAsyncSimulateFrame();
}
internal override void InternalUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.CheckExist)
{
if (_fileSystem.Exists(_bundle))
{
DownloadProgress = 1f;
DownloadedBytes = _bundle.FileSize;
_steps = ESteps.LoadAssetBundle;
}
else
{
_steps = ESteps.DownloadFile;
}
}
if (_steps == ESteps.DownloadFile)
{
_asyncSimulateFrame = _fileSystem.GetAsyncSimulateFrame();
DownloadProgress = 1f;
DownloadedBytes = _bundle.FileSize;
_steps = ESteps.LoadAssetBundle;
// 中断下载
if (AbortDownloadFile)
{
if (_downloadFileOp != null)
_downloadFileOp.AbortOperation();
_steps = ESteps.AbortDownload;
}
}
if (_steps == ESteps.DownloadFile)
{
if (_downloadFileOp == null)
{
DownloadFileOptions options = new DownloadFileOptions(int.MaxValue);
_downloadFileOp = _fileSystem.DownloadFileAsync(_bundle, options);
_downloadFileOp.StartOperation();
AddChildOperation(_downloadFileOp);
}
if (IsWaitForAsyncComplete)
_downloadFileOp.WaitForAsyncComplete();
_downloadFileOp.UpdateOperation();
DownloadProgress = _downloadFileOp.DownloadProgress;
DownloadedBytes = _downloadFileOp.DownloadedBytes;
if (_downloadFileOp.IsDone == false)
return;
if (_downloadFileOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.LoadAssetBundle;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _downloadFileOp.Error;
}
}
if (_steps == ESteps.AbortDownload)
{
if (_downloadFileOp != null)
{
if (IsWaitForAsyncComplete)
_downloadFileOp.WaitForAsyncComplete();
_downloadFileOp.UpdateOperation();
if (_downloadFileOp.IsDone == false)
return;
}
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = "Abort download file !";
}
if (_steps == ESteps.LoadAssetBundle)
{
if (IsWaitForAsyncComplete)
{
_steps = ESteps.CheckResult;
if (_fileSystem.VirtualWebGLMode)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = "Virtual WebGL Mode only support asyn load method !";
YooLogger.Error(Error);
}
else
{
_steps = ESteps.CheckResult;
}
}
else
{

View File

@@ -0,0 +1,156 @@
using UnityEngine;
namespace YooAsset
{
internal class DownloadVirtualBundleOperation : FSDownloadFileOperation
{
protected enum ESteps
{
None,
CheckExists,
CreateRequest,
CheckRequest,
TryAgain,
Done,
}
// 下载参数
protected readonly DefaultEditorFileSystem _fileSystem;
protected readonly DownloadFileOptions _options;
protected UnityVirtualBundleRequestOperation _unityDownloadFileOp;
protected int _requestCount = 0;
protected float _tryAgainTimer;
protected int _failedTryAgain;
private ESteps _steps = ESteps.None;
internal DownloadVirtualBundleOperation(DefaultEditorFileSystem fileSystem, PackageBundle bundle, DownloadFileOptions options) : base(bundle)
{
_fileSystem = fileSystem;
_options = options;
_failedTryAgain = options.FailedTryAgain;
}
internal override void InternalStart()
{
_steps = ESteps.CheckExists;
}
internal override void InternalUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
// 检测文件是否存在
if (_steps == ESteps.CheckExists)
{
if (_fileSystem.Exists(Bundle))
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.CreateRequest;
}
}
// 创建下载器
if (_steps == ESteps.CreateRequest)
{
if (_options.IsValid() == false)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = "Download file options is invalid !";
Debug.Log(Error);
return;
}
string url = GetRequestURL();
int speed = _fileSystem.VirtualDownloadSpeed;
_unityDownloadFileOp = new UnityVirtualBundleRequestOperation(Bundle, speed, url);
_unityDownloadFileOp.StartOperation();
_steps = ESteps.CheckRequest;
}
// 检测下载结果
if (_steps == ESteps.CheckRequest)
{
if (IsWaitForAsyncComplete)
_unityDownloadFileOp.WaitForAsyncComplete();
// 因为并发数量限制,下载器可能被挂起!
if (_unityDownloadFileOp.Status == EOperationStatus.None)
return;
_unityDownloadFileOp.UpdateOperation();
Progress = _unityDownloadFileOp.Progress;
DownloadedBytes = _unityDownloadFileOp.DownloadedBytes;
DownloadProgress = _unityDownloadFileOp.DownloadProgress;
if (_unityDownloadFileOp.IsDone == false)
return;
if (_unityDownloadFileOp.Status == EOperationStatus.Succeed)
{
_fileSystem.RecordDownloadFile(Bundle);
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
else
{
if (IsWaitForAsyncComplete == false && _failedTryAgain > 0)
{
_steps = ESteps.TryAgain;
YooLogger.Warning($"Failed download : {_unityDownloadFileOp.URL} Try again !");
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _unityDownloadFileOp.Error;
YooLogger.Error(Error);
}
}
}
// 重新尝试下载
if (_steps == ESteps.TryAgain)
{
_tryAgainTimer += Time.unscaledDeltaTime;
if (_tryAgainTimer > 1f)
{
_tryAgainTimer = 0f;
_failedTryAgain--;
Progress = 0f;
DownloadProgress = 0f;
DownloadedBytes = 0;
_steps = ESteps.CreateRequest;
}
}
}
internal override void InternalWaitForAsyncComplete()
{
while (true)
{
if (ExecuteWhileDone())
{
_steps = ESteps.Done;
break;
}
}
}
/// <summary>
/// 获取网络请求地址
/// </summary>
protected string GetRequestURL()
{
// 轮流返回请求地址
_requestCount++;
if (_requestCount % 2 == 0)
return _options.FallbackURL;
else
return _options.MainURL;
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 9a38597f546a46a429b24abd595c76e4
guid: f043dc0e0f147334380cfd0720636544
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -44,12 +44,12 @@ namespace YooAsset
public bool DisableUnityWebCache { private set; get; } = false;
/// <summary>
/// 自定义参数:跨域下载服务接口
/// 自定义参数:远程服务接口的实例类(支持跨域下载)
/// </summary>
public IRemoteServices RemoteServices { private set; get; }
/// <summary>
/// 自定义参数:解密方法
/// 自定义参数:解密服务接口的实例
/// </summary>
public IWebDecryptionServices DecryptionServices { private set; get; }

View File

@@ -14,8 +14,8 @@ namespace YooAsset
private readonly DefaultWebRemoteFileSystem _fileSystem;
private readonly string _packageVersion;
private readonly int _timeout;
private RequestWebRemotePackageHashOperation _requestWebPackageHashOp;
private LoadWebRemotePackageManifestOperation _loadWebPackageManifestOp;
private RequestWebPackageHashOperation _requestWebPackageHashOp;
private LoadWebPackageManifestOperation _loadWebPackageManifestOp;
private ESteps _steps = ESteps.None;
@@ -38,7 +38,7 @@ namespace YooAsset
{
if (_requestWebPackageHashOp == null)
{
_requestWebPackageHashOp = new RequestWebRemotePackageHashOperation(_fileSystem, _packageVersion, _timeout);
_requestWebPackageHashOp = new RequestWebPackageHashOperation(_fileSystem.RemoteServices, _fileSystem.PackageName, _packageVersion, _timeout);
_requestWebPackageHashOp.StartOperation();
AddChildOperation(_requestWebPackageHashOp);
}
@@ -64,7 +64,10 @@ namespace YooAsset
if (_loadWebPackageManifestOp == null)
{
string packageHash = _requestWebPackageHashOp.PackageHash;
_loadWebPackageManifestOp = new LoadWebRemotePackageManifestOperation(_fileSystem, _packageVersion, packageHash, _timeout);
string packageName = _fileSystem.PackageName;
var manifestServices = _fileSystem.ManifestServices;
var remoteServices = _fileSystem.RemoteServices;
_loadWebPackageManifestOp = new LoadWebPackageManifestOperation(manifestServices, remoteServices, packageName, _packageVersion, packageHash, _timeout);
_loadWebPackageManifestOp.StartOperation();
AddChildOperation(_loadWebPackageManifestOp);
}

View File

@@ -13,7 +13,7 @@ namespace YooAsset
private readonly DefaultWebRemoteFileSystem _fileSystem;
private readonly bool _appendTimeTicks;
private readonly int _timeout;
private RequestWebRemotePackageVersionOperation _requestWebPackageVersionOp;
private RequestWebPackageVersionOperation _requestWebPackageVersionOp;
private ESteps _steps = ESteps.None;
@@ -36,7 +36,7 @@ namespace YooAsset
{
if (_requestWebPackageVersionOp == null)
{
_requestWebPackageVersionOp = new RequestWebRemotePackageVersionOperation(_fileSystem, _appendTimeTicks, _timeout);
_requestWebPackageVersionOp = new RequestWebPackageVersionOperation(_fileSystem.RemoteServices, _fileSystem.PackageName, _appendTimeTicks, _timeout);
_requestWebPackageVersionOp.StartOperation();
AddChildOperation(_requestWebPackageVersionOp);
}

View File

@@ -1,131 +0,0 @@

namespace YooAsset
{
internal class LoadWebRemotePackageManifestOperation : AsyncOperationBase
{
private enum ESteps
{
None,
RequestFileData,
VerifyFileData,
LoadManifest,
Done,
}
private readonly DefaultWebRemoteFileSystem _fileSystem;
private readonly string _packageVersion;
private readonly string _packageHash;
private readonly int _timeout;
private UnityWebDataRequestOperation _webDataRequestOp;
private DeserializeManifestOperation _deserializer;
private int _requestCount = 0;
private ESteps _steps = ESteps.None;
/// <summary>
/// 包裹清单
/// </summary>
public PackageManifest Manifest { private set; get; }
internal LoadWebRemotePackageManifestOperation(DefaultWebRemoteFileSystem fileSystem, string packageVersion, string packageHash, int timeout)
{
_fileSystem = fileSystem;
_packageVersion = packageVersion;
_packageHash = packageHash;
_timeout = timeout;
}
internal override void InternalStart()
{
_requestCount = WebRequestCounter.GetRequestFailedCount(_fileSystem.PackageName, nameof(LoadWebRemotePackageManifestOperation));
_steps = ESteps.RequestFileData;
}
internal override void InternalUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.RequestFileData)
{
if (_webDataRequestOp == null)
{
string fileName = YooAssetSettingsData.GetManifestBinaryFileName(_fileSystem.PackageName, _packageVersion);
string url = GetWebRequestURL(fileName);
_webDataRequestOp = new UnityWebDataRequestOperation(url, _timeout);
_webDataRequestOp.StartOperation();
AddChildOperation(_webDataRequestOp);
}
_webDataRequestOp.UpdateOperation();
if (_webDataRequestOp.IsDone == false)
return;
if (_webDataRequestOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.VerifyFileData;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _webDataRequestOp.Error;
WebRequestCounter.RecordRequestFailed(_fileSystem.PackageName, nameof(LoadWebRemotePackageManifestOperation));
}
}
if (_steps == ESteps.VerifyFileData)
{
if (ManifestTools.VerifyManifestData(_webDataRequestOp.Result, _packageHash))
{
_steps = ESteps.LoadManifest;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = "Failed to verify web remote package manifest file!";
}
}
if (_steps == ESteps.LoadManifest)
{
if (_deserializer == null)
{
_deserializer = new DeserializeManifestOperation(_fileSystem.ManifestServices, _webDataRequestOp.Result);
_deserializer.StartOperation();
AddChildOperation(_deserializer);
}
_deserializer.UpdateOperation();
Progress = _deserializer.Progress;
if (_deserializer.IsDone == false)
return;
if (_deserializer.Status == EOperationStatus.Succeed)
{
_steps = ESteps.Done;
Manifest = _deserializer.Manifest;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _deserializer.Error;
}
}
}
internal override string InternalGetDesc()
{
return $"PackageVersion : {_packageVersion} PackageHash : {_packageHash}";
}
private string GetWebRequestURL(string fileName)
{
// 轮流返回请求地址
if (_requestCount % 2 == 0)
return _fileSystem.RemoteServices.GetRemoteMainURL(fileName);
else
return _fileSystem.RemoteServices.GetRemoteFallbackURL(fileName);
}
}
}

View File

@@ -1,92 +0,0 @@

namespace YooAsset
{
internal class RequestWebRemotePackageHashOperation : AsyncOperationBase
{
private enum ESteps
{
None,
RequestPackageHash,
Done,
}
private readonly DefaultWebRemoteFileSystem _fileSystem;
private readonly string _packageVersion;
private readonly int _timeout;
private UnityWebTextRequestOperation _webTextRequestOp;
private int _requestCount = 0;
private ESteps _steps = ESteps.None;
/// <summary>
/// 包裹哈希值
/// </summary>
public string PackageHash { private set; get; }
public RequestWebRemotePackageHashOperation(DefaultWebRemoteFileSystem fileSystem, string packageVersion, int timeout)
{
_fileSystem = fileSystem;
_packageVersion = packageVersion;
_timeout = timeout;
}
internal override void InternalStart()
{
_requestCount = WebRequestCounter.GetRequestFailedCount(_fileSystem.PackageName, nameof(RequestWebRemotePackageHashOperation));
_steps = ESteps.RequestPackageHash;
}
internal override void InternalUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.RequestPackageHash)
{
if (_webTextRequestOp == null)
{
string fileName = YooAssetSettingsData.GetPackageHashFileName(_fileSystem.PackageName, _packageVersion);
string url = GetWebRequestURL(fileName);
_webTextRequestOp = new UnityWebTextRequestOperation(url, _timeout);
_webTextRequestOp.StartOperation();
AddChildOperation(_webTextRequestOp);
}
_webTextRequestOp.UpdateOperation();
Progress = _webTextRequestOp.Progress;
if (_webTextRequestOp.IsDone == false)
return;
if (_webTextRequestOp.Status == EOperationStatus.Succeed)
{
PackageHash = _webTextRequestOp.Result;
if (string.IsNullOrEmpty(PackageHash))
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Web remote package hash file content is empty !";
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _webTextRequestOp.Error;
WebRequestCounter.RecordRequestFailed(_fileSystem.PackageName, nameof(RequestWebRemotePackageHashOperation));
}
}
}
private string GetWebRequestURL(string fileName)
{
// 轮流返回请求地址
if (_requestCount % 2 == 0)
return _fileSystem.RemoteServices.GetRemoteMainURL(fileName);
else
return _fileSystem.RemoteServices.GetRemoteFallbackURL(fileName);
}
}
}

View File

@@ -1,100 +0,0 @@

namespace YooAsset
{
internal class RequestWebRemotePackageVersionOperation : AsyncOperationBase
{
private enum ESteps
{
None,
RequestPackageVersion,
Done,
}
private readonly DefaultWebRemoteFileSystem _fileSystem;
private readonly bool _appendTimeTicks;
private readonly int _timeout;
private UnityWebTextRequestOperation _webTextRequestOp;
private int _requestCount = 0;
private ESteps _steps = ESteps.None;
/// <summary>
/// 包裹版本
/// </summary>
public string PackageVersion { private set; get; }
internal RequestWebRemotePackageVersionOperation(DefaultWebRemoteFileSystem fileSystem, bool appendTimeTicks, int timeout)
{
_fileSystem = fileSystem;
_appendTimeTicks = appendTimeTicks;
_timeout = timeout;
}
internal override void InternalStart()
{
_requestCount = WebRequestCounter.GetRequestFailedCount(_fileSystem.PackageName, nameof(RequestWebRemotePackageVersionOperation));
_steps = ESteps.RequestPackageVersion;
}
internal override void InternalUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.RequestPackageVersion)
{
if (_webTextRequestOp == null)
{
string fileName = YooAssetSettingsData.GetPackageVersionFileName(_fileSystem.PackageName);
string url = GetWebRequestURL(fileName);
_webTextRequestOp = new UnityWebTextRequestOperation(url, _timeout);
_webTextRequestOp.StartOperation();
AddChildOperation(_webTextRequestOp);
}
_webTextRequestOp.UpdateOperation();
Progress = _webTextRequestOp.Progress;
if (_webTextRequestOp.IsDone == false)
return;
if (_webTextRequestOp.Status == EOperationStatus.Succeed)
{
PackageVersion = _webTextRequestOp.Result;
if (string.IsNullOrEmpty(PackageVersion))
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Web remote package version file content is empty !";
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _webTextRequestOp.Error;
WebRequestCounter.RecordRequestFailed(_fileSystem.PackageName, nameof(RequestWebRemotePackageVersionOperation));
}
}
}
private string GetWebRequestURL(string fileName)
{
string url;
// 轮流返回请求地址
if (_requestCount % 2 == 0)
url = _fileSystem.RemoteServices.GetRemoteMainURL(fileName);
else
url = _fileSystem.RemoteServices.GetRemoteFallbackURL(fileName);
// 在URL末尾添加时间戳
if (_appendTimeTicks)
return $"{url}?{System.DateTime.UtcNow.Ticks}";
else
return url;
}
}
}

View File

@@ -58,7 +58,7 @@ namespace YooAsset
public bool DisableUnityWebCache { private set; get; } = false;
/// <summary>
/// 自定义参数:解密方法
/// 自定义参数:解密服务接口的实例
/// </summary>
public IWebDecryptionServices DecryptionServices { private set; get; }

View File

@@ -4,6 +4,7 @@ namespace YooAsset
public class FileSystemParametersDefine
{
public const string FILE_VERIFY_LEVEL = "FILE_VERIFY_LEVEL";
public const string FILE_VERIFY_MAX_CONCURRENCY = "FILE_VERIFY_MAX_CONCURRENCY";
public const string INSTALL_CLEAR_MODE = "INSTALL_CLEAR_MODE";
public const string REMOTE_SERVICES = "REMOTE_SERVICES";
public const string DECRYPTION_SERVICES = "DECRYPTION_SERVICES";
@@ -14,8 +15,12 @@ namespace YooAsset
public const string DISABLE_ONDEMAND_DOWNLOAD = "DISABLE_ONDEMAND_DOWNLOAD";
public const string DOWNLOAD_MAX_CONCURRENCY = "DOWNLOAD_MAX_CONCURRENCY";
public const string DOWNLOAD_MAX_REQUEST_PER_FRAME = "DOWNLOAD_MAX_REQUEST_PER_FRAME";
public const string DOWNLOAD_WATCH_DOG_TIME = "DOWNLOAD_WATCH_DOG_TIME";
public const string RESUME_DOWNLOAD_MINMUM_SIZE = "RESUME_DOWNLOAD_MINMUM_SIZE";
public const string RESUME_DOWNLOAD_RESPONSE_CODES = "RESUME_DOWNLOAD_RESPONSE_CODES";
public const string VIRTUAL_WEBGL_MODE = "VIRTUAL_WEBGL_MODE";
public const string VIRTUAL_DOWNLOAD_MODE = "VIRTUAL_DOWNLOAD_MODE";
public const string VIRTUAL_DOWNLOAD_SPEED = "VIRTUAL_DOWNLOAD_SPEED";
public const string ASYNC_SIMULATE_MIN_FRAME = "ASYNC_SIMULATE_MIN_FRAME";
public const string ASYNC_SIMULATE_MAX_FRAME = "ASYNC_SIMULATE_MAX_FRAME";
public const string COPY_BUILDIN_PACKAGE_MANIFEST = "COPY_BUILDIN_PACKAGE_MANIFEST";

View File

@@ -8,7 +8,7 @@ namespace YooAsset
/// <summary>
/// 文件校验
/// </summary>
public static EFileVerifyResult FileVerify(string filePath, long fileSize, string fileCRC, EFileVerifyLevel verifyLevel)
public static EFileVerifyResult FileVerify(string filePath, long fileSize, uint fileCRC, EFileVerifyLevel verifyLevel)
{
try
{
@@ -25,7 +25,7 @@ namespace YooAsset
// 再验证文件CRC
if (verifyLevel == EFileVerifyLevel.High)
{
string crc = HashUtility.FileCRC32(filePath);
uint crc = HashUtility.FileCRC32Value(filePath);
if (crc == fileCRC)
return EFileVerifyResult.Succeed;
else

View File

@@ -17,6 +17,11 @@ namespace YooAsset
/// 下载大小
/// </summary>
public long DownloadedBytes { protected set; get; } = 0;
/// <summary>
/// 终止下载文件
/// </summary>
public bool AbortDownloadFile = false;
}
internal sealed class FSLoadBundleCompleteOperation : FSLoadBundleOperation

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 97923f5987c469a4898718033af09e99
guid: 1ca8ffceab2965e4c8892f62efa86e90
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 275b87293edc6634f9d72387851dbbdf
guid: 10a171d1f549765498fc478ac208cfe5
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -1,7 +1,6 @@
#if UNITY_WEBGL && DOUYINMINIGAME
using YooAsset;
using YooAsset;
internal class LoadTiktokPackageManifestOperation : AsyncOperationBase
internal class LoadWebPackageManifestOperation : AsyncOperationBase
{
private enum ESteps
{
@@ -12,7 +11,9 @@ internal class LoadTiktokPackageManifestOperation : AsyncOperationBase
Done,
}
private readonly TiktokFileSystem _fileSystem;
private readonly IManifestRestoreServices _manifestServices;
private readonly IRemoteServices _remoteServices;
private readonly string _packageName;
private readonly string _packageVersion;
private readonly string _packageHash;
private readonly int _timeout;
@@ -27,16 +28,19 @@ internal class LoadTiktokPackageManifestOperation : AsyncOperationBase
public PackageManifest Manifest { private set; get; }
internal LoadTiktokPackageManifestOperation(TiktokFileSystem fileSystem, string packageVersion, string packageHash, int timeout)
internal LoadWebPackageManifestOperation(IManifestRestoreServices manifestServices, IRemoteServices remoteServices,
string packageName, string packageVersion, string packageHash, int timeout)
{
_fileSystem = fileSystem;
_manifestServices = manifestServices;
_remoteServices = remoteServices;
_packageName = packageName;
_packageVersion = packageVersion;
_packageHash = packageHash;
_timeout = timeout;
}
internal override void InternalStart()
{
_requestCount = WebRequestCounter.GetRequestFailedCount(_fileSystem.PackageName, nameof(LoadTiktokPackageManifestOperation));
_requestCount = WebRequestCounter.GetRequestFailedCount(_packageName, nameof(LoadWebPackageManifestOperation));
_steps = ESteps.RequestFileData;
}
internal override void InternalUpdate()
@@ -48,7 +52,7 @@ internal class LoadTiktokPackageManifestOperation : AsyncOperationBase
{
if (_webDataRequestOp == null)
{
string fileName = YooAssetSettingsData.GetManifestBinaryFileName(_fileSystem.PackageName, _packageVersion);
string fileName = YooAssetSettingsData.GetManifestBinaryFileName(_packageName, _packageVersion);
string url = GetRequestURL(fileName);
_webDataRequestOp = new UnityWebDataRequestOperation(url, _timeout);
_webDataRequestOp.StartOperation();
@@ -69,14 +73,13 @@ internal class LoadTiktokPackageManifestOperation : AsyncOperationBase
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _webDataRequestOp.Error;
WebRequestCounter.RecordRequestFailed(_fileSystem.PackageName, nameof(LoadTiktokPackageManifestOperation));
WebRequestCounter.RecordRequestFailed(_packageName, nameof(LoadWebPackageManifestOperation));
}
}
if (_steps == ESteps.VerifyFileData)
{
string fileHash = HashUtility.BytesCRC32(_webDataRequestOp.Result);
if (fileHash == _packageHash)
if (ManifestTools.VerifyManifestData(_webDataRequestOp.Result, _packageHash))
{
_steps = ESteps.LoadManifest;
}
@@ -84,7 +87,7 @@ internal class LoadTiktokPackageManifestOperation : AsyncOperationBase
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = "Failed to verify package manifest file!";
Error = "Failed to verify web package manifest file!";
}
}
@@ -92,7 +95,7 @@ internal class LoadTiktokPackageManifestOperation : AsyncOperationBase
{
if (_deserializer == null)
{
_deserializer = new DeserializeManifestOperation(_fileSystem.ManifestServices, _webDataRequestOp.Result);
_deserializer = new DeserializeManifestOperation(_manifestServices, _webDataRequestOp.Result);
_deserializer.StartOperation();
AddChildOperation(_deserializer);
}
@@ -116,14 +119,17 @@ internal class LoadTiktokPackageManifestOperation : AsyncOperationBase
}
}
}
internal override string InternalGetDesc()
{
return $"PackageVersion : {_packageVersion} PackageHash : {_packageHash}";
}
private string GetRequestURL(string fileName)
{
// 轮流返回请求地址
if (_requestCount % 2 == 0)
return _fileSystem.RemoteServices.GetRemoteMainURL(fileName);
return _remoteServices.GetRemoteMainURL(fileName);
else
return _fileSystem.RemoteServices.GetRemoteFallbackURL(fileName);
return _remoteServices.GetRemoteFallbackURL(fileName);
}
}
#endif
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: f2a5bb0106a45e540a43a05b72a75bcd
guid: eb2ed9a86dbe88c42a3715b90df0e266
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -1,7 +1,6 @@
#if UNITY_WEBGL && DOUYINMINIGAME
using YooAsset;
using YooAsset;
internal class RequestTiktokPackageHashOperation : AsyncOperationBase
internal class RequestWebPackageHashOperation : AsyncOperationBase
{
private enum ESteps
{
@@ -10,7 +9,8 @@ internal class RequestTiktokPackageHashOperation : AsyncOperationBase
Done,
}
private readonly TiktokFileSystem _fileSystem;
private readonly IRemoteServices _remoteServices;
private readonly string _packageName;
private readonly string _packageVersion;
private readonly int _timeout;
private UnityWebTextRequestOperation _webTextRequestOp;
@@ -23,15 +23,16 @@ internal class RequestTiktokPackageHashOperation : AsyncOperationBase
public string PackageHash { private set; get; }
public RequestTiktokPackageHashOperation(TiktokFileSystem fileSystem, string packageVersion, int timeout)
public RequestWebPackageHashOperation(IRemoteServices remoteServices, string packageName, string packageVersion, int timeout)
{
_fileSystem = fileSystem;
_remoteServices = remoteServices;
_packageName = packageName;
_packageVersion = packageVersion;
_timeout = timeout;
}
internal override void InternalStart()
{
_requestCount = WebRequestCounter.GetRequestFailedCount(_fileSystem.PackageName, nameof(RequestTiktokPackageHashOperation));
_requestCount = WebRequestCounter.GetRequestFailedCount(_packageName, nameof(RequestWebPackageHashOperation));
_steps = ESteps.RequestPackageHash;
}
internal override void InternalUpdate()
@@ -43,7 +44,7 @@ internal class RequestTiktokPackageHashOperation : AsyncOperationBase
{
if (_webTextRequestOp == null)
{
string fileName = YooAssetSettingsData.GetPackageHashFileName(_fileSystem.PackageName, _packageVersion);
string fileName = YooAssetSettingsData.GetPackageHashFileName(_packageName, _packageVersion);
string url = GetRequestURL(fileName);
_webTextRequestOp = new UnityWebTextRequestOperation(url, _timeout);
_webTextRequestOp.StartOperation();
@@ -62,7 +63,7 @@ internal class RequestTiktokPackageHashOperation : AsyncOperationBase
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Wechat package hash file content is empty !";
Error = $"Web package hash file content is empty !";
}
else
{
@@ -75,7 +76,7 @@ internal class RequestTiktokPackageHashOperation : AsyncOperationBase
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _webTextRequestOp.Error;
WebRequestCounter.RecordRequestFailed(_fileSystem.PackageName, nameof(RequestTiktokPackageHashOperation));
WebRequestCounter.RecordRequestFailed(_packageName, nameof(RequestWebPackageHashOperation));
}
}
}
@@ -84,9 +85,8 @@ internal class RequestTiktokPackageHashOperation : AsyncOperationBase
{
// 轮流返回请求地址
if (_requestCount % 2 == 0)
return _fileSystem.RemoteServices.GetRemoteMainURL(fileName);
return _remoteServices.GetRemoteMainURL(fileName);
else
return _fileSystem.RemoteServices.GetRemoteFallbackURL(fileName);
return _remoteServices.GetRemoteFallbackURL(fileName);
}
}
#endif
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9c7603967834be04e9307b6d4eec2666
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +1,6 @@
#if UNITY_WEBGL && DOUYINMINIGAME
using YooAsset;
using YooAsset;
internal class RequestTiktokPackageVersionOperation : AsyncOperationBase
internal class RequestWebPackageVersionOperation : AsyncOperationBase
{
private enum ESteps
{
@@ -10,7 +9,8 @@ internal class RequestTiktokPackageVersionOperation : AsyncOperationBase
Done,
}
private readonly TiktokFileSystem _fileSystem;
private readonly IRemoteServices _remoteServices;
private readonly string _packageName;
private readonly bool _appendTimeTicks;
private readonly int _timeout;
private UnityWebTextRequestOperation _webTextRequestOp;
@@ -23,15 +23,16 @@ internal class RequestTiktokPackageVersionOperation : AsyncOperationBase
public string PackageVersion { private set; get; }
public RequestTiktokPackageVersionOperation(TiktokFileSystem fileSystem, bool appendTimeTicks, int timeout)
public RequestWebPackageVersionOperation(IRemoteServices remoteServices, string packageName, bool appendTimeTicks, int timeout)
{
_fileSystem = fileSystem;
_remoteServices = remoteServices;
_packageName = packageName;
_appendTimeTicks = appendTimeTicks;
_timeout = timeout;
}
internal override void InternalStart()
{
_requestCount = WebRequestCounter.GetRequestFailedCount(_fileSystem.PackageName, nameof(RequestTiktokPackageVersionOperation));
_requestCount = WebRequestCounter.GetRequestFailedCount(_packageName, nameof(RequestWebPackageVersionOperation));
_steps = ESteps.RequestPackageVersion;
}
internal override void InternalUpdate()
@@ -43,7 +44,7 @@ internal class RequestTiktokPackageVersionOperation : AsyncOperationBase
{
if (_webTextRequestOp == null)
{
string fileName = YooAssetSettingsData.GetPackageVersionFileName(_fileSystem.PackageName);
string fileName = YooAssetSettingsData.GetPackageVersionFileName(_packageName);
string url = GetRequestURL(fileName);
_webTextRequestOp = new UnityWebTextRequestOperation(url, _timeout);
_webTextRequestOp.StartOperation();
@@ -62,7 +63,7 @@ internal class RequestTiktokPackageVersionOperation : AsyncOperationBase
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Wechat package version file content is empty !";
Error = $"Web package version file content is empty !";
}
else
{
@@ -75,7 +76,7 @@ internal class RequestTiktokPackageVersionOperation : AsyncOperationBase
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _webTextRequestOp.Error;
WebRequestCounter.RecordRequestFailed(_fileSystem.PackageName, nameof(RequestTiktokPackageVersionOperation));
WebRequestCounter.RecordRequestFailed(_packageName, nameof(RequestWebPackageVersionOperation));
}
}
}
@@ -86,9 +87,9 @@ internal class RequestTiktokPackageVersionOperation : AsyncOperationBase
// 轮流返回请求地址
if (_requestCount % 2 == 0)
url = _fileSystem.RemoteServices.GetRemoteMainURL(fileName);
url = _remoteServices.GetRemoteMainURL(fileName);
else
url = _fileSystem.RemoteServices.GetRemoteFallbackURL(fileName);
url = _remoteServices.GetRemoteFallbackURL(fileName);
// 在URL末尾添加时间戳
if (_appendTimeTicks)
@@ -96,5 +97,4 @@ internal class RequestTiktokPackageVersionOperation : AsyncOperationBase
else
return url;
}
}
#endif
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ae045c2050b3e8a4d91fb0585bdfb2c0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -43,10 +43,24 @@ namespace YooAsset
/// </summary>
public int BundleLoadingMaxConcurrency = int.MaxValue;
/// <summary>
/// 当资源引用计数为零的时候自动释放资源包
/// </summary>
public bool AutoUnloadBundleWhenUnused = false;
/// <summary>
/// WebGL平台强制同步加载资源对象
/// </summary>
public bool WebGLForceSyncLoadAsset = false;
#if YOOASSET_EXPERIMENTAL
/// <summary>
/// 启用弱引用资源句柄
/// </summary>
public bool UseWeakReferenceHandle = false;
#else
internal bool UseWeakReferenceHandle = false;
#endif
}
/// <summary>

View File

@@ -1,4 +1,5 @@
using System.Collections;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
@@ -16,6 +17,8 @@ namespace YooAsset
private static readonly List<AsyncOperationBase> _operations = new List<AsyncOperationBase>(1000);
private static readonly List<AsyncOperationBase> _newList = new List<AsyncOperationBase>(1000);
private static Action<string, AsyncOperationBase> _startCallback = null;
private static Action<string, AsyncOperationBase> _finishCallback = null;
// 计时器相关
private static Stopwatch _watch;
@@ -33,6 +36,10 @@ namespace YooAsset
{
get
{
if (_watch == null)
return false;
// NOTE : 单次调用开销约1微秒
return _watch.ElapsedMilliseconds - _frameTime >= MaxTimeSlice;
}
}
@@ -57,7 +64,12 @@ namespace YooAsset
{
var operation = _operations[i];
if (operation.IsFinish)
{
_operations.RemoveAt(i);
if (_finishCallback != null)
_finishCallback.Invoke(operation.PackageName, operation);
}
}
// 添加新增的异步操作
@@ -82,10 +94,11 @@ namespace YooAsset
}
// 更新进行中的异步操作
bool checkBusy = MaxTimeSlice < long.MaxValue;
_frameTime = _watch.ElapsedMilliseconds;
for (int i = 0; i < _operations.Count; i++)
{
if (IsBusy)
if (checkBusy && IsBusy)
break;
var operation = _operations[i];
@@ -103,6 +116,8 @@ namespace YooAsset
{
_operations.Clear();
_newList.Clear();
_startCallback = null;
_finishCallback = null;
_watch = null;
_frameTime = 0;
MaxTimeSlice = long.MaxValue;
@@ -140,6 +155,25 @@ namespace YooAsset
_newList.Add(operation);
operation.SetPackageName(packageName);
operation.StartOperation();
if (_startCallback != null)
_startCallback.Invoke(packageName, operation);
}
/// <summary>
/// 监听任务开始
/// </summary>
public static void RegisterStartCallback(Action<string, AsyncOperationBase> callback)
{
_startCallback = callback;
}
/// <summary>
/// 监听任务结束
/// </summary>
public static void RegisterFinishCallback(Action<string, AsyncOperationBase> callback)
{
_finishCallback = callback;
}
#region

View File

@@ -23,6 +23,11 @@ namespace YooAsset
if (IsValidWithWarning == false)
return;
Provider.ReleaseHandle(this);
// 主动卸载零引用的资源包
if (Provider.RefCount == 0)
Provider.TryUnloadBundle();
Provider = null;
}
@@ -146,11 +151,11 @@ namespace YooAsset
/// </summary>
public System.Threading.Tasks.Task Task
{
get
get
{
if (IsValidWithWarning == false)
return null;
return Provider.Task;
return Provider.Task;
}
}

View File

@@ -83,6 +83,7 @@ namespace YooAsset
{
if (_loadBundleOp == null)
{
// 统计计数增加
_resManager.BundleLoadingCounter++;
_loadBundleOp = LoadBundleInfo.LoadBundleFile();
_loadBundleOp.StartOperation();
@@ -163,14 +164,22 @@ namespace YooAsset
{
IsDestroyed = true;
// Check fatal
// 注意:正在加载中的任务不可以销毁
if (_steps == ESteps.LoadBundleFile)
throw new Exception($"Bundle file loader is not done : {LoadBundleInfo.Bundle.BundleName}");
if (RefCount > 0)
throw new Exception($"Bundle file loader ref is not zero : {LoadBundleInfo.Bundle.BundleName}");
if (IsDone == false)
throw new Exception($"Bundle file loader is not done : {LoadBundleInfo.Bundle.BundleName}");
if (Result != null)
Result.UnloadBundleFile();
if (IsDone == false)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = "Bundle loader destroyed !";
}
}
/// <summary>
@@ -178,10 +187,7 @@ namespace YooAsset
/// </summary>
public bool CanDestroyLoader()
{
if (IsDone == false)
return false;
if (RefCount > 0)
if (CanReleasableLoader() == false)
return false;
// YOOASSET_LEGACY_DEPENDENCY
@@ -191,14 +197,34 @@ namespace YooAsset
{
foreach (var bundleID in LoadBundleInfo.Bundle.ReferenceBundleIDs)
{
#if YOOASSET_EXPERIMENTAL
if (_resManager.CheckBundleReleasable(bundleID) == false)
return false;
#else
if (_resManager.CheckBundleDestroyed(bundleID) == false)
return false;
#endif
}
}
return true;
}
/// <summary>
/// 是否可以释放
/// </summary>
public bool CanReleasableLoader()
{
// 注意:正在加载中的任务不可以销毁
if (_steps == ESteps.LoadBundleFile)
return false;
if (RefCount > 0)
return false;
return true;
}
/// <summary>
/// 添加附属的资源提供者
/// </summary>
@@ -237,5 +263,28 @@ namespace YooAsset
_removeList.Clear();
}
}
/// <summary>
/// 尝试终止加载器
/// </summary>
public void TryAbortLoader()
{
if (IsDone == false)
{
if (_steps == ESteps.CheckConcurrency)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = "Abort bundle loader !";
}
if (_steps == ESteps.LoadBundleFile)
{
// 注意:终止下载器
if (_loadBundleOp != null)
_loadBundleOp.AbortDownloadFile = true;
}
}
}
}
}

View File

@@ -23,7 +23,7 @@ namespace YooAsset
None,
CheckOptions,
ReleaseAll,
AbortDownload,
TryAbortLoader,
CheckLoading,
DestroyAll,
Done,
@@ -78,15 +78,16 @@ namespace YooAsset
}
}
_steps = ESteps.AbortDownload;
_steps = ESteps.TryAbortLoader;
}
if (_steps == ESteps.AbortDownload)
if (_steps == ESteps.TryAbortLoader)
{
// 注意:终止所有载任务
// 尝试终止所有载任务
// 注意正在加载AssetBundle的任务无法终止
foreach (var loader in _resManager.LoaderDic.Values)
{
loader.AbortOperation();
loader.TryAbortLoader();
}
_steps = ESteps.CheckLoading;
}

View File

@@ -17,7 +17,7 @@ namespace YooAsset
AddChildOperation(_loadAllAssetsOp);
#if UNITY_WEBGL
if (_resManager.WebGLForceSyncLoadAsset())
if (_resManager.WebGLForceSyncLoadAsset)
_loadAllAssetsOp.WaitForAsyncComplete();
#endif
}

View File

@@ -17,7 +17,7 @@ namespace YooAsset
AddChildOperation(_loadAssetOp);
#if UNITY_WEBGL
if (_resManager.WebGLForceSyncLoadAsset())
if (_resManager.WebGLForceSyncLoadAsset)
_loadAssetOp.WaitForAsyncComplete();
#endif
}

Some files were not shown because too many files have changed in this diff Show More