Compare commits

...

66 Commits

Author SHA1 Message Date
何冠峰
79e0cf85f9 Update CHANGELOG.md 2025-02-19 19:10:36 +08:00
何冠峰
e996eaa008 Update package.json 2025-02-19 19:10:28 +08:00
何冠峰
5088c9e985 update asset bundle builder 2025-02-19 18:46:39 +08:00
何冠峰
610b3c6d32 Update FileSystemParameters.cs 2025-02-19 18:36:43 +08:00
何冠峰
cc7290f10e update operation system
快速启动模式
2025-02-19 18:36:33 +08:00
何冠峰
576b842368 support legacy dependency mode
YOOASSET_LEGACY_DEPENDENCY
2025-02-19 18:27:23 +08:00
何冠峰
d23c0ba715 update space shooter 2025-02-18 19:35:46 +08:00
何冠峰
98e19baebd Update TextureSchema.cs 2025-02-18 19:34:41 +08:00
何冠峰
f5947db44a Update ReorderableListView.cs 2025-02-18 19:34:34 +08:00
何冠峰
e978164329 Update ReorderableListView.cs 2025-02-18 19:28:55 +08:00
何冠峰
966c8f2efa update space shooter 2025-02-18 18:41:05 +08:00
何冠峰
a57fec3d71 update UIElements 2025-02-18 18:38:00 +08:00
何冠峰
84844eda20 update UIElements 2025-02-18 17:31:49 +08:00
何冠峰
698cdcba61 update AssetArtScanner 2025-02-17 18:18:07 +08:00
何冠峰
1d6c9393d4 Update AssetBundleCollector
支持列表元素上下拖拽排序
2025-02-17 17:54:46 +08:00
何冠峰
b654ac156d update AssetArtScanner
支持列表元素上下拖拽排序
2025-02-17 17:54:34 +08:00
何冠峰
d133a9a692 update extension sample 2025-02-17 15:44:41 +08:00
何冠峰
d55db19f0e update extension sample
微信小游戏和抖音小游戏AssetBundle使用插件卸载机制。
2025-02-14 16:37:23 +08:00
何冠峰
e3fc3df32c update space shooter 2025-02-14 12:05:30 +08:00
何冠峰
f2334da72d update extension sample 2025-02-14 12:05:24 +08:00
何冠峰
2902b6c2cf fix #472 2025-02-14 11:29:13 +08:00
何冠峰
dfa95b57b9 Update CHANGELOG.md 2025-02-14 10:03:39 +08:00
何冠峰
33a2cf66d0 Update CHANGELOG.md 2025-02-14 10:03:15 +08:00
何冠峰
5f52cf5b51 Update package.json 2025-02-14 10:03:09 +08:00
何冠峰
9d07905f2d fix #471 2025-02-13 20:14:33 +08:00
何冠峰
26dbe9dfdd update extension sample 2025-02-13 19:08:23 +08:00
何冠峰
98c5851071 update extension file system
解决微信小游戏预下载和正常下载冲突的问题
2025-02-13 18:57:39 +08:00
何冠峰
a6ee571d65 update file system 2025-02-13 18:56:24 +08:00
何冠峰
a138701afe update extension sample
抖音小游戏支持资源加密
2025-02-13 12:12:52 +08:00
何冠峰
e52bdea255 fix #467
微信小游戏资源加密
2025-02-13 12:02:09 +08:00
何冠峰
068a712a30 Merge pull request #470 from suxf/dev
fix: 微信加密资源解密错误
2025-02-13 10:13:28 +08:00
枫似锦
80a5300648 fix: 微信加密资源解密错误 2025-02-13 00:12:26 +08:00
何冠峰
0c36e458f7 update space shooter 2025-02-12 17:43:15 +08:00
何冠峰
b2fa52e4c4 update AssetArtScanner 2025-02-12 17:43:07 +08:00
何冠峰
151e978e5b update space shoot 2025-02-12 16:29:26 +08:00
何冠峰
9e806861ec update extension sample 2025-02-12 16:28:31 +08:00
何冠峰
a9a9368b9b update test sample 2025-02-12 16:27:51 +08:00
何冠峰
7936ba31ea update file system
WebGL网页平台支持资源加密。
2025-02-12 16:27:30 +08:00
何冠峰
afc456de9a Update UnloadAllAssetsOperation.cs 2025-02-12 14:44:02 +08:00
何冠峰
a98db0ba83 update extension sample 2025-02-12 14:43:51 +08:00
何冠峰
fb8720edd3 update extension sample
抖音小游戏支持文件加密。
2025-02-12 11:59:09 +08:00
何冠峰
2aa2a0ac3a update space shooter 2025-02-12 11:46:38 +08:00
何冠峰
0531b6ef3a update extension sample 2025-02-12 11:45:12 +08:00
何冠峰
24142de11f update extension sample
支持微信小游戏文件加密
2025-02-12 11:23:27 +08:00
何冠峰
7fad6eb70b update services
增加WebGL端解密接口
2025-02-12 11:22:09 +08:00
何冠峰
f60227abdf Merge pull request #469 from suxf/dev
优化微信小游戏文件系统逻辑
2025-02-12 10:10:32 +08:00
枫似锦
18d6a74c53 Merge branch 'dev' of https://github.com/suxf/YooAsset into dev 2025-02-12 00:30:22 +08:00
枫似锦
03d06ba657 优化微信小游戏文件系统逻辑 2025-02-12 00:29:10 +08:00
何冠峰
07086b68c8 update extension sample
优化了抖音小游戏文件系统缓存机制
2025-02-11 18:44:51 +08:00
何冠峰
0a85f3126f update extension sample
优化了微信小游戏文件系统缓存机制。
2025-02-11 18:18:29 +08:00
何冠峰
efa4180340 update resource manager
UnloadUnusedAssetsOperation逻辑里移除了Resources.UnloadUnusedAssets调用
2025-02-11 18:15:45 +08:00
何冠峰
fb06f2aa11 update resource manager
UnloadAllAssetsAsync新增UnloadAllAssetsOptions参数
2025-02-11 17:32:31 +08:00
何冠峰
ce023cedb8 update extension sample 2025-02-11 15:13:45 +08:00
何冠峰
3d1a28a50e update file system 2025-02-11 15:09:23 +08:00
何冠峰
5d2d0b4168 fix #341 2025-02-11 10:20:33 +08:00
何冠峰
fa985a5a93 Merge branch 'dev' of https://github.com/tuyoogame/YooAsset into dev 2025-02-11 09:55:38 +08:00
何冠峰
40f9937b60 update space shooter 2025-02-11 09:55:37 +08:00
何冠峰
c543c629c3 Merge pull request #466 from suxf/dev
fix:微信小游戏缓存文件系统查询机制不生效
2025-02-11 09:43:16 +08:00
何冠峰
f861279c49 Update CHANGELOG.md 2025-02-10 20:04:35 +08:00
何冠峰
ee89f81d46 Update package.json 2025-02-10 20:04:31 +08:00
何冠峰
6d216561f8 fix #468 2025-02-10 20:00:48 +08:00
枫似锦
0a96e583d3 Merge branch 'dev' of https://github.com/suxf/YooAsset into dev 2025-02-10 16:39:31 +08:00
枫似锦
c9d263c60d fix:微信小游戏缓存文件系统查询机制不生效 2025-02-10 16:38:23 +08:00
何冠峰
2d6488abf4 update AssetArtScanner
配置和报告容错性检测
2025-02-10 16:21:43 +08:00
何冠峰
7dfbac4a24 update AssetBundleCollector 2025-02-10 16:19:07 +08:00
何冠峰
7cfe4cb2c9 fix #465 2025-02-10 16:17:38 +08:00
92 changed files with 2516 additions and 813 deletions

View File

@@ -2,6 +2,93 @@
All notable changes to this package will be documented in this file. All notable changes to this package will be documented in this file.
## [2.3.0-preview] - 2025-02-19
### Improvements
资源收集窗口列表元素支持手动上下拖拽排序!
资源扫描窗口列表元素支持手动上下拖拽排序!
### Added
- 新增了UIElements扩展类ReorderableListView
- 新增初始化方法
```csharp
public class YooAssets
{
/// <summary>
/// 设置异步系统参数,快速启动模式的开关
/// 注意:该模式默认开启
/// </summary>
public static void SetOperationSystemQuickStartMode(bool state)
}
```
- 新增打包构建参数
```csharp
public class BuildParameters
{
/// <summary>
/// 旧版依赖模式
/// 说明兼容YooAssets1.5.x版本
/// </summary>
public bool LegacyDependency = false;
}
```
### Fixed
- (#472) 修复了Unity6平台TableView视图无法显示问题。
- 修复了微信小游戏和抖音小游戏未正确使用插件的卸载方法。
## [2.2.12] - 2025-02-14
### Improvements
- WebGL网页平台支持文件加密。
- 微信小游戏平台支持文件加密。
- 抖音小游戏平台支持文件加密。
### Fixed
- (#466) 修复了微信小游戏文件系统查询机制不生效!
- (#341) 修复了微信小游戏的下载进度异常问题。
- (#471) 修复了Unity2019,Unity2020平台上TableView视图无法显示的问题。
### Added
- 新增了ResourcePackage.UnloadAllAssetsAsync(UnloadAllAssetsOptions options)方法
```csharp
public sealed class UnloadAllAssetsOptions
{
/// <summary>
/// 释放所有资源句柄,防止卸载过程中触发完成回调!
/// </summary>
public bool ReleaseAllHandles = true;
/// <summary>
/// 卸载过程中锁定加载操作,防止新的任务请求!
/// </summary>
public bool LockLoadOperation = true;
}
```
## [2.2.11] - 2025-02-10
### Improvements
- AssetArtScanner配置和生成报告的容错性检测。
### Fixed
- (#465) 修复了特殊情况下,没有配置资源包文件后缀名构建失败的问题。
- (#468) 修复了安卓平台二次启动加载原生文件或加密文件失败的问题。
## [2.2.10] - 2025-02-08 ## [2.2.10] - 2025-02-08
### Improvements ### Improvements

View File

@@ -3,9 +3,24 @@ namespace YooAsset.Editor
{ {
public enum EHeaderType public enum EHeaderType
{ {
/// <summary>
/// 资源路径
/// </summary>
AssetPath, AssetPath,
/// <summary>
/// 字符串
/// </summary>
StringValue, StringValue,
/// <summary>
/// 整数数值
/// </summary>
LongValue, LongValue,
/// <summary>
/// 浮点数数值
/// </summary>
DoubleValue, DoubleValue,
} }
} }

View File

@@ -31,12 +31,28 @@ namespace YooAsset.Editor
/// <summary> /// <summary>
/// 添加扫描信息 /// 添加扫描信息
/// </summary> /// </summary>
public void AddScanInfo(string headerTitle, string scanInfo) public void AddScanInfo(string headerTitle, string value)
{ {
var reportScanInfo = new ReportScanInfo(headerTitle, scanInfo); var reportScanInfo = new ReportScanInfo(headerTitle, value);
ScanInfos.Add(reportScanInfo); ScanInfos.Add(reportScanInfo);
} }
/// <summary>
/// 添加扫描信息
/// </summary>
public void AddScanInfo(string headerTitle, long value)
{
AddScanInfo(headerTitle, value.ToString());
}
/// <summary>
/// 添加扫描信息
/// </summary>
public void AddScanInfo(string headerTitle, double value)
{
AddScanInfo(headerTitle, value.ToString());
}
/// <summary> /// <summary>
/// 获取扫描信息 /// 获取扫描信息
/// </summary> /// </summary>

View File

@@ -1,4 +1,5 @@
using System; using System;
using UnityEditor;
namespace YooAsset.Editor namespace YooAsset.Editor
{ {
@@ -93,5 +94,35 @@ namespace YooAsset.Editor
HeaderType = value; HeaderType = value;
return this; return this;
} }
/// <summary>
/// 检测数值有效性
/// </summary>
public void CheckValueValid(string value)
{
if (HeaderType == EHeaderType.AssetPath)
{
string guid = AssetDatabase.AssetPathToGUID(value);
if (string.IsNullOrEmpty(guid))
throw new Exception($"{HeaderTitle} value is invalid asset path : {value}");
}
else if (HeaderType == EHeaderType.DoubleValue)
{
if (double.TryParse(value, out double doubleValue) == false)
throw new Exception($"{HeaderTitle} value is invalid double value : {value}");
}
else if (HeaderType == EHeaderType.LongValue)
{
if (long.TryParse(value, out long longValue) == false)
throw new Exception($"{HeaderTitle} value is invalid long value : {value}");
}
else if (HeaderType == EHeaderType.StringValue)
{
}
else
{
throw new System.NotImplementedException(HeaderType.ToString());
}
}
} }
} }

View File

@@ -29,9 +29,9 @@ namespace YooAsset.Editor
/// <summary> /// <summary>
/// 报告标题 /// 报告名称
/// </summary> /// </summary>
public string ReportTitle; public string ReportName;
/// <summary> /// <summary>
/// 报告介绍 /// 报告介绍
@@ -41,7 +41,7 @@ namespace YooAsset.Editor
/// <summary> /// <summary>
/// 报告的标题列表 /// 报告的标题列表
/// </summary> /// </summary>
public List<ReportHeader> HeaderTitles = new List<ReportHeader>(); public List<ReportHeader> ReportHeaders = new List<ReportHeader>();
/// <summary> /// <summary>
/// 扫描的元素列表 /// 扫描的元素列表
@@ -49,23 +49,70 @@ namespace YooAsset.Editor
public List<ReportElement> ReportElements = new List<ReportElement>(); public List<ReportElement> ReportElements = new List<ReportElement>();
public ScanReport(string reportTitle, string reportDesc) public ScanReport(string reportName, string reportDesc)
{ {
ReportTitle = reportTitle; ReportName = reportName;
ReportDesc = reportDesc; ReportDesc = reportDesc;
} }
/// <summary>
/// 添加标题
/// </summary>
public ReportHeader AddHeader(string headerTitle, int width) public ReportHeader AddHeader(string headerTitle, int width)
{ {
var reportHeader = new ReportHeader(headerTitle, width); var reportHeader = new ReportHeader(headerTitle, width);
HeaderTitles.Add(reportHeader); ReportHeaders.Add(reportHeader);
return reportHeader; return reportHeader;
} }
/// <summary>
/// 添加标题
/// </summary>
public ReportHeader AddHeader(string headerTitle, int width, int minWidth, int maxWidth) public ReportHeader AddHeader(string headerTitle, int width, int minWidth, int maxWidth)
{ {
var reportHeader = new ReportHeader(headerTitle, width, minWidth, maxWidth); var reportHeader = new ReportHeader(headerTitle, width, minWidth, maxWidth);
HeaderTitles.Add(reportHeader); ReportHeaders.Add(reportHeader);
return reportHeader; return reportHeader;
} }
/// <summary>
/// 检测错误
/// </summary>
public void CheckError()
{
// 检测标题
Dictionary<string, ReportHeader> headerMap = new Dictionary<string, ReportHeader>();
foreach (var header in ReportHeaders)
{
string headerTitle = header.HeaderTitle;
if (headerMap.ContainsKey(headerTitle))
throw new Exception($"The header title {headerTitle} already exists !");
else
headerMap.Add(headerTitle, header);
}
// 检测扫描元素
HashSet<string> elementMap = new HashSet<string>();
foreach (var element in ReportElements)
{
if (string.IsNullOrEmpty(element.GUID))
throw new Exception($"The report element GUID is null or empty !");
if (elementMap.Contains(element.GUID))
throw new Exception($"The report element GUID already exists ! {element.GUID}");
else
elementMap.Add(element.GUID);
foreach (var scanInfo in element.ScanInfos)
{
if (headerMap.ContainsKey(scanInfo.HeaderTitle) == false)
throw new Exception($"The report element header {scanInfo.HeaderTitle} is missing !");
// 检测数值有效性
var header = headerMap[scanInfo.HeaderTitle];
header.CheckValueValid(scanInfo.ScanInfo);
}
}
}
} }
} }

View File

@@ -55,9 +55,9 @@ namespace YooAsset.Editor
if (string.IsNullOrEmpty(SchemaType)) if (string.IsNullOrEmpty(SchemaType))
{ {
SchemaType = scanReport.SchemaType; SchemaType = scanReport.SchemaType;
ReportTitle = scanReport.ReportTitle; ReportTitle = scanReport.ReportName;
ReportDesc = scanReport.ReportDesc; ReportDesc = scanReport.ReportDesc;
Headers = scanReport.HeaderTitles; Headers = scanReport.ReportHeaders;
} }
if (SchemaType != scanReport.SchemaType) if (SchemaType != scanReport.SchemaType)
@@ -82,7 +82,7 @@ namespace YooAsset.Editor
List<ReportElement> elements = scanReport.ReportElements; List<ReportElement> elements = scanReport.ReportElements;
// 设置白名单 // 设置白名单
var scanner = AssetArtScannerSettingData.GetScannerByGUID(scannerGUID); var scanner = AssetArtScannerSettingData.Setting.GetScanner(scannerGUID);
if (scanner != null) if (scanner != null)
{ {
foreach (var element in elements) foreach (var element in elements)
@@ -144,7 +144,7 @@ namespace YooAsset.Editor
string scannerGUID = scanReport.ScannerGUID; string scannerGUID = scanReport.ScannerGUID;
var elements = scanReport.ReportElements; var elements = scanReport.ReportElements;
var scanner = AssetArtScannerSettingData.GetScannerByGUID(scannerGUID); var scanner = AssetArtScannerSettingData.Setting.GetScanner(scannerGUID);
if (scanner != null) if (scanner != null)
{ {
List<string> whiteList = new List<string>(elements.Count); List<string> whiteList = new List<string>(elements.Count);
@@ -207,7 +207,7 @@ namespace YooAsset.Editor
private void FixInternal(string scannerGUID, List<ReportElement> fixList) private void FixInternal(string scannerGUID, List<ReportElement> fixList)
{ {
AssetArtScanner scanner = AssetArtScannerSettingData.GetScannerByGUID(scannerGUID); AssetArtScanner scanner = AssetArtScannerSettingData.Setting.GetScanner(scannerGUID);
if (scanner != null) if (scanner != null)
{ {
var schema = scanner.LoadSchema(); var schema = scanner.LoadSchema();

View File

@@ -30,7 +30,7 @@ namespace YooAsset.Editor
// 检测标题数和内容是否匹配 // 检测标题数和内容是否匹配
foreach (var element in report.ReportElements) foreach (var element in report.ReportElements)
{ {
if (element.ScanInfos.Count != report.HeaderTitles.Count) if (element.ScanInfos.Count != report.ReportHeaders.Count)
{ {
throw new Exception($"报告的标题数和内容不匹配!"); throw new Exception($"报告的标题数和内容不匹配!");
} }

View File

@@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.IO;
using UnityEditor; using UnityEditor;
using UnityEngine; using UnityEngine;
@@ -46,6 +47,17 @@ namespace YooAsset.Editor
public List<string> WhiteList = new List<string>(); public List<string> WhiteList = new List<string>();
/// <summary>
/// 检测关键字匹配
/// </summary>
public bool CheckKeyword(string keyword)
{
if (ScannerName.Contains(keyword) || ScannerDesc.Contains(keyword))
return true;
else
return false;
}
/// <summary> /// <summary>
/// 是否在白名单里 /// 是否在白名单里
/// </summary> /// </summary>
@@ -54,6 +66,24 @@ namespace YooAsset.Editor
return WhiteList.Contains(guid); return WhiteList.Contains(guid);
} }
/// <summary>
/// 检测配置错误
/// </summary>
public void CheckConfigError()
{
if (string.IsNullOrEmpty(ScannerName))
throw new Exception($"Scanner name is null or empty !");
if (string.IsNullOrEmpty(ScannerSchema))
throw new Exception($"Scanner {ScannerName} schema is null !");
if (string.IsNullOrEmpty(SaveDirectory) == false)
{
if (Directory.Exists(SaveDirectory) == false)
throw new Exception($"Scanner {ScannerName} save directory is invalid : {SaveDirectory}");
}
}
/// <summary> /// <summary>
/// 加载扫描模式实例 /// 加载扫描模式实例
/// </summary> /// </summary>
@@ -85,14 +115,11 @@ namespace YooAsset.Editor
public ScanReport RunScanner() public ScanReport RunScanner()
{ {
if (Collectors.Count == 0) if (Collectors.Count == 0)
{ Debug.LogWarning($"Scanner {ScannerName} collector is empty !");
Debug.LogWarning($"Scanner collector is empty : {ScannerName}");
return null;
}
ScannerSchema schema = LoadSchema(); ScannerSchema schema = LoadSchema();
if (schema == null) if (schema == null)
return null; throw new Exception($"Failed to load schema : {ScannerSchema}");
var report = schema.RunScanner(this); var report = schema.RunScanner(this);
report.FileSign = ScannerDefine.ReportFileSign; report.FileSign = ScannerDefine.ReportFileSign;
@@ -101,13 +128,5 @@ namespace YooAsset.Editor
report.ScannerGUID = ScannerGUID; report.ScannerGUID = ScannerGUID;
return report; return report;
} }
public bool CheckKeyword(string keyword)
{
if (ScannerName.Contains(keyword) || ScannerDesc.Contains(keyword))
return true;
else
return false;
}
} }
} }

View File

@@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.IO; using System.IO;
using UnityEngine; using UnityEngine;
using NUnit.Framework.Constraints;
namespace YooAsset.Editor namespace YooAsset.Editor
{ {
@@ -13,5 +14,55 @@ namespace YooAsset.Editor
/// 扫描器列表 /// 扫描器列表
/// </summary> /// </summary>
public List<AssetArtScanner> Scanners = new List<AssetArtScanner>(); public List<AssetArtScanner> Scanners = new List<AssetArtScanner>();
/// <summary>
/// 开始扫描
/// </summary>
public ScannerResult BeginScan(string scannerGUID)
{
try
{
// 获取扫描器配置
var scanner = GetScanner(scannerGUID);
if (scanner == null)
throw new Exception($"Invalid scanner GUID : {scannerGUID}");
// 检测配置合法性
scanner.CheckConfigError();
// 开始扫描工作
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);
}
catch (Exception e)
{
return new ScannerResult(e.Message);
}
}
/// <summary>
/// 获取指定的扫描器
/// </summary>
public AssetArtScanner GetScanner(string scannerGUID)
{
foreach (var scanner in Scanners)
{
if (scanner.ScannerGUID == scannerGUID)
return scanner;
}
Debug.LogWarning($"Not found scanner : {scannerGUID}");
return null;
}
} }
} }

View File

@@ -61,10 +61,10 @@ namespace YooAsset.Editor
{ {
foreach (var scanner in Setting.Scanners) foreach (var scanner in Setting.Scanners)
{ {
var scanResult = ScanInternal(scanner); var scanResult = Setting.BeginScan(scanner.ScannerGUID);
if (scanResult.Succeed == false) if (scanResult.Succeed == false)
{ {
Debug.LogError($"Scanner {scanner.ScannerName} failed ! {scanResult.ErrorInfo}"); Debug.LogError($"{scanner.ScannerName} failed : {scanResult.ErrorInfo}");
} }
} }
} }
@@ -82,10 +82,10 @@ namespace YooAsset.Editor
continue; continue;
} }
var scanResult = ScanInternal(scanner); var scanResult = Setting.BeginScan(scanner.ScannerGUID);
if (scanResult.Succeed == false) if (scanResult.Succeed == false)
{ {
Debug.LogError($"Scanner {scanner.ScannerName} failed ! {scanResult.ErrorInfo}"); Debug.LogError($"{scanner.ScannerName} failed : {scanResult.ErrorInfo}");
} }
} }
} }
@@ -95,30 +95,14 @@ namespace YooAsset.Editor
/// </summary> /// </summary>
public static ScannerResult Scan(string scannerGUID) public static ScannerResult Scan(string scannerGUID)
{ {
AssetArtScanner scanner = GetScannerByGUID(scannerGUID); var scanResult = Setting.BeginScan(scannerGUID);
var scanResult = ScanInternal(scanner);
if (scanResult.Succeed == false) if (scanResult.Succeed == false)
{ {
Debug.LogError($"Scanner {scanner.ScannerName} failed ! {scanResult.ErrorInfo}"); Debug.LogError(scanResult.ErrorInfo);
} }
return scanResult; return scanResult;
} }
/// <summary>
/// 获取指定的扫描器
/// </summary>
public static AssetArtScanner GetScannerByGUID(string scannerGUID)
{
foreach (var scanner in Setting.Scanners)
{
if (scanner.ScannerGUID == scannerGUID)
return scanner;
}
Debug.LogWarning($"Not found scanner : {scannerGUID}");
return null;
}
// 扫描器编辑相关 // 扫描器编辑相关
public static AssetArtScanner CreateScanner(string name, string desc) public static AssetArtScanner CreateScanner(string name, string desc)
{ {
@@ -173,31 +157,5 @@ namespace YooAsset.Editor
IsDirty = true; IsDirty = true;
} }
} }
private static ScannerResult ScanInternal(AssetArtScanner scanner)
{
if (scanner == null)
return new ScannerResult("Scanner is null !");
string saveDirectory = "Assets/";
if (string.IsNullOrEmpty(scanner.SaveDirectory) == false)
{
saveDirectory = scanner.SaveDirectory;
if (Directory.Exists(saveDirectory) == false)
return new ScannerResult($"Scanner save directory is invalid : {saveDirectory}");
}
ScanReport report = scanner.RunScanner();
if (report != null)
{
string filePath = $"{saveDirectory}/{scanner.ScannerName}_{scanner.ScannerDesc}.json";
ScanReportConfig.ExportJsonConfig(filePath, report);
return new ScannerResult(filePath, report);
}
else
{
return new ScannerResult($"Scanner run failed : {scanner.ScannerName}");
}
}
} }
} }

View File

@@ -69,7 +69,6 @@ namespace YooAsset.Editor
_scannerListView = root.Q<ListView>("ScannerListView"); _scannerListView = root.Q<ListView>("ScannerListView");
_scannerListView.makeItem = MakeScannerListViewItem; _scannerListView.makeItem = MakeScannerListViewItem;
_scannerListView.bindItem = BindScannerListViewItem; _scannerListView.bindItem = BindScannerListViewItem;
#if UNITY_2022_3_OR_NEWER #if UNITY_2022_3_OR_NEWER
_scannerListView.selectionChanged += ScannerListView_onSelectionChange; _scannerListView.selectionChanged += ScannerListView_onSelectionChange;
#elif UNITY_2020_1_OR_NEWER #elif UNITY_2020_1_OR_NEWER
@@ -277,12 +276,23 @@ namespace YooAsset.Editor
{ {
_scannerListView.Clear(); _scannerListView.Clear();
_scannerListView.ClearSelection(); _scannerListView.ClearSelection();
_scannerListView.itemsSource = FilterScanners();
_scannerListView.Rebuild();
if (_lastModifyScannerIndex >= 0 && _lastModifyScannerIndex < _scannerListView.itemsSource.Count) var filterItems = FilterScanners();
if (AssetArtScannerSettingData.Setting.Scanners.Count == filterItems.Count)
{ {
_scannerListView.selectedIndex = _lastModifyScannerIndex; #if UNITY_2020_3_OR_NEWER
_scannerListView.reorderable = true;
#endif
_scannerListView.itemsSource = AssetArtScannerSettingData.Setting.Scanners;
_scannerListView.Rebuild();
}
else
{
#if UNITY_2020_3_OR_NEWER
_scannerListView.reorderable = false;
#endif
_scannerListView.itemsSource = filterItems;
_scannerListView.Rebuild();
} }
} }
private List<AssetArtScanner> FilterScanners() private List<AssetArtScanner> FilterScanners()
@@ -344,31 +354,7 @@ namespace YooAsset.Editor
// 显示检视面板 // 显示检视面板
var scanSchema = selectScanner.LoadSchema(); var scanSchema = selectScanner.LoadSchema();
if (scanSchema != null) RefreshInspector(scanSchema);
{
var inspector = scanSchema.CreateInspector();
if (inspector == null)
{
UIElementsTools.SetElementVisible(_inspectorContainer, false);
}
else
{
if (inspector.Containner is VisualElement container)
{
UIElementsTools.SetElementVisible(_inspectorContainer, true);
_inspectorContainer.Clear();
_inspectorContainer.Add(container);
_inspectorContainer.style.width = inspector.Width;
_inspectorContainer.style.minWidth = inspector.MinWidth;
_inspectorContainer.style.maxWidth = inspector.MaxWidth;
}
else
{
Debug.LogWarning($"{nameof(ScannerSchema)} inspector container is invalid !");
UIElementsTools.SetElementVisible(_inspectorContainer, false);
}
}
}
// 设置Schema对象 // 设置Schema对象
if (scanSchema == null) if (scanSchema == null)
@@ -521,6 +507,38 @@ namespace YooAsset.Editor
AssetArtScannerSettingData.RemoveCollector(selectSacnner, selectCollector); AssetArtScannerSettingData.RemoveCollector(selectSacnner, selectCollector);
FillCollectorViewData(); FillCollectorViewData();
} }
// 属性面板相关
private void RefreshInspector(ScannerSchema scanSchema)
{
if (scanSchema == null)
{
UIElementsTools.SetElementVisible(_inspectorContainer, false);
return;
}
var inspector = scanSchema.CreateInspector();
if (inspector == null)
{
UIElementsTools.SetElementVisible(_inspectorContainer, false);
return;
}
if (inspector.Containner is VisualElement container)
{
UIElementsTools.SetElementVisible(_inspectorContainer, true);
_inspectorContainer.Clear();
_inspectorContainer.Add(container);
_inspectorContainer.style.width = inspector.Width;
_inspectorContainer.style.minWidth = inspector.MinWidth;
_inspectorContainer.style.maxWidth = inspector.MaxWidth;
}
else
{
Debug.LogWarning($"{nameof(ScannerSchema)} inspector container is invalid !");
UIElementsTools.SetElementVisible(_inspectorContainer, false);
}
}
} }
} }
#endif #endif

View File

@@ -9,7 +9,7 @@
<ui:VisualElement name="ScannerListContainer" style="width: 250px; flex-grow: 0; background-color: rgb(67, 67, 67); border-left-width: 5px; border-right-width: 5px; border-top-width: 5px; border-bottom-width: 5px;"> <ui:VisualElement name="ScannerListContainer" style="width: 250px; flex-grow: 0; background-color: rgb(67, 67, 67); border-left-width: 5px; border-right-width: 5px; border-top-width: 5px; border-bottom-width: 5px;">
<ui:Label text="Scanner List" display-tooltip-when-elided="true" name="ScannerListTitle" style="background-color: rgb(89, 89, 89); -unity-text-align: upper-center; -unity-font-style: bold; border-left-width: 3px; border-right-width: 3px; border-top-width: 3px; border-bottom-width: 3px; font-size: 12px;" /> <ui:Label text="Scanner List" display-tooltip-when-elided="true" name="ScannerListTitle" style="background-color: rgb(89, 89, 89); -unity-text-align: upper-center; -unity-font-style: bold; border-left-width: 3px; border-right-width: 3px; border-top-width: 3px; border-bottom-width: 3px; font-size: 12px;" />
<uie:ToolbarSearchField focusable="true" name="ScannerSearchField" style="width: 230px;" /> <uie:ToolbarSearchField focusable="true" name="ScannerSearchField" style="width: 230px;" />
<ui:ListView focusable="true" name="ScannerListView" item-height="20" virtualization-method="DynamicHeight" style="flex-grow: 1;" /> <ui:ListView focusable="true" name="ScannerListView" item-height="20" virtualization-method="DynamicHeight" reorder-mode="Animated" reorderable="true" style="flex-grow: 1;" />
<ui:VisualElement name="ScannerAddContainer" style="justify-content: center; flex-direction: row; flex-shrink: 0;"> <ui:VisualElement name="ScannerAddContainer" style="justify-content: center; flex-direction: row; flex-shrink: 0;">
<ui:Button text=" - " display-tooltip-when-elided="true" name="RemoveBtn" /> <ui:Button text=" - " display-tooltip-when-elided="true" name="RemoveBtn" />
<ui:Button text=" + " display-tooltip-when-elided="true" name="AddBtn" /> <ui:Button text=" + " display-tooltip-when-elided="true" name="AddBtn" />

View File

@@ -6,7 +6,7 @@ namespace YooAsset.Editor
/// <summary> /// <summary>
/// 检视界面的UI元素容器UIElements元素 /// 检视界面的UI元素容器UIElements元素
/// </summary> /// </summary>
public object Containner; public object Containner { private set; get; }
/// <summary> /// <summary>
/// 检视界面宽度 /// 检视界面宽度
@@ -22,5 +22,24 @@ namespace YooAsset.Editor
/// 检视界面最大宽度 /// 检视界面最大宽度
/// </summary> /// </summary>
public int MaxWidth = 250; public int MaxWidth = 250;
public SchemaInspector(object containner)
{
Containner = containner;
}
public SchemaInspector(object containner, int width)
{
Containner = containner;
Width = width;
MinWidth = width;
MaxWidth = width;
}
public SchemaInspector(object containner, int width, int minWidth, int maxWidth)
{
Containner = containner;
Width = width;
MinWidth = minWidth;
MaxWidth = maxWidth;
}
} }
} }

View File

@@ -51,6 +51,12 @@ namespace YooAsset.Editor
/// </summary> /// </summary>
public string PackageNote; public string PackageNote;
/// <summary>
/// 旧版依赖模式
/// 说明兼容YooAssets1.5.x版本
/// </summary>
public bool LegacyDependency = false;
/// <summary> /// <summary>
/// 清空构建缓存文件 /// 清空构建缓存文件
/// </summary> /// </summary>

View File

@@ -31,6 +31,7 @@ namespace YooAsset.Editor
// 创建新补丁清单 // 创建新补丁清单
PackageManifest manifest = new PackageManifest(); PackageManifest manifest = new PackageManifest();
manifest.FileVersion = YooAssetSettings.ManifestFileVersion; manifest.FileVersion = YooAssetSettings.ManifestFileVersion;
manifest.LegacyDependency = buildParameters.LegacyDependency;
manifest.EnableAddressable = buildMapContext.Command.EnableAddressable; manifest.EnableAddressable = buildMapContext.Command.EnableAddressable;
manifest.LocationToLower = buildMapContext.Command.LocationToLower; manifest.LocationToLower = buildMapContext.Command.LocationToLower;
manifest.IncludeAssetGUID = buildMapContext.Command.IncludeAssetGUID; manifest.IncludeAssetGUID = buildMapContext.Command.IncludeAssetGUID;
@@ -43,8 +44,8 @@ namespace YooAsset.Editor
manifest.AssetList = CreatePackageAssetList(buildMapContext); manifest.AssetList = CreatePackageAssetList(buildMapContext);
manifest.BundleList = CreatePackageBundleList(buildMapContext); manifest.BundleList = CreatePackageBundleList(buildMapContext);
// 处理资源清单的ID数据 // 处理资源清单的资源对象
ProcessPacakgeIDs(manifest); ProcessPacakgeAsset(manifest);
// 处理资源包的依赖列表 // 处理资源包的依赖列表
if (processBundleDepends) if (processBundleDepends)
@@ -54,6 +55,14 @@ namespace YooAsset.Editor
if (processBundleTags) if (processBundleTags)
ProcessBundleTags(manifest); ProcessBundleTags(manifest);
#region YOOASSET_LEGACY_DEPENDENCY
if (buildParameters.LegacyDependency)
{
if (processBundleDepends)
ProcessLegacyDependency(context, manifest);
}
#endregion
// 创建补丁清单文本文件 // 创建补丁清单文本文件
{ {
string fileName = YooAssetSettingsData.GetManifestJsonFileName(buildParameters.PackageName, buildParameters.PackageVersion); string fileName = YooAssetSettingsData.GetManifestJsonFileName(buildParameters.PackageName, buildParameters.PackageVersion);
@@ -137,7 +146,7 @@ namespace YooAsset.Editor
packageAsset.AssetPath = assetInfo.AssetInfo.AssetPath; packageAsset.AssetPath = assetInfo.AssetInfo.AssetPath;
packageAsset.AssetGUID = buildMapContext.Command.IncludeAssetGUID ? assetInfo.AssetInfo.AssetGUID : string.Empty; packageAsset.AssetGUID = buildMapContext.Command.IncludeAssetGUID ? assetInfo.AssetInfo.AssetGUID : string.Empty;
packageAsset.AssetTags = assetInfo.AssetTags.ToArray(); packageAsset.AssetTags = assetInfo.AssetTags.ToArray();
packageAsset.BundleNameInEditor = assetInfo.BundleName; packageAsset.TempDataInEditor = assetInfo;
result.Add(packageAsset); result.Add(packageAsset);
} }
} }
@@ -165,9 +174,9 @@ namespace YooAsset.Editor
} }
/// <summary> /// <summary>
/// 处理资源清单的ID数据 /// 处理资源清单的资源对象列表
/// </summary> /// </summary>
private void ProcessPacakgeIDs(PackageManifest manifest) private void ProcessPacakgeAsset(PackageManifest manifest)
{ {
// 注意:优先缓存资源包索引 // 注意:优先缓存资源包索引
for (int index = 0; index < manifest.BundleList.Count; index++) for (int index = 0; index < manifest.BundleList.Count; index++)
@@ -176,10 +185,11 @@ namespace YooAsset.Editor
_cachedBundleIndexIDs.Add(bundleName, index); _cachedBundleIndexIDs.Add(bundleName, index);
} }
// 记录资源对象所属的资源包ID
foreach (var packageAsset in manifest.AssetList) foreach (var packageAsset in manifest.AssetList)
{ {
string bundleName = packageAsset.BundleNameInEditor; var assetInfo = packageAsset.TempDataInEditor as BuildAssetInfo;
packageAsset.BundleID = GetCachedBundleIndexID(bundleName); packageAsset.BundleID = GetCachedBundleIndexID(assetInfo.BundleName);
} }
} }
@@ -192,7 +202,7 @@ namespace YooAsset.Editor
foreach (var packageBundle in manifest.BundleList) foreach (var packageBundle in manifest.BundleList)
{ {
int mainBundleID = GetCachedBundleIndexID(packageBundle.BundleName); int mainBundleID = GetCachedBundleIndexID(packageBundle.BundleName);
var depends = GetBundleDepends(context, packageBundle.BundleName); string[] depends = GetBundleDepends(context, packageBundle.BundleName);
List<int> dependIDs = new List<int>(depends.Length); List<int> dependIDs = new List<int>(depends.Length);
foreach (var dependBundleName in depends) foreach (var dependBundleName in depends)
{ {
@@ -264,5 +274,140 @@ namespace YooAsset.Editor
} }
return value; return value;
} }
/// <summary>
/// 是否包含该资源包的索引ID
/// </summary>
private bool ContainsCachedBundleIndexID(string bundleName)
{
return _cachedBundleIndexIDs.ContainsKey(bundleName);
}
#region YOOASSET_LEGACY_DEPENDENCY
private class DependencyQuery
{
private readonly HashSet<int> _dependIDs;
public DependencyQuery(int[] dependIDs)
{
_dependIDs = new HashSet<int>(dependIDs);
}
public bool Contains(int bundleID)
{
return _dependIDs.Contains(bundleID);
}
}
private void ProcessLegacyDependency(BuildContext context, PackageManifest manifest)
{
foreach (var packageBundle in manifest.BundleList)
{
var dependIDs = packageBundle.DependIDs;
packageBundle.TempDataInEditor = new DependencyQuery(dependIDs);
}
// 记录资源对象依赖的资源包ID集合
// 注意:依赖关系非引擎构建结果里查询!
foreach (var packageAsset in manifest.AssetList)
{
var mainAssetInfo = packageAsset.TempDataInEditor as BuildAssetInfo;
packageAsset.DependBundleIDs = GetAssetDependBundleIDs(mainAssetInfo);
}
// 记录引用该资源包的资源包ID集合
foreach (var packageBundle in manifest.BundleList)
{
packageBundle.ReferenceBundleIDs = GetBundleReferenceBundleIDs(manifest, packageBundle);
}
// 注意:如果是可编程构建管线,需要补充内置资源包
// 注意:该步骤依赖前面的操作!
var buildResultContext = context.TryGetContextObject<TaskBuilding_SBP.BuildResultContext>();
if (buildResultContext != null)
{
ProcessBuiltinBundleReference(context, manifest, buildResultContext.BuiltinShadersBundleName);
ProcessBuiltinBundleReference(context, manifest, buildResultContext.MonoScriptsBundleName);
}
}
private void ProcessBuiltinBundleReference(BuildContext context, PackageManifest manifest, string builtinBundleName)
{
if (string.IsNullOrEmpty(builtinBundleName))
return;
// 查询内置资源包是否存在
if (ContainsCachedBundleIndexID(builtinBundleName) == false)
return;
// 获取内置资源包
int builtinBundleID = GetCachedBundleIndexID(builtinBundleName);
var builtinPackageBundle = manifest.BundleList[builtinBundleID];
// 更新依赖资源包ID集合
HashSet<int> cacheBundleIDs = new HashSet<int>(builtinPackageBundle.ReferenceBundleIDs);
HashSet<string> tempTags = new HashSet<string>();
foreach (var packageAsset in manifest.AssetList)
{
if (cacheBundleIDs.Contains(packageAsset.BundleID))
{
if (packageAsset.DependBundleIDs.Contains(builtinBundleID) == false)
{
var tempBundleIDs = new List<int>(packageAsset.DependBundleIDs);
tempBundleIDs.Add(builtinBundleID);
packageAsset.DependBundleIDs = tempBundleIDs.ToArray();
}
foreach (var tag in packageAsset.AssetTags)
{
if (tempTags.Contains(tag) == false)
tempTags.Add(tag);
}
}
}
// 更新内置资源包的标签集合
foreach (var tag in builtinPackageBundle.Tags)
{
if (tempTags.Contains(tag) == false)
tempTags.Add(tag);
}
builtinPackageBundle.Tags = tempTags.ToArray();
}
private int[] GetAssetDependBundleIDs(BuildAssetInfo mainAssetInfo)
{
HashSet<int> result = new HashSet<int>();
int mainBundleID = GetCachedBundleIndexID(mainAssetInfo.BundleName);
foreach (var dependAssetInfo in mainAssetInfo.AllDependAssetInfos)
{
if (dependAssetInfo.HasBundleName())
{
int bundleID = GetCachedBundleIndexID(dependAssetInfo.BundleName);
if (mainBundleID != bundleID)
{
if (result.Contains(bundleID) == false)
result.Add(bundleID);
}
}
}
return result.ToArray();
}
private int[] GetBundleReferenceBundleIDs(PackageManifest manifest, PackageBundle queryBundle)
{
int queryBundleID = GetCachedBundleIndexID(queryBundle.BundleName);
List<int> result = new List<int>();
foreach (var packageBundle in manifest.BundleList)
{
if (packageBundle == queryBundle)
continue;
var dependencyQuery = packageBundle.TempDataInEditor as DependencyQuery;
if (dependencyQuery.Contains(queryBundleID))
{
int referenceBundleID = GetCachedBundleIndexID(packageBundle.BundleName);
if (result.Contains(referenceBundleID) == false)
result.Add(referenceBundleID);
}
}
return result.ToArray();
}
#endregion
} }
} }

View File

@@ -42,6 +42,7 @@ namespace YooAsset.Editor
buildReport.Summary.AutoCollectShaders = buildMapContext.Command.AutoCollectShaders; buildReport.Summary.AutoCollectShaders = buildMapContext.Command.AutoCollectShaders;
// 构建参数 // 构建参数
buildReport.Summary.LegacyDependency = buildParameters.LegacyDependency;
buildReport.Summary.ClearBuildCacheFiles = buildParameters.ClearBuildCacheFiles; buildReport.Summary.ClearBuildCacheFiles = buildParameters.ClearBuildCacheFiles;
buildReport.Summary.UseAssetDependencyDB = buildParameters.UseAssetDependencyDB; buildReport.Summary.UseAssetDependencyDB = buildParameters.UseAssetDependencyDB;
buildReport.Summary.EnableSharePackRule = buildParameters.EnableSharePackRule; buildReport.Summary.EnableSharePackRule = buildParameters.EnableSharePackRule;

View File

@@ -13,6 +13,8 @@ namespace YooAsset.Editor
public class BuildResultContext : IContextObject public class BuildResultContext : IContextObject
{ {
public IBundleBuildResults Results; public IBundleBuildResults Results;
public string BuiltinShadersBundleName;
public string MonoScriptsBundleName;
} }
void IBuildTask.Run(BuildContext context) void IBuildTask.Run(BuildContext context)
@@ -53,6 +55,8 @@ namespace YooAsset.Editor
BuildLogger.Log("UnityEngine build success!"); BuildLogger.Log("UnityEngine build success!");
BuildResultContext buildResultContext = new BuildResultContext(); BuildResultContext buildResultContext = new BuildResultContext();
buildResultContext.Results = buildResults; buildResultContext.Results = buildResults;
buildResultContext.BuiltinShadersBundleName = builtinShadersBundleName;
buildResultContext.MonoScriptsBundleName = monoScriptsBundleName;
context.SetContextObject(buildResultContext); context.SetContextObject(buildResultContext);
} }
} }

View File

@@ -9,7 +9,7 @@ namespace YooAsset.Editor
private readonly Dictionary<System.Type, IContextObject> _contextObjects = new Dictionary<System.Type, IContextObject>(); private readonly Dictionary<System.Type, IContextObject> _contextObjects = new Dictionary<System.Type, IContextObject>();
/// <summary> /// <summary>
/// 清空所有情景对象 /// 清空所有上下文对象
/// </summary> /// </summary>
public void ClearAllContext() public void ClearAllContext()
{ {
@@ -17,7 +17,7 @@ namespace YooAsset.Editor
} }
/// <summary> /// <summary>
/// 设置情景对象 /// 设置上下文对象
/// </summary> /// </summary>
public void SetContextObject(IContextObject contextObject) public void SetContextObject(IContextObject contextObject)
{ {
@@ -32,7 +32,7 @@ namespace YooAsset.Editor
} }
/// <summary> /// <summary>
/// 获取情景对象 /// 获取上下文对象
/// </summary> /// </summary>
public T GetContextObject<T>() where T : IContextObject public T GetContextObject<T>() where T : IContextObject
{ {
@@ -46,5 +46,21 @@ namespace YooAsset.Editor
throw new Exception($"Not found context object : {type}"); throw new Exception($"Not found context object : {type}");
} }
} }
/// <summary>
/// 获取上下文对象
/// </summary>
public T TryGetContextObject<T>() where T : IContextObject
{
var type = typeof(T);
if (_contextObjects.TryGetValue(type, out IContextObject contextObject))
{
return (T)contextObject;
}
else
{
return default;
}
}
} }
} }

View File

@@ -37,6 +37,7 @@ namespace YooAsset.Editor
buildParameters.BuildTarget = BuildTarget; buildParameters.BuildTarget = BuildTarget;
buildParameters.PackageName = PackageName; buildParameters.PackageName = PackageName;
buildParameters.PackageVersion = GetPackageVersion(); buildParameters.PackageVersion = GetPackageVersion();
buildParameters.LegacyDependency = false;
buildParameters.EnableSharePackRule = true; buildParameters.EnableSharePackRule = true;
buildParameters.VerifyBuildingResult = true; buildParameters.VerifyBuildingResult = true;
buildParameters.FileNameStyle = fileNameStyle; buildParameters.FileNameStyle = fileNameStyle;

View File

@@ -38,6 +38,7 @@ namespace YooAsset.Editor
buildParameters.BuildTarget = BuildTarget; buildParameters.BuildTarget = BuildTarget;
buildParameters.PackageName = PackageName; buildParameters.PackageName = PackageName;
buildParameters.PackageVersion = GetPackageVersion(); buildParameters.PackageVersion = GetPackageVersion();
buildParameters.LegacyDependency = false;
buildParameters.EnableSharePackRule = true; buildParameters.EnableSharePackRule = true;
buildParameters.VerifyBuildingResult = true; buildParameters.VerifyBuildingResult = true;
buildParameters.FileNameStyle = fileNameStyle; buildParameters.FileNameStyle = fileNameStyle;

View File

@@ -98,9 +98,9 @@ namespace YooAsset.Editor
} }
/// <summary> /// <summary>
/// 开始收集工作 /// 获取收集的资源列表
/// </summary> /// </summary>
public CollectResult BeginCollect(CollectCommand command) public List<CollectAssetInfo> GetCollectAssets(CollectCommand command)
{ {
Dictionary<string, CollectAssetInfo> result = new Dictionary<string, CollectAssetInfo>(10000); Dictionary<string, CollectAssetInfo> result = new Dictionary<string, CollectAssetInfo>(10000);
@@ -139,9 +139,7 @@ namespace YooAsset.Editor
} }
// 返回结果 // 返回结果
var collectAssets = result.Values.ToList(); return result.Values.ToList();
var collectResult = new CollectResult(command, collectAssets);
return collectResult;
} }
/// <summary> /// <summary>

View File

@@ -116,7 +116,8 @@ namespace YooAsset.Editor
command.AutoCollectShaders = package.AutoCollectShaders; command.AutoCollectShaders = package.AutoCollectShaders;
// 开始收集工作 // 开始收集工作
CollectResult collectResult = package.BeginCollect(command); var collectAssets = package.GetCollectAssets(command);
var collectResult = new CollectResult(command, collectAssets);
return collectResult; return collectResult;
} }

View File

@@ -28,7 +28,7 @@
<ui:VisualElement name="ContentContainer" style="flex-grow: 1; flex-direction: row;"> <ui:VisualElement name="ContentContainer" style="flex-grow: 1; flex-direction: row;">
<ui:VisualElement name="PackageContainer" style="width: 200px; flex-grow: 0; background-color: rgb(67, 67, 67); border-left-width: 5px; border-right-width: 5px; border-top-width: 5px; border-bottom-width: 5px;"> <ui:VisualElement name="PackageContainer" style="width: 200px; flex-grow: 0; background-color: rgb(67, 67, 67); border-left-width: 5px; border-right-width: 5px; border-top-width: 5px; border-bottom-width: 5px;">
<ui:Label text="Packages" display-tooltip-when-elided="true" name="PackageTitle" style="background-color: rgb(89, 89, 89); -unity-text-align: upper-center; -unity-font-style: bold; border-left-width: 5px; border-right-width: 5px; border-top-width: 5px; border-bottom-width: 5px; font-size: 12px;" /> <ui:Label text="Packages" display-tooltip-when-elided="true" name="PackageTitle" style="background-color: rgb(89, 89, 89); -unity-text-align: upper-center; -unity-font-style: bold; border-left-width: 5px; border-right-width: 5px; border-top-width: 5px; border-bottom-width: 5px; font-size: 12px;" />
<ui:ListView focusable="true" name="PackageListView" item-height="20" virtualization-method="DynamicHeight" style="flex-grow: 1;" /> <ui:ListView focusable="true" name="PackageListView" item-height="20" virtualization-method="DynamicHeight" reorderable="true" reorder-mode="Animated" style="flex-grow: 1;" />
<ui:VisualElement name="PackageAddContainer" style="height: 20px; flex-direction: row; justify-content: center;"> <ui:VisualElement name="PackageAddContainer" style="height: 20px; flex-direction: row; justify-content: center;">
<ui:Button text=" - " display-tooltip-when-elided="true" name="RemoveBtn" /> <ui:Button text=" - " display-tooltip-when-elided="true" name="RemoveBtn" />
<ui:Button text=" + " display-tooltip-when-elided="true" name="AddBtn" /> <ui:Button text=" + " display-tooltip-when-elided="true" name="AddBtn" />
@@ -38,7 +38,7 @@
<ui:Label text="Groups" display-tooltip-when-elided="true" name="GroupTitle" style="background-color: rgb(89, 89, 89); -unity-text-align: upper-center; -unity-font-style: bold; border-left-width: 5px; border-right-width: 5px; border-top-width: 5px; border-bottom-width: 5px; font-size: 12px;" /> <ui:Label text="Groups" display-tooltip-when-elided="true" name="GroupTitle" style="background-color: rgb(89, 89, 89); -unity-text-align: upper-center; -unity-font-style: bold; border-left-width: 5px; border-right-width: 5px; border-top-width: 5px; border-bottom-width: 5px; font-size: 12px;" />
<ui:TextField picking-mode="Ignore" label="Package Name" name="PackageName" style="flex-direction: column;" /> <ui:TextField picking-mode="Ignore" label="Package Name" name="PackageName" style="flex-direction: column;" />
<ui:TextField picking-mode="Ignore" label="Package Desc" name="PackageDesc" style="flex-direction: column;" /> <ui:TextField picking-mode="Ignore" label="Package Desc" name="PackageDesc" style="flex-direction: column;" />
<ui:ListView focusable="true" name="GroupListView" item-height="20" virtualization-method="DynamicHeight" style="flex-grow: 1;" /> <ui:ListView focusable="true" name="GroupListView" item-height="20" virtualization-method="DynamicHeight" reorderable="true" reorder-mode="Animated" style="flex-grow: 1;" />
<ui:VisualElement name="GroupAddContainer" style="height: 20px; flex-direction: row; justify-content: center;"> <ui:VisualElement name="GroupAddContainer" style="height: 20px; flex-direction: row; justify-content: center;">
<ui:Button text=" - " display-tooltip-when-elided="true" name="RemoveBtn" /> <ui:Button text=" - " display-tooltip-when-elided="true" name="RemoveBtn" />
<ui:Button text=" + " display-tooltip-when-elided="true" name="AddBtn" /> <ui:Button text=" + " display-tooltip-when-elided="true" name="AddBtn" />

View File

@@ -2,7 +2,7 @@
<ui:VisualElement name="TopGroup" style="flex-grow: 1; border-left-width: 1px; border-right-width: 1px; border-top-width: 1px; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); border-top-color: rgb(0, 0, 0); border-bottom-color: rgb(0, 0, 0); margin-left: 0; margin-right: 0; margin-top: 2px; margin-bottom: 1px; display: flex;"> <ui:VisualElement name="TopGroup" style="flex-grow: 1; border-left-width: 1px; border-right-width: 1px; border-top-width: 1px; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); border-top-color: rgb(0, 0, 0); border-bottom-color: rgb(0, 0, 0); margin-left: 0; margin-right: 0; margin-top: 2px; margin-bottom: 1px; display: flex;">
<YooAsset.Editor.TableView name="TopTableView" /> <YooAsset.Editor.TableView name="TopTableView" />
</ui:VisualElement> </ui:VisualElement>
<ui:VisualElement name="BottomGroup" style="height: 200px; border-left-width: 1px; border-right-width: 1px; border-top-width: 1px; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); border-top-color: rgb(0, 0, 0); border-bottom-color: rgb(0, 0, 0); margin-left: 0; margin-right: 0; margin-top: 1px; margin-bottom: 1px; display: flex;"> <ui:VisualElement name="BottomGroup" style="height: 200px; border-left-width: 1px; border-right-width: 1px; border-top-width: 1px; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); border-top-color: rgb(0, 0, 0); border-bottom-color: rgb(0, 0, 0); margin-left: 0; margin-right: 0; margin-top: 1px; margin-bottom: 1px; display: flex; flex-grow: 1;">
<YooAsset.Editor.TableView name="BottomTableView" /> <YooAsset.Editor.TableView name="BottomTableView" />
</ui:VisualElement> </ui:VisualElement>
</ui:UXML> </ui:UXML>

View File

@@ -67,6 +67,7 @@ namespace YooAsset.Editor
public string IgnoreRuleName; public string IgnoreRuleName;
// 构建参数 // 构建参数
public bool LegacyDependency;
public bool ClearBuildCacheFiles; public bool ClearBuildCacheFiles;
public bool UseAssetDependencyDB; public bool UseAssetDependencyDB;
public bool EnableSharePackRule; public bool EnableSharePackRule;

View File

@@ -1,8 +1,8 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False"> <ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False">
<ui:VisualElement name="TopGroup" style="flex-grow: 1; border-left-width: 1px; border-right-width: 1px; border-top-width: 1px; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); border-top-color: rgb(0, 0, 0); border-bottom-color: rgb(0, 0, 0); margin-left: 0; margin-right: 0; margin-top: 2px; margin-bottom: 1px; display: flex;"> <ui:VisualElement name="TopGroup" style="flex-grow: 1; border-left-width: 1px; border-right-width: 1px; border-top-width: 1px; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); border-top-color: rgb(0, 0, 0); border-bottom-color: rgb(0, 0, 0); margin-left: 0; margin-right: 0; margin-top: 2px; margin-bottom: 1px; display: flex;">
<YooAsset.Editor.TableView name="TopTableView" /> <YooAsset.Editor.TableView name="TopTableView" style="flex-grow: 1;" />
</ui:VisualElement> </ui:VisualElement>
<ui:VisualElement name="BottomGroup" style="height: 200px; border-left-width: 1px; border-right-width: 1px; border-top-width: 1px; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); border-top-color: rgb(0, 0, 0); border-bottom-color: rgb(0, 0, 0); margin-left: 0; margin-right: 0; margin-top: 1px; margin-bottom: 1px; display: flex;"> <ui:VisualElement name="BottomGroup" style="height: 200px; border-left-width: 1px; border-right-width: 1px; border-top-width: 1px; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); border-top-color: rgb(0, 0, 0); border-bottom-color: rgb(0, 0, 0); margin-left: 0; margin-right: 0; margin-top: 1px; margin-bottom: 1px; display: flex; flex-grow: 1;">
<YooAsset.Editor.TableView name="BottomTableView" /> <YooAsset.Editor.TableView name="BottomTableView" style="flex-grow: 1;" />
</ui:VisualElement> </ui:VisualElement>
</ui:UXML> </ui:UXML>

View File

@@ -1,8 +1,8 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False"> <ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False">
<ui:VisualElement name="TopGroup" style="flex-grow: 1; border-left-width: 1px; border-right-width: 1px; border-top-width: 1px; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); border-top-color: rgb(0, 0, 0); border-bottom-color: rgb(0, 0, 0); margin-left: 0; margin-right: 0; margin-top: 2px; margin-bottom: 1px; display: flex;"> <ui:VisualElement name="TopGroup" style="flex-grow: 1; border-left-width: 1px; border-right-width: 1px; border-top-width: 1px; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); border-top-color: rgb(0, 0, 0); border-bottom-color: rgb(0, 0, 0); margin-left: 0; margin-right: 0; margin-top: 2px; margin-bottom: 1px; display: flex;">
<YooAsset.Editor.TableView name="TopTableView" /> <YooAsset.Editor.TableView name="TopTableView" style="flex-grow: 1;" />
</ui:VisualElement> </ui:VisualElement>
<ui:VisualElement name="BottomGroup" style="height: 200px; border-left-width: 1px; border-right-width: 1px; border-top-width: 1px; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); border-top-color: rgb(0, 0, 0); border-bottom-color: rgb(0, 0, 0); margin-left: 0; margin-right: 0; margin-top: 1px; margin-bottom: 1px; display: flex;"> <ui:VisualElement name="BottomGroup" style="height: 200px; border-left-width: 1px; border-right-width: 1px; border-top-width: 1px; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); border-top-color: rgb(0, 0, 0); border-bottom-color: rgb(0, 0, 0); margin-left: 0; margin-right: 0; margin-top: 1px; margin-bottom: 1px; display: flex; flex-grow: 1;">
<YooAsset.Editor.TableView name="BottomTableView" /> <YooAsset.Editor.TableView name="BottomTableView" style="flex-grow: 1;" />
</ui:VisualElement> </ui:VisualElement>
</ui:UXML> </ui:UXML>

View File

@@ -75,9 +75,10 @@ namespace YooAsset.Editor
_items.Add(new ItemWrapper("Include Asset GUID", $"{buildReport.Summary.IncludeAssetGUID}")); _items.Add(new ItemWrapper("Include Asset GUID", $"{buildReport.Summary.IncludeAssetGUID}"));
_items.Add(new ItemWrapper("Auto Collect Shaders", $"{buildReport.Summary.AutoCollectShaders}")); _items.Add(new ItemWrapper("Auto Collect Shaders", $"{buildReport.Summary.AutoCollectShaders}"));
_items.Add(new ItemWrapper("Ignore Rule Name", $"{buildReport.Summary.IgnoreRuleName}")); _items.Add(new ItemWrapper("Ignore Rule Name", $"{buildReport.Summary.IgnoreRuleName}"));
_items.Add(new ItemWrapper(string.Empty, string.Empty)); _items.Add(new ItemWrapper(string.Empty, string.Empty));
_items.Add(new ItemWrapper("Build Params", string.Empty)); _items.Add(new ItemWrapper("Build Params", string.Empty));
_items.Add(new ItemWrapper("Legacy Dependency Mode", $"{buildReport.Summary.LegacyDependency}"));
_items.Add(new ItemWrapper("Clear Build Cache Files", $"{buildReport.Summary.ClearBuildCacheFiles}")); _items.Add(new ItemWrapper("Clear Build Cache Files", $"{buildReport.Summary.ClearBuildCacheFiles}"));
_items.Add(new ItemWrapper("Use Asset Dependency DB", $"{buildReport.Summary.UseAssetDependencyDB}")); _items.Add(new ItemWrapper("Use Asset Dependency DB", $"{buildReport.Summary.UseAssetDependencyDB}"));
_items.Add(new ItemWrapper("Enable Share Pack Rule", $"{buildReport.Summary.EnableSharePackRule}")); _items.Add(new ItemWrapper("Enable Share Pack Rule", $"{buildReport.Summary.EnableSharePackRule}"));

View File

@@ -12,15 +12,9 @@ namespace YooAsset.Editor
/// </summary> /// </summary>
public class PanelSplitView : TwoPaneSplitView public class PanelSplitView : TwoPaneSplitView
{ {
#if UNITY_6000_0_OR_NEWER
public new class UxmlFactory : UxmlElementAttribute
{
}
#else
public new class UxmlFactory : UxmlFactory<PanelSplitView, UxmlTraits> public new class UxmlFactory : UxmlFactory<PanelSplitView, UxmlTraits>
{ {
} }
#endif
/// <summary> /// <summary>
/// 竖版分屏 /// 竖版分屏

View File

@@ -0,0 +1,627 @@
#if UNITY_2021_3_OR_NEWER
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
namespace YooAsset.Editor
{
public class ReorderableListView : VisualElement
{
public new class UxmlFactory : UxmlFactory<ReorderableListView, UxmlTraits>
{
}
/// <summary>
/// 制作元素委托
/// </summary>
/// <returns></returns>
public delegate VisualElement MakeElementDelegate();
/// <summary>
/// 绑定元素委托
/// </summary>
public delegate void BindElementDelegqate(VisualElement element, int index);
private Foldout _foldout;
private ListView _listView;
private Label _headerLabel;
private Button _addButton;
private Button _removeButton;
private string _headerName = nameof(ReorderableListView);
/// <summary>
/// 源数据
/// </summary>
public IList SourceData
{
set
{
if (value is ArrayList)
throw new Exception($"{nameof(SourceData)} not support {nameof(ArrayList)}");
_listView.Clear();
_listView.ClearSelection();
_listView.itemsSource = value;
_listView.Rebuild();
RefreshFoldoutName();
RefreshRemoveButton();
}
get
{
return _listView.itemsSource;
}
}
/// <summary>
/// 元素固定高度
/// </summary>
public float ElementHeight
{
set
{
_listView.fixedItemHeight = value;
_listView.Rebuild();
}
get
{
return _listView.fixedItemHeight;
}
}
/// <summary>
/// 增加按钮显隐
/// </summary>
public bool DisplayAdd
{
set
{
UIElementsTools.SetElementVisible(_addButton, value);
}
get
{
return _addButton.style.visibility == Visibility.Visible;
}
}
/// <summary>
/// 移除按钮显隐
/// </summary>
public bool DisplayRemove
{
set
{
UIElementsTools.SetElementVisible(_removeButton, value);
}
get
{
return _removeButton.style.visibility == Visibility.Visible;
}
}
/// <summary>
/// 标题名称
/// </summary>
public string HeaderName
{
set
{
_headerName = value;
RefreshFoldoutName();
}
get
{
return _headerName;
}
}
/// <summary>
/// 制作元素的回调
/// </summary>
public MakeElementDelegate MakeElementCallback;
/// <summary>
/// 绑定元素的回调
/// </summary>
public BindElementDelegqate BindElementCallback;
public ReorderableListView()
{
CreateView(true);
}
public ReorderableListView(bool foldout)
{
CreateView(foldout);
}
private void CreateView(bool foldout)
{
this.style.flexGrow = 1;
this.style.flexShrink = 1;
// 折叠栏
if (foldout)
{
_foldout = new Foldout();
_foldout.style.flexGrow = 1f;
_foldout.style.flexShrink = 1f;
_foldout.text = $"{nameof(ReorderableListView)}";
}
else
{
_headerLabel = new Label();
}
// 列表视图
_listView = new ListView();
_listView.style.flexGrow = 1;
_listView.style.flexShrink = 1;
_listView.reorderable = true;
_listView.reorderMode = ListViewReorderMode.Animated;
_listView.makeItem = MakeListViewElement;
_listView.bindItem = BindListViewElement;
#if UNITY_2022_3_OR_NEWER
_listView.selectionChanged += OnSelectionChanged;
#elif UNITY_2020_1_OR_NEWER
_listView.onSelectionChange += OnSelectionChanged;
#else
_listView.onSelectionChanged += OnSelectionChanged;
#endif
// 按钮组
var buttonContainer = new VisualElement();
buttonContainer.style.flexDirection = FlexDirection.RowReverse;
// 移除按钮
_removeButton = new Button();
_removeButton.text = " - ";
_removeButton.clicked += OnClickRemoveButton;
_removeButton.SetEnabled(false);
buttonContainer.Add(_removeButton);
// 增加按钮
_addButton = new Button();
_addButton.text = " + ";
_addButton.clicked += OnClickAddButton;
buttonContainer.Add(_addButton);
// 组织页面
if (foldout)
{
_foldout.Add(_listView);
_foldout.Add(buttonContainer);
this.Add(_foldout);
}
else
{
this.Add(_headerLabel);
this.Add(_listView);
this.Add(buttonContainer);
}
}
private void OnClickAddButton()
{
if (_listView.itemsSource != null)
{
object defaultValue = GetElementDefaultValue();
_listView.itemsSource.Add(defaultValue);
_listView.Rebuild();
RefreshFoldoutName();
RefreshRemoveButton();
}
else
{
Debug.LogWarning("The source data is null !");
}
}
private void OnClickRemoveButton()
{
if (_listView.itemsSource != null)
{
if (_listView.selectedIndex >= 0)
{
_listView.itemsSource.RemoveAt(_listView.selectedIndex);
_listView.Rebuild();
RefreshFoldoutName();
RefreshRemoveButton();
}
}
else
{
Debug.LogWarning("The source data is null !");
}
}
private void OnSelectionChanged(IEnumerable<object> objs)
{
RefreshRemoveButton();
}
/// <summary>
/// 生成元素
/// </summary>
private VisualElement MakeListViewElement()
{
if (MakeElementCallback != null)
{
return MakeElementCallback.Invoke();
}
Type elementType = GetElementType();
if (elementType == typeof(string))
{
TextField textField = new TextField();
textField.RegisterValueChangedCallback(evt =>
{
int itemIndex = (int)textField.userData;
_listView.itemsSource[itemIndex] = textField.value;
});
return textField;
}
else if (elementType == typeof(int))
{
IntegerField intField = new IntegerField();
intField.RegisterValueChangedCallback(evt =>
{
int itemIndex = (int)intField.userData;
_listView.itemsSource[itemIndex] = intField.value;
});
return intField;
}
else if (elementType == typeof(long))
{
LongField longField = new LongField();
longField.RegisterValueChangedCallback(evt =>
{
int itemIndex = (int)longField.userData;
_listView.itemsSource[itemIndex] = longField.value;
});
return longField;
}
else if (elementType == typeof(float))
{
FloatField floatField = new FloatField();
floatField.RegisterValueChangedCallback(evt =>
{
int itemIndex = (int)floatField.userData;
_listView.itemsSource[itemIndex] = floatField.value;
});
return floatField;
}
else if (elementType == typeof(double))
{
DoubleField doubleField = new DoubleField();
doubleField.RegisterValueChangedCallback(evt =>
{
int itemIndex = (int)doubleField.userData;
_listView.itemsSource[itemIndex] = doubleField.value;
});
return doubleField;
}
else if (elementType == typeof(bool))
{
Toggle toggle = new Toggle();
toggle.RegisterValueChangedCallback(evt =>
{
int itemIndex = (int)toggle.userData;
_listView.itemsSource[itemIndex] = toggle.value;
});
return toggle;
}
else if (elementType == typeof(Hash128))
{
Hash128Field hash128Field = new Hash128Field();
hash128Field.RegisterValueChangedCallback(evt =>
{
int itemIndex = (int)hash128Field.userData;
_listView.itemsSource[itemIndex] = hash128Field.value;
});
return hash128Field;
}
else if (elementType == typeof(Vector2))
{
Vector2Field vector2Field = new Vector2Field();
vector2Field.RegisterValueChangedCallback(evt =>
{
int itemIndex = (int)vector2Field.userData;
_listView.itemsSource[itemIndex] = vector2Field.value;
});
return vector2Field;
}
else if (elementType == typeof(Vector3))
{
Vector3Field vector3Field = new Vector3Field();
vector3Field.RegisterValueChangedCallback(evt =>
{
int itemIndex = (int)vector3Field.userData;
_listView.itemsSource[itemIndex] = vector3Field.value;
});
return vector3Field;
}
else if (elementType == typeof(Vector4))
{
Vector4Field vector4Field = new Vector4Field();
vector4Field.RegisterValueChangedCallback(evt =>
{
int itemIndex = (int)vector4Field.userData;
_listView.itemsSource[itemIndex] = vector4Field.value;
});
return vector4Field;
}
else if (elementType == typeof(Rect))
{
RectField rectField = new RectField();
rectField.RegisterValueChangedCallback(evt =>
{
int itemIndex = (int)rectField.userData;
_listView.itemsSource[itemIndex] = rectField.value;
});
return rectField;
}
else if (elementType == typeof(Bounds))
{
BoundsField boundsField = new BoundsField();
boundsField.RegisterValueChangedCallback(evt =>
{
int itemIndex = (int)boundsField.userData;
_listView.itemsSource[itemIndex] = boundsField.value;
});
return boundsField;
}
else if (elementType == typeof(Color))
{
ColorField colorField = new ColorField();
colorField.RegisterValueChangedCallback(evt =>
{
int itemIndex = (int)colorField.userData;
_listView.itemsSource[itemIndex] = colorField.value;
});
return colorField;
}
else if (elementType == typeof(Gradient))
{
GradientField gradientField = new GradientField();
gradientField.RegisterValueChangedCallback(evt =>
{
int itemIndex = (int)gradientField.userData;
_listView.itemsSource[itemIndex] = gradientField.value;
});
return gradientField;
}
else if (elementType == typeof(AnimationCurve))
{
CurveField curveField = new CurveField();
curveField.RegisterValueChangedCallback(evt =>
{
int itemIndex = (int)curveField.userData;
_listView.itemsSource[itemIndex] = curveField.value;
});
return curveField;
}
else if (elementType == typeof(UnityEngine.Object))
{
ObjectField objectField = new ObjectField();
objectField.objectType = typeof(UnityEngine.Object);
objectField.RegisterValueChangedCallback(evt =>
{
int itemIndex = (int)objectField.userData;
_listView.itemsSource[itemIndex] = objectField.value;
});
return objectField;
}
else if (elementType.IsEnum)
{
EnumField enumField = new EnumField();
enumField.RegisterValueChangedCallback(evt =>
{
int itemIndex = (int)enumField.userData;
_listView.itemsSource[itemIndex] = enumField.value;
});
return enumField;
}
else
{
Label label = new Label();
label.text = $"Not support element type : {elementType.Name}";
return label;
}
}
/// <summary>
/// 绑定元素
/// </summary>
private void BindListViewElement(VisualElement listViewElement, int index)
{
if (BindElementCallback != null)
{
BindElementCallback.Invoke(listViewElement, index);
return;
}
var elementValue = _listView.itemsSource[index];
string elementName = GetElementName(index);
Type elementType = GetElementType();
if (elementType == typeof(string))
{
TextField textField = listViewElement as TextField;
textField.userData = index;
textField.label = elementName;
textField.SetValueWithoutNotify(elementValue as string);
}
else if (elementType == typeof(int))
{
IntegerField intField = listViewElement as IntegerField;
intField.userData = index;
intField.label = elementName;
intField.SetValueWithoutNotify((int)elementValue);
}
else if (elementType == typeof(long))
{
LongField longField = listViewElement as LongField;
longField.userData = index;
longField.label = elementName;
longField.SetValueWithoutNotify((long)elementValue);
}
else if (elementType == typeof(float))
{
FloatField floatField = listViewElement as FloatField;
floatField.userData = index;
floatField.label = elementName;
floatField.SetValueWithoutNotify((float)elementValue);
}
else if (elementType == typeof(double))
{
DoubleField doubleField = listViewElement as DoubleField;
doubleField.userData = index;
doubleField.label = elementName;
doubleField.SetValueWithoutNotify((double)elementValue);
}
else if (elementType == typeof(bool))
{
Toggle toggle = listViewElement as Toggle;
toggle.userData = index;
toggle.label = elementName;
toggle.SetValueWithoutNotify((bool)elementValue);
}
else if (elementType == typeof(Hash128))
{
Hash128Field hash128Field = listViewElement as Hash128Field;
hash128Field.userData = index;
hash128Field.label = elementName;
hash128Field.SetValueWithoutNotify((Hash128)elementValue);
}
else if (elementType == typeof(Vector2))
{
Vector2Field vector2Field = listViewElement as Vector2Field;
vector2Field.userData = index;
vector2Field.label = elementName;
vector2Field.SetValueWithoutNotify((Vector2)elementValue);
}
else if (elementType == typeof(Vector3))
{
Vector3Field vector3Field = listViewElement as Vector3Field;
vector3Field.userData = index;
vector3Field.label = elementName;
vector3Field.SetValueWithoutNotify((Vector3)elementValue);
}
else if (elementType == typeof(Vector4))
{
Vector4Field vector4Field = listViewElement as Vector4Field;
vector4Field.userData = index;
vector4Field.label = elementName;
vector4Field.SetValueWithoutNotify((Vector4)elementValue);
}
else if (elementType == typeof(Rect))
{
RectField rectField = listViewElement as RectField;
rectField.userData = index;
rectField.label = elementName;
rectField.SetValueWithoutNotify((Rect)elementValue);
}
else if (elementType == typeof(Bounds))
{
BoundsField boundsField = listViewElement as BoundsField;
boundsField.userData = index;
boundsField.label = elementName;
boundsField.SetValueWithoutNotify((Bounds)elementValue);
}
else if (elementType == typeof(Color))
{
ColorField colorField = listViewElement as ColorField;
colorField.userData = index;
colorField.label = elementName;
colorField.SetValueWithoutNotify((Color)elementValue);
}
else if (elementType == typeof(Gradient))
{
GradientField gradientField = listViewElement as GradientField;
gradientField.userData = index;
gradientField.label = elementName;
gradientField.SetValueWithoutNotify((Gradient)elementValue);
}
else if (elementType == typeof(AnimationCurve))
{
CurveField curveField = listViewElement as CurveField;
curveField.userData = index;
curveField.label = elementName;
curveField.SetValueWithoutNotify((AnimationCurve)elementValue);
}
else if (elementType == typeof(UnityEngine.Object))
{
ObjectField objectField = listViewElement as ObjectField;
objectField.userData = index;
objectField.label = elementName;
objectField.SetValueWithoutNotify(elementValue as UnityEngine.Object);
}
else if (elementType.IsEnum)
{
EnumField enumField = listViewElement as EnumField;
enumField.userData = index;
enumField.label = elementName;
enumField.Init((Enum)elementValue);
enumField.SetValueWithoutNotify((Enum)elementValue);
}
else
{
}
}
private Type GetElementType()
{
Type elementType = _listView.itemsSource.GetType().GetGenericArguments()[0];
return elementType;
}
private object GetElementDefaultValue()
{
Type type = GetElementType();
if (type.IsValueType)
{
return Activator.CreateInstance(type);
}
return null;
}
private string GetElementName(int index)
{
return $"Element {index}";
}
private void RefreshRemoveButton()
{
if (_listView.itemsSource == null)
{
_removeButton.SetEnabled(false);
return;
}
// 注意:数据列表移除元素的时候有可能会越界!
if (_listView.selectedIndex >= _listView.itemsSource.Count)
_listView.ClearSelection();
if (_listView.selectedIndex >= 0)
_removeButton.SetEnabled(true);
else
_removeButton.SetEnabled(false);
}
private void RefreshFoldoutName()
{
if (_listView.itemsSource == null)
{
if (_foldout != null)
_foldout.text = _headerName;
if (_headerLabel != null)
_headerLabel.text = _headerName;
}
else
{
if (_foldout != null)
_foldout.text = _headerName + $" ({_listView.itemsSource.Count}) ";
if (_headerLabel != null)
_headerLabel.text = _headerName + $" ({_listView.itemsSource.Count}) ";
}
}
}
}
#endif

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 640ec7bd883b8314db53b508278aea6e guid: 111ec0d18888d7e4396b2192f7b4f347
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2

View File

@@ -9,15 +9,9 @@ namespace YooAsset.Editor
{ {
public class ResizeHandle : VisualElement public class ResizeHandle : VisualElement
{ {
#if UNITY_6000_0_OR_NEWER
public new class UxmlFactory : UxmlElementAttribute
{
}
#else
public new class UxmlFactory : UxmlFactory<ResizeHandle, UxmlTraits> public new class UxmlFactory : UxmlFactory<ResizeHandle, UxmlTraits>
{ {
} }
#endif
private bool _isResizing = false; private bool _isResizing = false;
private float _initialWidth; private float _initialWidth;

View File

@@ -15,15 +15,9 @@ namespace YooAsset.Editor
/// </summary> /// </summary>
public class TableView : VisualElement public class TableView : VisualElement
{ {
#if UNITY_6000_0_OR_NEWER
public new class UxmlFactory : UxmlElementAttribute
{
}
#else
public new class UxmlFactory : UxmlFactory<TableView, UxmlTraits> public new class UxmlFactory : UxmlFactory<TableView, UxmlTraits>
{ {
} }
#endif
private readonly Toolbar _toolbar; private readonly Toolbar _toolbar;
private readonly ListView _listView; private readonly ListView _listView;
@@ -90,10 +84,16 @@ namespace YooAsset.Editor
public TableView() public TableView()
{ {
_toolbar = new Toolbar(); this.style.flexShrink = 1f;
this.Add(_toolbar); this.style.flexGrow = 1f;
// 定义标题栏
_toolbar = new Toolbar();
// 定义列表视图
_listView = new ListView(); _listView = new ListView();
_listView.style.flexShrink = 1f;
_listView.style.flexGrow = 1f;
_listView.makeItem = MakeListViewElement; _listView.makeItem = MakeListViewElement;
_listView.bindItem = BindListViewElement; _listView.bindItem = BindListViewElement;
_listView.selectionType = SelectionType.Multiple; _listView.selectionType = SelectionType.Multiple;
@@ -107,6 +107,7 @@ namespace YooAsset.Editor
_listView.onSelectionChanged += OnSelectionChanged; _listView.onSelectionChanged += OnSelectionChanged;
#endif #endif
this.Add(_toolbar);
this.Add(_listView); this.Add(_listView);
} }

View File

@@ -21,7 +21,7 @@ namespace YooAsset
} }
protected readonly Dictionary<string, FileWrapper> _wrappers = new Dictionary<string, FileWrapper>(10000); protected readonly Dictionary<string, FileWrapper> _wrappers = new Dictionary<string, FileWrapper>(10000);
protected readonly Dictionary<string, string> _buildinFilePaths = new Dictionary<string, string>(10000); protected readonly Dictionary<string, string> _buildinFilePathMapping = new Dictionary<string, string>(10000);
protected IFileSystem _unpackFileSystem; protected IFileSystem _unpackFileSystem;
protected string _packageRoot; protected string _packageRoot;
@@ -113,12 +113,13 @@ namespace YooAsset
} }
public virtual FSDownloadFileOperation DownloadFileAsync(PackageBundle bundle, DownloadParam param) public virtual FSDownloadFileOperation DownloadFileAsync(PackageBundle bundle, DownloadParam param)
{ {
// 注意:业务层的解压下载器会依赖内置文件系统的下载方法
param.ImportFilePath = GetBuildinFileLoadPath(bundle); param.ImportFilePath = GetBuildinFileLoadPath(bundle);
return _unpackFileSystem.DownloadFileAsync(bundle, param); return _unpackFileSystem.DownloadFileAsync(bundle, param);
} }
public virtual FSLoadBundleOperation LoadBundleFile(PackageBundle bundle) public virtual FSLoadBundleOperation LoadBundleFile(PackageBundle bundle)
{ {
if (NeedUnpack(bundle)) if (IsUnpackBundleFile(bundle))
{ {
return _unpackFileSystem.LoadBundleFile(bundle); return _unpackFileSystem.LoadBundleFile(bundle);
} }
@@ -216,11 +217,7 @@ namespace YooAsset
} }
public virtual bool NeedUnpack(PackageBundle bundle) public virtual bool NeedUnpack(PackageBundle bundle)
{ {
if (Belong(bundle) == false) if (IsUnpackBundleFile(bundle))
return false;
#if UNITY_ANDROID
if (bundle.BundleType == (int)EBuildBundleType.RawBundle || bundle.Encrypted)
{ {
return _unpackFileSystem.Exists(bundle) == false; return _unpackFileSystem.Exists(bundle) == false;
} }
@@ -228,9 +225,6 @@ namespace YooAsset
{ {
return false; return false;
} }
#else
return false;
#endif
} }
public virtual bool NeedImport(PackageBundle bundle) public virtual bool NeedImport(PackageBundle bundle)
{ {
@@ -239,14 +233,14 @@ namespace YooAsset
public virtual string GetBundleFilePath(PackageBundle bundle) public virtual string GetBundleFilePath(PackageBundle bundle)
{ {
if (NeedUnpack(bundle)) if (IsUnpackBundleFile(bundle))
return _unpackFileSystem.GetBundleFilePath(bundle); return _unpackFileSystem.GetBundleFilePath(bundle);
return GetBuildinFileLoadPath(bundle); return GetBuildinFileLoadPath(bundle);
} }
public virtual byte[] ReadBundleFileData(PackageBundle bundle) public virtual byte[] ReadBundleFileData(PackageBundle bundle)
{ {
if (NeedUnpack(bundle)) if (IsUnpackBundleFile(bundle))
return _unpackFileSystem.ReadBundleFileData(bundle); return _unpackFileSystem.ReadBundleFileData(bundle);
if (Exists(bundle) == false) if (Exists(bundle) == false)
@@ -277,7 +271,7 @@ namespace YooAsset
} }
public virtual string ReadBundleFileText(PackageBundle bundle) public virtual string ReadBundleFileText(PackageBundle bundle)
{ {
if (NeedUnpack(bundle)) if (IsUnpackBundleFile(bundle))
return _unpackFileSystem.ReadBundleFileText(bundle); return _unpackFileSystem.ReadBundleFileText(bundle);
if (Exists(bundle) == false) if (Exists(bundle) == false)
@@ -315,10 +309,10 @@ namespace YooAsset
} }
public string GetBuildinFileLoadPath(PackageBundle bundle) public string GetBuildinFileLoadPath(PackageBundle bundle)
{ {
if (_buildinFilePaths.TryGetValue(bundle.BundleGUID, out string filePath) == false) if (_buildinFilePathMapping.TryGetValue(bundle.BundleGUID, out string filePath) == false)
{ {
filePath = PathUtility.Combine(_packageRoot, bundle.FileName); filePath = PathUtility.Combine(_packageRoot, bundle.FileName);
_buildinFilePaths.Add(bundle.BundleGUID, filePath); _buildinFilePathMapping.Add(bundle.BundleGUID, filePath);
} }
return filePath; return filePath;
} }
@@ -343,6 +337,24 @@ namespace YooAsset
return YooAssetSettingsData.GetYooResourcesLoadPath(PackageName, fileName); return YooAssetSettingsData.GetYooResourcesLoadPath(PackageName, fileName);
} }
/// <summary>
/// 是否属于解压资源包文件
/// </summary>
protected bool IsUnpackBundleFile(PackageBundle bundle)
{
if (Belong(bundle) == false)
return false;
#if UNITY_ANDROID
if (bundle.BundleType == (int)EBuildBundleType.RawBundle || bundle.Encrypted)
return true;
else
return false;
#else
return false;
#endif
}
/// <summary> /// <summary>
/// 记录文件信息 /// 记录文件信息
/// </summary> /// </summary>

View File

@@ -11,10 +11,10 @@ namespace YooAsset
/// </summary> /// </summary>
internal class DefaultCacheFileSystem : IFileSystem internal class DefaultCacheFileSystem : IFileSystem
{ {
protected readonly Dictionary<string, RecordFileElement> _wrappers = new Dictionary<string, RecordFileElement>(10000); protected readonly Dictionary<string, RecordFileElement> _records = new Dictionary<string, RecordFileElement>(10000);
protected readonly Dictionary<string, string> _bundleDataFilePaths = new Dictionary<string, string>(10000); protected readonly Dictionary<string, string> _bundleDataFilePathMapping = new Dictionary<string, string>(10000);
protected readonly Dictionary<string, string> _bundleInfoFilePaths = new Dictionary<string, string>(10000); protected readonly Dictionary<string, string> _bundleInfoFilePathMapping = new Dictionary<string, string>(10000);
protected readonly Dictionary<string, string> _tempFilePaths = new Dictionary<string, string>(10000); protected readonly Dictionary<string, string> _tempFilePathMapping = new Dictionary<string, string>(10000);
protected DefaultCacheDownloadCenter _downloadCenter; protected DefaultCacheDownloadCenter _downloadCenter;
protected string _packageRoot; protected string _packageRoot;
@@ -45,7 +45,7 @@ namespace YooAsset
{ {
get get
{ {
return _wrappers.Count; return _records.Count;
} }
} }
@@ -245,7 +245,7 @@ namespace YooAsset
} }
public virtual bool Exists(PackageBundle bundle) public virtual bool Exists(PackageBundle bundle)
{ {
return _wrappers.ContainsKey(bundle.BundleGUID); return _records.ContainsKey(bundle.BundleGUID);
} }
public virtual bool NeedDownload(PackageBundle bundle) public virtual bool NeedDownload(PackageBundle bundle)
{ {
@@ -330,60 +330,60 @@ namespace YooAsset
#region #region
public List<string> GetAllCachedBundleGUIDs() public List<string> GetAllCachedBundleGUIDs()
{ {
return _wrappers.Keys.ToList(); return _records.Keys.ToList();
} }
public string GetTempFilePath(PackageBundle bundle) public string GetTempFilePath(PackageBundle bundle)
{ {
if (_tempFilePaths.TryGetValue(bundle.BundleGUID, out string filePath) == false) if (_tempFilePathMapping.TryGetValue(bundle.BundleGUID, out string filePath) == false)
{ {
filePath = PathUtility.Combine(_tempFilesRoot, bundle.BundleGUID); filePath = PathUtility.Combine(_tempFilesRoot, bundle.BundleGUID);
_tempFilePaths.Add(bundle.BundleGUID, filePath); _tempFilePathMapping.Add(bundle.BundleGUID, filePath);
} }
return filePath; return filePath;
} }
public string GetBundleDataFilePath(PackageBundle bundle) public string GetBundleDataFilePath(PackageBundle bundle)
{ {
if (_bundleDataFilePaths.TryGetValue(bundle.BundleGUID, out string filePath) == false) if (_bundleDataFilePathMapping.TryGetValue(bundle.BundleGUID, out string filePath) == false)
{ {
string folderName = bundle.FileHash.Substring(0, 2); string folderName = bundle.FileHash.Substring(0, 2);
filePath = PathUtility.Combine(_cacheBundleFilesRoot, folderName, bundle.BundleGUID, DefaultCacheFileSystemDefine.BundleDataFileName); filePath = PathUtility.Combine(_cacheBundleFilesRoot, folderName, bundle.BundleGUID, DefaultCacheFileSystemDefine.BundleDataFileName);
if (AppendFileExtension) if (AppendFileExtension)
filePath += bundle.FileExtension; filePath += bundle.FileExtension;
_bundleDataFilePaths.Add(bundle.BundleGUID, filePath); _bundleDataFilePathMapping.Add(bundle.BundleGUID, filePath);
} }
return filePath; return filePath;
} }
public string GetBundleInfoFilePath(PackageBundle bundle) public string GetBundleInfoFilePath(PackageBundle bundle)
{ {
if (_bundleInfoFilePaths.TryGetValue(bundle.BundleGUID, out string filePath) == false) if (_bundleInfoFilePathMapping.TryGetValue(bundle.BundleGUID, out string filePath) == false)
{ {
string folderName = bundle.FileHash.Substring(0, 2); string folderName = bundle.FileHash.Substring(0, 2);
filePath = PathUtility.Combine(_cacheBundleFilesRoot, folderName, bundle.BundleGUID, DefaultCacheFileSystemDefine.BundleInfoFileName); filePath = PathUtility.Combine(_cacheBundleFilesRoot, folderName, bundle.BundleGUID, DefaultCacheFileSystemDefine.BundleInfoFileName);
_bundleInfoFilePaths.Add(bundle.BundleGUID, filePath); _bundleInfoFilePathMapping.Add(bundle.BundleGUID, filePath);
} }
return filePath; return filePath;
} }
public bool IsRecordBundleFile(string bundleGUID) public bool IsRecordBundleFile(string bundleGUID)
{ {
return _wrappers.ContainsKey(bundleGUID); return _records.ContainsKey(bundleGUID);
} }
public bool RecordBundleFile(string bundleGUID, RecordFileElement element) public bool RecordBundleFile(string bundleGUID, RecordFileElement element)
{ {
if (_wrappers.ContainsKey(bundleGUID)) if (_records.ContainsKey(bundleGUID))
{ {
YooLogger.Error($"{nameof(DefaultCacheFileSystem)} has element : {bundleGUID}"); YooLogger.Error($"{nameof(DefaultCacheFileSystem)} has element : {bundleGUID}");
return false; return false;
} }
_wrappers.Add(bundleGUID, element); _records.Add(bundleGUID, element);
return true; return true;
} }
public EFileVerifyResult VerifyCacheFile(PackageBundle bundle) public EFileVerifyResult VerifyCacheFile(PackageBundle bundle)
{ {
if (_wrappers.TryGetValue(bundle.BundleGUID, out RecordFileElement wrapper) == false) if (_records.TryGetValue(bundle.BundleGUID, out RecordFileElement wrapper) == false)
return EFileVerifyResult.CacheNotFound; return EFileVerifyResult.CacheNotFound;
EFileVerifyResult result = FileVerifyHelper.FileVerify(wrapper.DataFilePath, wrapper.DataFileSize, wrapper.DataFileCRC, EFileVerifyLevel.High); EFileVerifyResult result = FileVerifyHelper.FileVerify(wrapper.DataFilePath, wrapper.DataFileSize, wrapper.DataFileCRC, EFileVerifyLevel.High);
@@ -391,7 +391,7 @@ namespace YooAsset
} }
public bool WriteCacheBundleFile(PackageBundle bundle, string copyPath) public bool WriteCacheBundleFile(PackageBundle bundle, string copyPath)
{ {
if (_wrappers.ContainsKey(bundle.BundleGUID)) if (_records.ContainsKey(bundle.BundleGUID))
{ {
throw new Exception("Should never get here !"); throw new Exception("Should never get here !");
} }
@@ -426,7 +426,7 @@ namespace YooAsset
} }
public bool DeleteCacheBundleFile(string bundleGUID) public bool DeleteCacheBundleFile(string bundleGUID)
{ {
if (_wrappers.TryGetValue(bundleGUID, out RecordFileElement wrapper)) if (_records.TryGetValue(bundleGUID, out RecordFileElement wrapper))
{ {
try try
{ {
@@ -434,7 +434,7 @@ namespace YooAsset
FileInfo fileInfo = new FileInfo(dataFilePath); FileInfo fileInfo = new FileInfo(dataFilePath);
if (fileInfo.Exists) if (fileInfo.Exists)
fileInfo.Directory.Delete(true); fileInfo.Directory.Delete(true);
_wrappers.Remove(bundleGUID); _records.Remove(bundleGUID);
return true; return true;
} }
catch (Exception e) catch (Exception e)

View File

@@ -47,6 +47,11 @@ namespace YooAsset
/// 自定义参数:跨域下载服务接口 /// 自定义参数:跨域下载服务接口
/// </summary> /// </summary>
public IRemoteServices RemoteServices { private set; get; } = null; public IRemoteServices RemoteServices { private set; get; } = null;
/// <summary>
/// 自定义参数:解密方法类
/// </summary>
public IWebDecryptionServices DecryptionServices { private set; get; }
#endregion #endregion
@@ -108,6 +113,10 @@ namespace YooAsset
{ {
RemoteServices = (IRemoteServices)value; RemoteServices = (IRemoteServices)value;
} }
else if (name == FileSystemParametersDefine.DECRYPTION_SERVICES)
{
DecryptionServices = (IWebDecryptionServices)value;
}
else else
{ {
YooLogger.Warning($"Invalid parameter : {name}"); YooLogger.Warning($"Invalid parameter : {name}");

View File

@@ -1,6 +1,4 @@
 
using UnityEngine;
namespace YooAsset namespace YooAsset
{ {
internal class DWRFSLoadAssetBundleOperation : FSLoadBundleOperation internal class DWRFSLoadAssetBundleOperation : FSLoadBundleOperation
@@ -8,13 +6,13 @@ namespace YooAsset
private enum ESteps private enum ESteps
{ {
None, None,
DownloadFile, DownloadAssetBundle,
Done, Done,
} }
private readonly DefaultWebRemoteFileSystem _fileSystem; private readonly DefaultWebRemoteFileSystem _fileSystem;
private readonly PackageBundle _bundle; private readonly PackageBundle _bundle;
private DownloadHandlerAssetBundleOperation _downloadhanlderAssetBundleOp; private DownloadAssetBundleOperation _downloadAssetBundleOp;
private ESteps _steps = ESteps.None; private ESteps _steps = ESteps.None;
@@ -25,38 +23,47 @@ namespace YooAsset
} }
internal override void InternalOnStart() internal override void InternalOnStart()
{ {
_steps = ESteps.DownloadFile; _steps = ESteps.DownloadAssetBundle;
} }
internal override void InternalOnUpdate() internal override void InternalOnUpdate()
{ {
if (_steps == ESteps.None || _steps == ESteps.Done) if (_steps == ESteps.None || _steps == ESteps.Done)
return; return;
if (_steps == ESteps.DownloadFile) if (_steps == ESteps.DownloadAssetBundle)
{ {
if (_downloadhanlderAssetBundleOp == null) if (_downloadAssetBundleOp == null)
{ {
DownloadParam downloadParam = new DownloadParam(int.MaxValue, 60); DownloadParam downloadParam = new DownloadParam(int.MaxValue, 60);
downloadParam.MainURL = _fileSystem.RemoteServices.GetRemoteMainURL(_bundle.FileName); downloadParam.MainURL = _fileSystem.RemoteServices.GetRemoteMainURL(_bundle.FileName);
downloadParam.FallbackURL = _fileSystem.RemoteServices.GetRemoteFallbackURL(_bundle.FileName); downloadParam.FallbackURL = _fileSystem.RemoteServices.GetRemoteFallbackURL(_bundle.FileName);
_downloadhanlderAssetBundleOp = new DownloadHandlerAssetBundleOperation(_fileSystem.DisableUnityWebCache, _bundle, downloadParam);
OperationSystem.StartOperation(_fileSystem.PackageName, _downloadhanlderAssetBundleOp); if (_bundle.Encrypted)
{
_downloadAssetBundleOp = new DownloadWebEncryptAssetBundleOperation(true, _fileSystem.DecryptionServices, _bundle, downloadParam);
OperationSystem.StartOperation(_fileSystem.PackageName, _downloadAssetBundleOp);
}
else
{
_downloadAssetBundleOp = new DownloadWebNormalAssetBundleOperation(_fileSystem.DisableUnityWebCache, _bundle, downloadParam);
OperationSystem.StartOperation(_fileSystem.PackageName, _downloadAssetBundleOp);
}
} }
DownloadProgress = _downloadhanlderAssetBundleOp.DownloadProgress; DownloadProgress = _downloadAssetBundleOp.DownloadProgress;
DownloadedBytes = _downloadhanlderAssetBundleOp.DownloadedBytes; DownloadedBytes = _downloadAssetBundleOp.DownloadedBytes;
Progress = _downloadhanlderAssetBundleOp.Progress; Progress = _downloadAssetBundleOp.Progress;
if (_downloadhanlderAssetBundleOp.IsDone == false) if (_downloadAssetBundleOp.IsDone == false)
return; return;
if (_downloadhanlderAssetBundleOp.Status == EOperationStatus.Succeed) if (_downloadAssetBundleOp.Status == EOperationStatus.Succeed)
{ {
var assetBundle = _downloadhanlderAssetBundleOp.Result; var assetBundle = _downloadAssetBundleOp.Result;
if(assetBundle == null) if (assetBundle == null)
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Failed; Status = EOperationStatus.Failed;
Error = $"{nameof(DownloadHandlerAssetBundleOperation)} loaded asset bundle is null !"; Error = $"{nameof(DownloadAssetBundleOperation)} loaded asset bundle is null !";
} }
else else
{ {
@@ -69,7 +76,7 @@ namespace YooAsset
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Failed; Status = EOperationStatus.Failed;
Error = _downloadhanlderAssetBundleOp.Error; Error = _downloadAssetBundleOp.Error;
} }
} }
} }
@@ -85,10 +92,10 @@ namespace YooAsset
} }
public override void AbortDownloadOperation() public override void AbortDownloadOperation()
{ {
if (_steps == ESteps.DownloadFile) if (_steps == ESteps.DownloadAssetBundle)
{ {
if (_downloadhanlderAssetBundleOp != null) if (_downloadAssetBundleOp != null)
_downloadhanlderAssetBundleOp.SetAbort(); _downloadAssetBundleOp.SetAbort();
} }
} }
} }

View File

@@ -21,7 +21,7 @@ namespace YooAsset
} }
protected readonly Dictionary<string, FileWrapper> _wrappers = new Dictionary<string, FileWrapper>(10000); protected readonly Dictionary<string, FileWrapper> _wrappers = new Dictionary<string, FileWrapper>(10000);
protected readonly Dictionary<string, string> _webFilePaths = new Dictionary<string, string>(10000); protected readonly Dictionary<string, string> _webFilePathMapping = new Dictionary<string, string>(10000);
protected string _webPackageRoot = string.Empty; protected string _webPackageRoot = string.Empty;
/// <summary> /// <summary>
@@ -56,6 +56,11 @@ namespace YooAsset
/// 禁用Unity的网络缓存 /// 禁用Unity的网络缓存
/// </summary> /// </summary>
public bool DisableUnityWebCache { private set; get; } = false; public bool DisableUnityWebCache { private set; get; } = false;
/// <summary>
/// 自定义参数:解密方法类
/// </summary>
public IWebDecryptionServices DecryptionServices { private set; get; }
#endregion #endregion
@@ -113,6 +118,10 @@ namespace YooAsset
{ {
DisableUnityWebCache = (bool)value; DisableUnityWebCache = (bool)value;
} }
else if (name == FileSystemParametersDefine.DECRYPTION_SERVICES)
{
DecryptionServices = (IWebDecryptionServices)value;
}
else else
{ {
YooLogger.Warning($"Invalid parameter : {name}"); YooLogger.Warning($"Invalid parameter : {name}");
@@ -173,10 +182,10 @@ namespace YooAsset
} }
public string GetWebFileLoadPath(PackageBundle bundle) public string GetWebFileLoadPath(PackageBundle bundle)
{ {
if (_webFilePaths.TryGetValue(bundle.BundleGUID, out string filePath) == false) if (_webFilePathMapping.TryGetValue(bundle.BundleGUID, out string filePath) == false)
{ {
filePath = PathUtility.Combine(_webPackageRoot, bundle.FileName); filePath = PathUtility.Combine(_webPackageRoot, bundle.FileName);
_webFilePaths.Add(bundle.BundleGUID, filePath); _webFilePathMapping.Add(bundle.BundleGUID, filePath);
} }
return filePath; return filePath;
} }

View File

@@ -6,13 +6,13 @@ namespace YooAsset
private enum ESteps private enum ESteps
{ {
None, None,
DownloadFile, DownloadAssetBundle,
Done, Done,
} }
private readonly DefaultWebServerFileSystem _fileSystem; private readonly DefaultWebServerFileSystem _fileSystem;
private readonly PackageBundle _bundle; private readonly PackageBundle _bundle;
private DownloadHandlerAssetBundleOperation _downloadhanlderAssetBundleOp; private DownloadAssetBundleOperation _downloadAssetBundleOp;
private ESteps _steps = ESteps.None; private ESteps _steps = ESteps.None;
@@ -23,39 +23,48 @@ namespace YooAsset
} }
internal override void InternalOnStart() internal override void InternalOnStart()
{ {
_steps = ESteps.DownloadFile; _steps = ESteps.DownloadAssetBundle;
} }
internal override void InternalOnUpdate() internal override void InternalOnUpdate()
{ {
if (_steps == ESteps.None || _steps == ESteps.Done) if (_steps == ESteps.None || _steps == ESteps.Done)
return; return;
if (_steps == ESteps.DownloadFile) if (_steps == ESteps.DownloadAssetBundle)
{ {
if (_downloadhanlderAssetBundleOp == null) if (_downloadAssetBundleOp == null)
{ {
DownloadParam downloadParam = new DownloadParam(int.MaxValue, 60); DownloadParam downloadParam = new DownloadParam(int.MaxValue, 60);
string fileLoadPath = _fileSystem.GetWebFileLoadPath(_bundle); string fileLoadPath = _fileSystem.GetWebFileLoadPath(_bundle);
downloadParam.MainURL = DownloadSystemHelper.ConvertToWWWPath(fileLoadPath); downloadParam.MainURL = DownloadSystemHelper.ConvertToWWWPath(fileLoadPath);
downloadParam.FallbackURL = downloadParam.MainURL; downloadParam.FallbackURL = downloadParam.MainURL;
_downloadhanlderAssetBundleOp = new DownloadHandlerAssetBundleOperation(_fileSystem.DisableUnityWebCache, _bundle, downloadParam);
OperationSystem.StartOperation(_fileSystem.PackageName, _downloadhanlderAssetBundleOp); if (_bundle.Encrypted)
{
_downloadAssetBundleOp = new DownloadWebEncryptAssetBundleOperation(true, _fileSystem.DecryptionServices, _bundle, downloadParam);
OperationSystem.StartOperation(_fileSystem.PackageName, _downloadAssetBundleOp);
}
else
{
_downloadAssetBundleOp = new DownloadWebNormalAssetBundleOperation(_fileSystem.DisableUnityWebCache, _bundle, downloadParam);
OperationSystem.StartOperation(_fileSystem.PackageName, _downloadAssetBundleOp);
}
} }
DownloadProgress = _downloadhanlderAssetBundleOp.DownloadProgress; DownloadProgress = _downloadAssetBundleOp.DownloadProgress;
DownloadedBytes = _downloadhanlderAssetBundleOp.DownloadedBytes; DownloadedBytes = _downloadAssetBundleOp.DownloadedBytes;
Progress = _downloadhanlderAssetBundleOp.Progress; Progress = _downloadAssetBundleOp.Progress;
if (_downloadhanlderAssetBundleOp.IsDone == false) if (_downloadAssetBundleOp.IsDone == false)
return; return;
if (_downloadhanlderAssetBundleOp.Status == EOperationStatus.Succeed) if (_downloadAssetBundleOp.Status == EOperationStatus.Succeed)
{ {
var assetBundle = _downloadhanlderAssetBundleOp.Result; var assetBundle = _downloadAssetBundleOp.Result;
if (assetBundle == null) if (assetBundle == null)
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Failed; Status = EOperationStatus.Failed;
Error = $"{nameof(DownloadHandlerAssetBundleOperation)} loaded asset bundle is null !"; Error = $"{nameof(DownloadAssetBundleOperation)} loaded asset bundle is null !";
} }
else else
{ {
@@ -68,7 +77,7 @@ namespace YooAsset
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Failed; Status = EOperationStatus.Failed;
Error = _downloadhanlderAssetBundleOp.Error; Error = _downloadAssetBundleOp.Error;
} }
} }
} }
@@ -84,10 +93,10 @@ namespace YooAsset
} }
public override void AbortDownloadOperation() public override void AbortDownloadOperation()
{ {
if (_steps == ESteps.DownloadFile) if (_steps == ESteps.DownloadAssetBundle)
{ {
if (_downloadhanlderAssetBundleOp != null) if (_downloadAssetBundleOp != null)
_downloadhanlderAssetBundleOp.SetAbort(); _downloadAssetBundleOp.SetAbort();
} }
} }
} }

View File

@@ -109,11 +109,13 @@ namespace YooAsset
/// <summary> /// <summary>
/// 创建默认的WebServer文件系统参数 /// 创建默认的WebServer文件系统参数
/// </summary> /// </summary>
/// <param name="decryptionServices">加密文件解密服务类</param>
/// <param name="disableUnityWebCache">禁用Unity的网络缓存</param> /// <param name="disableUnityWebCache">禁用Unity的网络缓存</param>
public static FileSystemParameters CreateDefaultWebServerFileSystemParameters(bool disableUnityWebCache = false) public static FileSystemParameters CreateDefaultWebServerFileSystemParameters(IWebDecryptionServices decryptionServices = null, bool disableUnityWebCache = false)
{ {
string fileSystemClass = typeof(DefaultWebServerFileSystem).FullName; string fileSystemClass = typeof(DefaultWebServerFileSystem).FullName;
var fileSystemParams = new FileSystemParameters(fileSystemClass, null); var fileSystemParams = new FileSystemParameters(fileSystemClass, null);
fileSystemParams.AddParameter(FileSystemParametersDefine.DECRYPTION_SERVICES, decryptionServices);
fileSystemParams.AddParameter(FileSystemParametersDefine.DISABLE_UNITY_WEB_CACHE, disableUnityWebCache); fileSystemParams.AddParameter(FileSystemParametersDefine.DISABLE_UNITY_WEB_CACHE, disableUnityWebCache);
return fileSystemParams; return fileSystemParams;
} }
@@ -122,12 +124,14 @@ namespace YooAsset
/// 创建默认的WebRemote文件系统参数 /// 创建默认的WebRemote文件系统参数
/// </summary> /// </summary>
/// <param name="remoteServices">远端资源地址查询服务类</param> /// <param name="remoteServices">远端资源地址查询服务类</param>
/// <param name="decryptionServices">加密文件解密服务类</param>
/// <param name="disableUnityWebCache">禁用Unity的网络缓存</param> /// <param name="disableUnityWebCache">禁用Unity的网络缓存</param>
public static FileSystemParameters CreateDefaultWebRemoteFileSystemParameters(IRemoteServices remoteServices, bool disableUnityWebCache = false) public static FileSystemParameters CreateDefaultWebRemoteFileSystemParameters(IRemoteServices remoteServices, IWebDecryptionServices decryptionServices = null, bool disableUnityWebCache = false)
{ {
string fileSystemClass = typeof(DefaultWebRemoteFileSystem).FullName; string fileSystemClass = typeof(DefaultWebRemoteFileSystem).FullName;
var fileSystemParams = new FileSystemParameters(fileSystemClass, null); var fileSystemParams = new FileSystemParameters(fileSystemClass, null);
fileSystemParams.AddParameter(FileSystemParametersDefine.REMOTE_SERVICES, remoteServices); fileSystemParams.AddParameter(FileSystemParametersDefine.REMOTE_SERVICES, remoteServices);
fileSystemParams.AddParameter(FileSystemParametersDefine.DECRYPTION_SERVICES, decryptionServices);
fileSystemParams.AddParameter(FileSystemParametersDefine.DISABLE_UNITY_WEB_CACHE, disableUnityWebCache); fileSystemParams.AddParameter(FileSystemParametersDefine.DISABLE_UNITY_WEB_CACHE, disableUnityWebCache);
return fileSystemParams; return fileSystemParams;
} }

View File

@@ -20,7 +20,7 @@ namespace YooAsset
/// <summary> /// <summary>
/// 初始化缓存系统 /// 初始化文件系统
/// </summary> /// </summary>
FSInitializeFileSystemOperation InitializeFileSystemAsync(); FSInitializeFileSystemOperation InitializeFileSystemAsync();
@@ -30,7 +30,7 @@ namespace YooAsset
FSLoadPackageManifestOperation LoadPackageManifestAsync(string packageVersion, int timeout); FSLoadPackageManifestOperation LoadPackageManifestAsync(string packageVersion, int timeout);
/// <summary> /// <summary>
/// 查询最新的版本 /// 查询包裹版本
/// </summary> /// </summary>
FSRequestPackageVersionOperation RequestPackageVersionAsync(bool appendTimeTicks, int timeout); FSRequestPackageVersionOperation RequestPackageVersionAsync(bool appendTimeTicks, int timeout);
@@ -40,7 +40,7 @@ namespace YooAsset
FSClearCacheFilesOperation ClearCacheFilesAsync(PackageManifest manifest, string clearMode, object clearParam); FSClearCacheFilesOperation ClearCacheFilesAsync(PackageManifest manifest, string clearMode, object clearParam);
/// <summary> /// <summary>
/// 下载远端文件 /// 下载Bundle文件
/// </summary> /// </summary>
FSDownloadFileOperation DownloadFileAsync(PackageBundle bundle, DownloadParam param); FSDownloadFileOperation DownloadFileAsync(PackageBundle bundle, DownloadParam param);

View File

@@ -0,0 +1,14 @@
using UnityEngine;
using UnityEngine.Networking;
namespace YooAsset
{
internal abstract class DownloadAssetBundleOperation : DefaultDownloadFileOperation
{
internal DownloadAssetBundleOperation(PackageBundle bundle, DownloadParam param) : base(bundle, param)
{
}
public AssetBundle Result;
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: e4420bd73f37dec468a9b23425be68f2 guid: 0f65d2f6038b95246b7a09cec4055b3a
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2

View File

@@ -0,0 +1,157 @@
using UnityEngine;
using UnityEngine.Networking;
namespace YooAsset
{
internal class DownloadWebEncryptAssetBundleOperation : DownloadAssetBundleOperation
{
private readonly bool _checkTimeout;
private readonly IWebDecryptionServices _decryptionServices;
private DownloadHandlerBuffer _downloadhandler;
private ESteps _steps = ESteps.None;
internal DownloadWebEncryptAssetBundleOperation(bool checkTimeout, IWebDecryptionServices decryptionServices, PackageBundle bundle, DownloadParam param) : base(bundle, param)
{
_checkTimeout = checkTimeout;
_decryptionServices = decryptionServices;
}
internal override void InternalOnStart()
{
_steps = ESteps.CreateRequest;
}
internal override void InternalOnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
// 创建下载器
if (_steps == ESteps.CreateRequest)
{
// 获取请求地址
_requestURL = GetRequestURL();
// 重置变量
ResetRequestFiled();
// 创建下载器
CreateWebRequest();
_steps = ESteps.CheckRequest;
}
// 检测下载结果
if (_steps == ESteps.CheckRequest)
{
DownloadProgress = _webRequest.downloadProgress;
DownloadedBytes = (long)_webRequest.downloadedBytes;
Progress = DownloadProgress;
if (_webRequest.isDone == false)
{
if (_checkTimeout)
CheckRequestTimeout();
return;
}
// 检查网络错误
if (CheckRequestResult())
{
if (_decryptionServices == null)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"The {nameof(IWebDecryptionServices)} is null !";
YooLogger.Error(Error);
return;
}
var fileData = _downloadhandler.data;
if (fileData == null || fileData.Length == 0)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"The download handler data is null or empty !";
YooLogger.Error(Error);
return;
}
AssetBundle assetBundle = LoadEncryptedAssetBundle(fileData);
if (assetBundle == null)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = "Download handler asset bundle object is null !";
}
else
{
_steps = ESteps.Done;
Result = assetBundle;
Status = EOperationStatus.Succeed;
}
}
else
{
_steps = ESteps.TryAgain;
}
// 注意:最终释放请求器
DisposeWebRequest();
}
// 重新尝试下载
if (_steps == ESteps.TryAgain)
{
if (FailedTryAgain <= 0)
{
Status = EOperationStatus.Failed;
_steps = ESteps.Done;
YooLogger.Error(Error);
return;
}
_tryAgainTimer += Time.unscaledDeltaTime;
if (_tryAgainTimer > 1f)
{
FailedTryAgain--;
_steps = ESteps.CreateRequest;
YooLogger.Warning(Error);
}
}
}
internal override void InternalOnAbort()
{
_steps = ESteps.Done;
DisposeWebRequest();
}
private void CreateWebRequest()
{
_downloadhandler = new DownloadHandlerBuffer();
_webRequest = DownloadSystemHelper.NewUnityWebRequestGet(_requestURL);
_webRequest.downloadHandler = _downloadhandler;
_webRequest.disposeDownloadHandlerOnDispose = true;
_webRequest.SendWebRequest();
}
private void DisposeWebRequest()
{
if (_webRequest != null)
{
//注意引擎底层会自动调用Abort方法
_webRequest.Dispose();
_webRequest = null;
}
}
/// <summary>
/// 加载加密资源文件
/// </summary>
private AssetBundle LoadEncryptedAssetBundle(byte[] fileData)
{
var fileInfo = new WebDecryptFileInfo();
fileInfo.BundleName = Bundle.BundleName;
fileInfo.FileLoadCRC = Bundle.UnityCRC;
fileInfo.FileData = fileData;
var decryptResult = _decryptionServices.LoadAssetBundle(fileInfo);
return decryptResult.Result;
}
}
}

View File

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

View File

@@ -3,16 +3,13 @@ using UnityEngine.Networking;
namespace YooAsset namespace YooAsset
{ {
internal class DownloadHandlerAssetBundleOperation : DefaultDownloadFileOperation internal class DownloadWebNormalAssetBundleOperation : DownloadAssetBundleOperation
{ {
private readonly bool _disableUnityWebCache; private readonly bool _disableUnityWebCache;
private DownloadHandlerAssetBundle _downloadhandler; private DownloadHandlerAssetBundle _downloadhandler;
private ESteps _steps = ESteps.None; private ESteps _steps = ESteps.None;
public AssetBundle Result { private set; get; } internal DownloadWebNormalAssetBundleOperation(bool disableUnityWebCache, PackageBundle bundle, DownloadParam param) : base(bundle, param)
internal DownloadHandlerAssetBundleOperation(bool disableUnityWebCache, PackageBundle bundle, DownloadParam param) : base(bundle, param)
{ {
_disableUnityWebCache = disableUnityWebCache; _disableUnityWebCache = disableUnityWebCache;
} }
@@ -55,12 +52,12 @@ namespace YooAsset
// 检查网络错误 // 检查网络错误
if (CheckRequestResult()) if (CheckRequestResult())
{ {
var assetBundle = _downloadhandler.assetBundle; AssetBundle assetBundle = _downloadhandler.assetBundle;
if (assetBundle == null) if (assetBundle == null)
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Error = "Download handler asset bundle object is null !";
Status = EOperationStatus.Failed; Status = EOperationStatus.Failed;
Error = "Download handler asset bundle object is null !";
} }
else else
{ {
@@ -106,7 +103,7 @@ namespace YooAsset
private void CreateWebRequest() private void CreateWebRequest()
{ {
_downloadhandler = CreateDownloadHandler(); _downloadhandler = CreateWebDownloadHandler();
_webRequest = DownloadSystemHelper.NewUnityWebRequestGet(_requestURL); _webRequest = DownloadSystemHelper.NewUnityWebRequestGet(_requestURL);
_webRequest.downloadHandler = _downloadhandler; _webRequest.downloadHandler = _downloadhandler;
_webRequest.disposeDownloadHandlerOnDispose = true; _webRequest.disposeDownloadHandlerOnDispose = true;
@@ -121,7 +118,7 @@ namespace YooAsset
_webRequest = null; _webRequest = null;
} }
} }
private DownloadHandlerAssetBundle CreateDownloadHandler() private DownloadHandlerAssetBundle CreateWebDownloadHandler()
{ {
if (_disableUnityWebCache) if (_disableUnityWebCache)
{ {

View File

@@ -13,6 +13,11 @@ namespace YooAsset
private static Stopwatch _watch; private static Stopwatch _watch;
private static long _frameTime; private static long _frameTime;
/// <summary>
/// 快速启动模式
/// </summary>
public static bool QuickStartMode = false;
/// <summary> /// <summary>
/// 异步操作的最小时间片段 /// 异步操作的最小时间片段
/// </summary> /// </summary>
@@ -136,6 +141,11 @@ namespace YooAsset
_newList.Add(operation); _newList.Add(operation);
operation.SetPackageName(packageName); operation.SetPackageName(packageName);
operation.SetStart(); operation.SetStart();
if (QuickStartMode)
{
operation.InternalOnUpdate();
}
} }
} }
} }

View File

@@ -153,7 +153,23 @@ namespace YooAsset
if (IsDone == false) if (IsDone == false)
return false; return false;
return RefCount <= 0; if (RefCount > 0)
return false;
#region YOOASSET_LEGACY_DEPENDENCY
// 检查引用链上的资源包是否已经全部销毁
// 注意:互相引用的资源包无法卸载!
if (LoadBundleInfo.Bundle.ReferenceBundleIDs.Length > 0)
{
foreach (var bundleID in LoadBundleInfo.Bundle.ReferenceBundleIDs)
{
if (_resourceManager.CheckBundleDestroyed(bundleID) == false)
return false;
}
}
#endregion
return true;
} }
/// <summary> /// <summary>

View File

@@ -3,38 +3,88 @@ using UnityEngine;
namespace YooAsset namespace YooAsset
{ {
public sealed class UnloadAllAssetsOptions
{
/// <summary>
/// 释放所有资源句柄,防止卸载过程中触发完成回调!
/// </summary>
public bool ReleaseAllHandles = false;
/// <summary>
/// 卸载过程中锁定加载操作,防止新的任务请求!
/// </summary>
public bool LockLoadOperation = false;
}
public sealed class UnloadAllAssetsOperation : AsyncOperationBase public sealed class UnloadAllAssetsOperation : AsyncOperationBase
{ {
private enum ESteps private enum ESteps
{ {
None, None,
CheckOptions,
ReleaseAll,
AbortDownload, AbortDownload,
CheckLoading, CheckLoading,
UnloadAll, DestroyAll,
Done, Done,
} }
private readonly ResourceManager _resManager; private readonly ResourceManager _resManager;
private readonly UnloadAllAssetsOptions _options;
private ESteps _steps = ESteps.None; private ESteps _steps = ESteps.None;
internal UnloadAllAssetsOperation(ResourceManager resourceManager) internal UnloadAllAssetsOperation(ResourceManager resourceManager, UnloadAllAssetsOptions options)
{ {
_resManager = resourceManager; _resManager = resourceManager;
_options = options;
} }
internal override void InternalOnStart() internal override void InternalOnStart()
{ {
_steps = ESteps.AbortDownload; _steps = ESteps.CheckOptions;
} }
internal override void InternalOnUpdate() internal override void InternalOnUpdate()
{ {
if (_steps == ESteps.None || _steps == ESteps.Done) if (_steps == ESteps.None || _steps == ESteps.Done)
return; return;
if (_steps == ESteps.CheckOptions)
{
if (_options == null)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"{nameof(UnloadAllAssetsOptions)} is null.";
return;
}
// 设置锁定状态
if (_options.LockLoadOperation)
_resManager.LockLoadOperation = true;
_steps = ESteps.ReleaseAll;
}
if (_steps == ESteps.ReleaseAll)
{
// 清空所有场景句柄
_resManager.SceneHandles.Clear();
// 释放所有资源句柄
if (_options.ReleaseAllHandles)
{
foreach (var provider in _resManager.ProviderDic.Values)
{
provider.ReleaseAllHandles();
}
}
_steps = ESteps.AbortDownload;
}
if (_steps == ESteps.AbortDownload) if (_steps == ESteps.AbortDownload)
{ {
// 注意:终止所有下载任务 // 注意:终止所有下载任务
var loaderDic = _resManager._loaderDic; foreach (var loader in _resManager.LoaderDic.Values)
foreach (var loader in loaderDic.Values)
{ {
loader.AbortDownloadOperation(); loader.AbortDownloadOperation();
} }
@@ -44,44 +94,32 @@ namespace YooAsset
if (_steps == ESteps.CheckLoading) if (_steps == ESteps.CheckLoading)
{ {
// 注意:等待所有任务完成 // 注意:等待所有任务完成
var providerDic = _resManager._providerDic; foreach (var provider in _resManager.ProviderDic.Values)
foreach (var provider in providerDic.Values)
{ {
if (provider.IsDone == false) if (provider.IsDone == false)
return; return;
} }
_steps = ESteps.UnloadAll; _steps = ESteps.DestroyAll;
} }
if (_steps == ESteps.UnloadAll) if (_steps == ESteps.DestroyAll)
{ {
var loaderDic = _resManager._loaderDic;
var providerDic = _resManager._providerDic;
// 清空所有场景句柄
_resManager._sceneHandles.Clear();
// 释放所有资源句柄
foreach (var provider in providerDic.Values)
{
provider.ReleaseAllHandles();
}
// 强制销毁资源提供者 // 强制销毁资源提供者
foreach (var provider in providerDic.Values) foreach (var provider in _resManager.ProviderDic.Values)
{ {
provider.DestroyProvider(); provider.DestroyProvider();
} }
// 强制销毁文件加载器 // 强制销毁文件加载器
foreach (var loader in loaderDic.Values) foreach (var loader in _resManager.LoaderDic.Values)
{ {
loader.DestroyLoader(); loader.DestroyLoader();
} }
// 清空数据 // 清空数据
providerDic.Clear(); _resManager.ProviderDic.Clear();
loaderDic.Clear(); _resManager.LoaderDic.Clear();
_resManager.LockLoadOperation = false;
// 注意:调用底层接口释放所有资源 // 注意:调用底层接口释放所有资源
Resources.UnloadUnusedAssets(); Resources.UnloadUnusedAssets();

View File

@@ -31,17 +31,16 @@ namespace YooAsset
if (_steps == ESteps.UnloadUnused) if (_steps == ESteps.UnloadUnused)
{ {
var loaderDic = _resManager._loaderDic; var removeList = new List<LoadBundleFileOperation>(_resManager.LoaderDic.Count);
var removeList = new List<LoadBundleFileOperation>(loaderDic.Count);
// 注意:优先销毁资源提供者 // 注意:优先销毁资源提供者
foreach (var loader in loaderDic.Values) foreach (var loader in _resManager.LoaderDic.Values)
{ {
loader.TryDestroyProviders(); loader.TryDestroyProviders();
} }
// 获取销毁列表 // 获取销毁列表
foreach (var loader in loaderDic.Values) foreach (var loader in _resManager.LoaderDic.Values)
{ {
if (loader.CanDestroyLoader()) if (loader.CanDestroyLoader())
{ {
@@ -54,13 +53,9 @@ namespace YooAsset
{ {
string bundleName = loader.LoadBundleInfo.Bundle.BundleName; string bundleName = loader.LoadBundleInfo.Bundle.BundleName;
loader.DestroyLoader(); loader.DestroyLoader();
_resManager._loaderDic.Remove(bundleName); _resManager.LoaderDic.Remove(bundleName);
} }
// 注意:调用底层接口释放所有资源
if (removeList.Count > 0)
Resources.UnloadUnusedAssets();
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Succeed; Status = EOperationStatus.Succeed;
} }

View File

@@ -86,7 +86,7 @@ namespace YooAsset
// 依赖资源包加载器集合 // 依赖资源包加载器集合
var dependLoaders = manager.CreateDependBundleFileLoaders(assetInfo); var dependLoaders = manager.CreateDependBundleFileLoaders(assetInfo);
if(dependLoaders.Count > 0) if (dependLoaders.Count > 0)
_bundleLoaders.AddRange(dependLoaders); _bundleLoaders.AddRange(dependLoaders);
// 增加引用计数 // 增加引用计数

View File

@@ -9,9 +9,9 @@ namespace YooAsset
{ {
internal class ResourceManager internal class ResourceManager
{ {
internal readonly Dictionary<string, ProviderOperation> _providerDic = new Dictionary<string, ProviderOperation>(5000); internal readonly Dictionary<string, ProviderOperation> ProviderDic = new Dictionary<string, ProviderOperation>(5000);
internal readonly Dictionary<string, LoadBundleFileOperation> _loaderDic = new Dictionary<string, LoadBundleFileOperation>(5000); internal readonly Dictionary<string, LoadBundleFileOperation> LoaderDic = new Dictionary<string, LoadBundleFileOperation>(5000);
internal readonly List<SceneHandle> _sceneHandles = new List<SceneHandle>(100); internal readonly List<SceneHandle> SceneHandles = new List<SceneHandle>(100);
private long _sceneCreateIndex = 0; private long _sceneCreateIndex = 0;
private IBundleQuery _bundleQuery; private IBundleQuery _bundleQuery;
@@ -20,6 +20,11 @@ namespace YooAsset
/// </summary> /// </summary>
public readonly string PackageName; public readonly string PackageName;
/// <summary>
/// 锁定加载操作
/// </summary>
public bool LockLoadOperation = false;
public ResourceManager(string packageName) public ResourceManager(string packageName)
{ {
@@ -64,7 +69,7 @@ namespace YooAsset
{ {
string bundleName = mainLoader.LoadBundleInfo.Bundle.BundleName; string bundleName = mainLoader.LoadBundleInfo.Bundle.BundleName;
mainLoader.DestroyLoader(); mainLoader.DestroyLoader();
_loaderDic.Remove(bundleName); LoaderDic.Remove(bundleName);
} }
} }
@@ -79,7 +84,7 @@ namespace YooAsset
{ {
string bundleName = dependLoader.LoadBundleInfo.Bundle.BundleName; string bundleName = dependLoader.LoadBundleInfo.Bundle.BundleName;
dependLoader.DestroyLoader(); dependLoader.DestroyLoader();
_loaderDic.Remove(bundleName); LoaderDic.Remove(bundleName);
} }
} }
} }
@@ -92,6 +97,15 @@ namespace YooAsset
/// </summary> /// </summary>
public SceneHandle LoadSceneAsync(AssetInfo assetInfo, LoadSceneParameters loadSceneParams, bool suspendLoad, uint priority) public SceneHandle LoadSceneAsync(AssetInfo assetInfo, LoadSceneParameters loadSceneParams, bool suspendLoad, uint priority)
{ {
if (LockLoadOperation)
{
string error = $"The load operation locked !";
YooLogger.Error(error);
CompletedProvider completedProvider = new CompletedProvider(this, assetInfo);
completedProvider.SetCompletedWithError(error);
return completedProvider.CreateHandle<SceneHandle>();
}
if (assetInfo.IsInvalid) if (assetInfo.IsInvalid)
{ {
YooLogger.Error($"Failed to load scene ! {assetInfo.Error}"); YooLogger.Error($"Failed to load scene ! {assetInfo.Error}");
@@ -106,14 +120,14 @@ namespace YooAsset
{ {
provider = new SceneProvider(this, providerGUID, assetInfo, loadSceneParams, suspendLoad); provider = new SceneProvider(this, providerGUID, assetInfo, loadSceneParams, suspendLoad);
provider.InitSpawnDebugInfo(); provider.InitSpawnDebugInfo();
_providerDic.Add(providerGUID, provider); ProviderDic.Add(providerGUID, provider);
OperationSystem.StartOperation(PackageName, provider); OperationSystem.StartOperation(PackageName, provider);
} }
provider.Priority = priority; provider.Priority = priority;
var handle = provider.CreateHandle<SceneHandle>(); var handle = provider.CreateHandle<SceneHandle>();
handle.PackageName = PackageName; handle.PackageName = PackageName;
_sceneHandles.Add(handle); SceneHandles.Add(handle);
return handle; return handle;
} }
@@ -122,6 +136,15 @@ namespace YooAsset
/// </summary> /// </summary>
public AssetHandle LoadAssetAsync(AssetInfo assetInfo, uint priority) public AssetHandle LoadAssetAsync(AssetInfo assetInfo, uint priority)
{ {
if (LockLoadOperation)
{
string error = $"The load operation locked !";
YooLogger.Error(error);
CompletedProvider completedProvider = new CompletedProvider(this, assetInfo);
completedProvider.SetCompletedWithError(error);
return completedProvider.CreateHandle<AssetHandle>();
}
if (assetInfo.IsInvalid) if (assetInfo.IsInvalid)
{ {
YooLogger.Error($"Failed to load asset ! {assetInfo.Error}"); YooLogger.Error($"Failed to load asset ! {assetInfo.Error}");
@@ -136,7 +159,7 @@ namespace YooAsset
{ {
provider = new AssetProvider(this, providerGUID, assetInfo); provider = new AssetProvider(this, providerGUID, assetInfo);
provider.InitSpawnDebugInfo(); provider.InitSpawnDebugInfo();
_providerDic.Add(providerGUID, provider); ProviderDic.Add(providerGUID, provider);
OperationSystem.StartOperation(PackageName, provider); OperationSystem.StartOperation(PackageName, provider);
} }
@@ -149,6 +172,15 @@ namespace YooAsset
/// </summary> /// </summary>
public SubAssetsHandle LoadSubAssetsAsync(AssetInfo assetInfo, uint priority) public SubAssetsHandle LoadSubAssetsAsync(AssetInfo assetInfo, uint priority)
{ {
if (LockLoadOperation)
{
string error = $"The load operation locked !";
YooLogger.Error(error);
CompletedProvider completedProvider = new CompletedProvider(this, assetInfo);
completedProvider.SetCompletedWithError(error);
return completedProvider.CreateHandle<SubAssetsHandle>();
}
if (assetInfo.IsInvalid) if (assetInfo.IsInvalid)
{ {
YooLogger.Error($"Failed to load sub assets ! {assetInfo.Error}"); YooLogger.Error($"Failed to load sub assets ! {assetInfo.Error}");
@@ -163,7 +195,7 @@ namespace YooAsset
{ {
provider = new SubAssetsProvider(this, providerGUID, assetInfo); provider = new SubAssetsProvider(this, providerGUID, assetInfo);
provider.InitSpawnDebugInfo(); provider.InitSpawnDebugInfo();
_providerDic.Add(providerGUID, provider); ProviderDic.Add(providerGUID, provider);
OperationSystem.StartOperation(PackageName, provider); OperationSystem.StartOperation(PackageName, provider);
} }
@@ -176,6 +208,15 @@ namespace YooAsset
/// </summary> /// </summary>
public AllAssetsHandle LoadAllAssetsAsync(AssetInfo assetInfo, uint priority) public AllAssetsHandle LoadAllAssetsAsync(AssetInfo assetInfo, uint priority)
{ {
if (LockLoadOperation)
{
string error = $"The load operation locked !";
YooLogger.Error(error);
CompletedProvider completedProvider = new CompletedProvider(this, assetInfo);
completedProvider.SetCompletedWithError(error);
return completedProvider.CreateHandle<AllAssetsHandle>();
}
if (assetInfo.IsInvalid) if (assetInfo.IsInvalid)
{ {
YooLogger.Error($"Failed to load all assets ! {assetInfo.Error}"); YooLogger.Error($"Failed to load all assets ! {assetInfo.Error}");
@@ -190,7 +231,7 @@ namespace YooAsset
{ {
provider = new AllAssetsProvider(this, providerGUID, assetInfo); provider = new AllAssetsProvider(this, providerGUID, assetInfo);
provider.InitSpawnDebugInfo(); provider.InitSpawnDebugInfo();
_providerDic.Add(providerGUID, provider); ProviderDic.Add(providerGUID, provider);
OperationSystem.StartOperation(PackageName, provider); OperationSystem.StartOperation(PackageName, provider);
} }
@@ -203,6 +244,15 @@ namespace YooAsset
/// </summary> /// </summary>
public RawFileHandle LoadRawFileAsync(AssetInfo assetInfo, uint priority) public RawFileHandle LoadRawFileAsync(AssetInfo assetInfo, uint priority)
{ {
if (LockLoadOperation)
{
string error = $"The load operation locked !";
YooLogger.Error(error);
CompletedProvider completedProvider = new CompletedProvider(this, assetInfo);
completedProvider.SetCompletedWithError(error);
return completedProvider.CreateHandle<RawFileHandle>();
}
if (assetInfo.IsInvalid) if (assetInfo.IsInvalid)
{ {
YooLogger.Error($"Failed to load raw file ! {assetInfo.Error}"); YooLogger.Error($"Failed to load raw file ! {assetInfo.Error}");
@@ -217,7 +267,7 @@ namespace YooAsset
{ {
provider = new RawFileProvider(this, providerGUID, assetInfo); provider = new RawFileProvider(this, providerGUID, assetInfo);
provider.InitSpawnDebugInfo(); provider.InitSpawnDebugInfo();
_providerDic.Add(providerGUID, provider); ProviderDic.Add(providerGUID, provider);
OperationSystem.StartOperation(PackageName, provider); OperationSystem.StartOperation(PackageName, provider);
} }
@@ -245,12 +295,20 @@ namespace YooAsset
{ {
foreach (var provider in removeList) foreach (var provider in removeList)
{ {
_providerDic.Remove(provider.ProviderGUID); ProviderDic.Remove(provider.ProviderGUID);
} }
} }
internal bool CheckBundleDestroyed(int bundleID)
{
string bundleName = _bundleQuery.GetMainBundleName(bundleID);
var bundleFileLoader = TryGetBundleFileLoader(bundleName);
if (bundleFileLoader == null)
return true;
return bundleFileLoader.IsDestroyed;
}
internal bool HasAnyLoader() internal bool HasAnyLoader()
{ {
return _loaderDic.Count > 0; return LoaderDic.Count > 0;
} }
private LoadBundleFileOperation CreateBundleFileLoaderInternal(BundleInfo bundleInfo) private LoadBundleFileOperation CreateBundleFileLoaderInternal(BundleInfo bundleInfo)
@@ -264,19 +322,19 @@ namespace YooAsset
// 新增下载需求 // 新增下载需求
loaderOperation = new LoadBundleFileOperation(this, bundleInfo); loaderOperation = new LoadBundleFileOperation(this, bundleInfo);
OperationSystem.StartOperation(PackageName, loaderOperation); OperationSystem.StartOperation(PackageName, loaderOperation);
_loaderDic.Add(bundleName, loaderOperation); LoaderDic.Add(bundleName, loaderOperation);
return loaderOperation; return loaderOperation;
} }
private LoadBundleFileOperation TryGetBundleFileLoader(string bundleName) private LoadBundleFileOperation TryGetBundleFileLoader(string bundleName)
{ {
if (_loaderDic.TryGetValue(bundleName, out LoadBundleFileOperation value)) if (LoaderDic.TryGetValue(bundleName, out LoadBundleFileOperation value))
return value; return value;
else else
return null; return null;
} }
private ProviderOperation TryGetAssetProvider(string providerGUID) private ProviderOperation TryGetAssetProvider(string providerGUID)
{ {
if (_providerDic.TryGetValue(providerGUID, out ProviderOperation value)) if (ProviderDic.TryGetValue(providerGUID, out ProviderOperation value))
return value; return value;
else else
return null; return null;
@@ -284,7 +342,7 @@ namespace YooAsset
private void OnSceneUnloaded(Scene scene) private void OnSceneUnloaded(Scene scene)
{ {
List<SceneHandle> removeList = new List<SceneHandle>(); List<SceneHandle> removeList = new List<SceneHandle>();
foreach (var sceneHandle in _sceneHandles) foreach (var sceneHandle in SceneHandles)
{ {
if (sceneHandle.IsValid) if (sceneHandle.IsValid)
{ {
@@ -297,15 +355,15 @@ namespace YooAsset
} }
foreach (var sceneHandle in removeList) foreach (var sceneHandle in removeList)
{ {
_sceneHandles.Remove(sceneHandle); SceneHandles.Remove(sceneHandle);
} }
} }
#region #region
internal List<DebugProviderInfo> GetDebugReportInfos() internal List<DebugProviderInfo> GetDebugReportInfos()
{ {
List<DebugProviderInfo> result = new List<DebugProviderInfo>(_providerDic.Count); List<DebugProviderInfo> result = new List<DebugProviderInfo>(ProviderDic.Count);
foreach (var provider in _providerDic.Values) foreach (var provider in ProviderDic.Values)
{ {
DebugProviderInfo providerInfo = new DebugProviderInfo(); DebugProviderInfo providerInfo = new DebugProviderInfo();
providerInfo.AssetPath = provider.MainAssetInfo.AssetPath; providerInfo.AssetPath = provider.MainAssetInfo.AssetPath;

View File

@@ -13,6 +13,11 @@ namespace YooAsset
/// </summary> /// </summary>
BundleInfo[] GetDependBundleInfos(AssetInfo assetPath); BundleInfo[] GetDependBundleInfos(AssetInfo assetPath);
/// <summary>
/// 获取主资源包名称
/// </summary>
string GetMainBundleName(int bundleID);
/// <summary> /// <summary>
/// 获取主资源包名称 /// 获取主资源包名称
/// </summary> /// </summary>

View File

@@ -35,6 +35,7 @@ namespace YooAsset
buffer.WriteUTF8(manifest.FileVersion); buffer.WriteUTF8(manifest.FileVersion);
// 写入文件头信息 // 写入文件头信息
buffer.WriteBool(manifest.LegacyDependency);
buffer.WriteBool(manifest.EnableAddressable); buffer.WriteBool(manifest.EnableAddressable);
buffer.WriteBool(manifest.LocationToLower); buffer.WriteBool(manifest.LocationToLower);
buffer.WriteBool(manifest.IncludeAssetGUID); buffer.WriteBool(manifest.IncludeAssetGUID);
@@ -55,6 +56,7 @@ namespace YooAsset
buffer.WriteUTF8(packageAsset.AssetGUID); buffer.WriteUTF8(packageAsset.AssetGUID);
buffer.WriteUTF8Array(packageAsset.AssetTags); buffer.WriteUTF8Array(packageAsset.AssetTags);
buffer.WriteInt32(packageAsset.BundleID); buffer.WriteInt32(packageAsset.BundleID);
buffer.WriteInt32Array(packageAsset.DependBundleIDs);
} }
// 写入资源包列表 // 写入资源包列表
@@ -70,6 +72,7 @@ namespace YooAsset
buffer.WriteBool(packageBundle.Encrypted); buffer.WriteBool(packageBundle.Encrypted);
buffer.WriteUTF8Array(packageBundle.Tags); buffer.WriteUTF8Array(packageBundle.Tags);
buffer.WriteInt32Array(packageBundle.DependIDs); buffer.WriteInt32Array(packageBundle.DependIDs);
buffer.WriteInt32Array(packageBundle.ReferenceBundleIDs);
} }
// 写入文件流 // 写入文件流
@@ -108,6 +111,7 @@ namespace YooAsset
{ {
// 读取文件头信息 // 读取文件头信息
manifest.FileVersion = fileVersion; manifest.FileVersion = fileVersion;
manifest.LegacyDependency = buffer.ReadBool();
manifest.EnableAddressable = buffer.ReadBool(); manifest.EnableAddressable = buffer.ReadBool();
manifest.LocationToLower = buffer.ReadBool(); manifest.LocationToLower = buffer.ReadBool();
manifest.IncludeAssetGUID = buffer.ReadBool(); manifest.IncludeAssetGUID = buffer.ReadBool();
@@ -133,6 +137,7 @@ namespace YooAsset
packageAsset.AssetGUID = buffer.ReadUTF8(); packageAsset.AssetGUID = buffer.ReadUTF8();
packageAsset.AssetTags = buffer.ReadUTF8Array(); packageAsset.AssetTags = buffer.ReadUTF8Array();
packageAsset.BundleID = buffer.ReadInt32(); packageAsset.BundleID = buffer.ReadInt32();
packageAsset.DependBundleIDs = buffer.ReadInt32Array();
FillAssetCollection(manifest, packageAsset); FillAssetCollection(manifest, packageAsset);
} }
@@ -150,6 +155,7 @@ namespace YooAsset
packageBundle.Encrypted = buffer.ReadBool(); packageBundle.Encrypted = buffer.ReadBool();
packageBundle.Tags = buffer.ReadUTF8Array(); packageBundle.Tags = buffer.ReadUTF8Array();
packageBundle.DependIDs = buffer.ReadInt32Array(); packageBundle.DependIDs = buffer.ReadInt32Array();
packageBundle.ReferenceBundleIDs = buffer.ReadInt32Array();
FillBundleCollection(manifest, packageBundle); FillBundleCollection(manifest, packageBundle);
} }
} }
@@ -318,8 +324,15 @@ namespace YooAsset
} }
else if (nameStyle == (int)EFileNameStyle.BundleName_HashName) else if (nameStyle == (int)EFileNameStyle.BundleName_HashName)
{ {
string fileName = bundleName.Remove(bundleName.LastIndexOf('.')); if (string.IsNullOrEmpty(fileExtension))
return StringUtility.Format("{0}_{1}{2}", fileName, fileHash, fileExtension); {
return StringUtility.Format("{0}_{1}", bundleName, fileHash);
}
else
{
string fileName = bundleName.Remove(bundleName.LastIndexOf('.'));
return StringUtility.Format("{0}_{1}{2}", fileName, fileHash, fileExtension);
}
} }
else else
{ {

View File

@@ -78,6 +78,7 @@ namespace YooAsset
// 读取文件头信息 // 读取文件头信息
Manifest = new PackageManifest(); Manifest = new PackageManifest();
Manifest.FileVersion = fileVersion; Manifest.FileVersion = fileVersion;
Manifest.LegacyDependency = _buffer.ReadBool();
Manifest.EnableAddressable = _buffer.ReadBool(); Manifest.EnableAddressable = _buffer.ReadBool();
Manifest.LocationToLower = _buffer.ReadBool(); Manifest.LocationToLower = _buffer.ReadBool();
Manifest.IncludeAssetGUID = _buffer.ReadBool(); Manifest.IncludeAssetGUID = _buffer.ReadBool();
@@ -112,6 +113,7 @@ namespace YooAsset
packageAsset.AssetGUID = _buffer.ReadUTF8(); packageAsset.AssetGUID = _buffer.ReadUTF8();
packageAsset.AssetTags = _buffer.ReadUTF8Array(); packageAsset.AssetTags = _buffer.ReadUTF8Array();
packageAsset.BundleID = _buffer.ReadInt32(); packageAsset.BundleID = _buffer.ReadInt32();
packageAsset.DependBundleIDs = _buffer.ReadInt32Array();
ManifestTools.FillAssetCollection(Manifest, packageAsset); ManifestTools.FillAssetCollection(Manifest, packageAsset);
_packageAssetCount--; _packageAssetCount--;
@@ -146,6 +148,7 @@ namespace YooAsset
packageBundle.Encrypted = _buffer.ReadBool(); packageBundle.Encrypted = _buffer.ReadBool();
packageBundle.Tags = _buffer.ReadUTF8Array(); packageBundle.Tags = _buffer.ReadUTF8Array();
packageBundle.DependIDs = _buffer.ReadInt32Array(); packageBundle.DependIDs = _buffer.ReadInt32Array();
packageBundle.ReferenceBundleIDs = _buffer.ReadInt32Array();
ManifestTools.FillBundleCollection(Manifest, packageBundle); ManifestTools.FillBundleCollection(Manifest, packageBundle);
_packageBundleCount--; _packageBundleCount--;

View File

@@ -31,11 +31,18 @@ namespace YooAsset
/// </summary> /// </summary>
public int BundleID; public int BundleID;
#region YOOASSET_LEGACY_DEPENDENCY
/// <summary> /// <summary>
/// 所属资源包名称(仅编辑器有效) /// 依赖的资源包列表
/// </summary>
public int[] DependBundleIDs;
#endregion
/// <summary>
/// 临时数据对象(仅编辑器有效)
/// </summary> /// </summary>
[NonSerialized] [NonSerialized]
public string BundleNameInEditor; public object TempDataInEditor;
/// <summary> /// <summary>
/// 是否包含Tag /// 是否包含Tag

View File

@@ -47,6 +47,14 @@ namespace YooAsset
/// </summary> /// </summary>
public int[] DependIDs; public int[] DependIDs;
#region YOOASSET_LEGACY_DEPENDENCY
/// <summary>
/// 引用该资源包的资源包列表
/// 说明:谁引用了该资源包
/// </summary>
public int[] ReferenceBundleIDs;
#endregion
/// <summary> /// <summary>
/// 资源包GUID /// 资源包GUID
/// </summary> /// </summary>
@@ -101,6 +109,12 @@ namespace YooAsset
[NonSerialized] [NonSerialized]
public readonly List<PackageAsset> IncludeMainAssets = new List<PackageAsset>(10); public readonly List<PackageAsset> IncludeMainAssets = new List<PackageAsset>(10);
/// <summary>
/// 临时数据对象(仅编辑器有效)
/// </summary>
[NonSerialized]
public object TempDataInEditor;
public PackageBundle() public PackageBundle()
{ {

View File

@@ -17,6 +17,11 @@ namespace YooAsset
/// </summary> /// </summary>
public string FileVersion; public string FileVersion;
/// <summary>
/// 旧版依赖模式
/// </summary>
public bool LegacyDependency;
/// <summary> /// <summary>
/// 启用可寻址资源定位 /// 启用可寻址资源定位
/// </summary> /// </summary>
@@ -155,16 +160,7 @@ namespace YooAsset
{ {
if (AssetDic.TryGetValue(assetPath, out PackageAsset packageAsset)) if (AssetDic.TryGetValue(assetPath, out PackageAsset packageAsset))
{ {
int bundleID = packageAsset.BundleID; return GetMainPackageBundle(packageAsset.BundleID);
if (bundleID >= 0 && bundleID < BundleList.Count)
{
var packageBundle = BundleList[bundleID];
return packageBundle;
}
else
{
throw new Exception($"Invalid bundle id : {bundleID} Asset path : {assetPath}");
}
} }
else else
{ {
@@ -172,27 +168,58 @@ namespace YooAsset
} }
} }
/// <summary>
/// 获取主资源包
/// 注意传入的资源包ID一定合法有效
/// </summary>
public PackageBundle GetMainPackageBundle(int bundleID)
{
if (bundleID >= 0 && bundleID < BundleList.Count)
{
var packageBundle = BundleList[bundleID];
return packageBundle;
}
else
{
throw new Exception($"Invalid bundle id : {bundleID}");
}
}
/// <summary> /// <summary>
/// 获取资源依赖列表 /// 获取资源依赖列表
/// 注意:传入的资源路径一定合法有效! /// 注意:传入的资源路径一定合法有效!
/// </summary> /// </summary>
public PackageBundle[] GetAllDependencies(string assetPath) public PackageBundle[] GetAllDependencies(string assetPath)
{ {
var packageBundle = GetMainPackageBundle(assetPath); // YOOASSET_LEGACY_DEPENDENCY
List<PackageBundle> result = new List<PackageBundle>(packageBundle.DependIDs.Length); if (LegacyDependency)
foreach (var dependID in packageBundle.DependIDs)
{ {
if (dependID >= 0 && dependID < BundleList.Count) if (TryGetPackageAsset(assetPath, out PackageAsset packageAsset))
{ {
var dependBundle = BundleList[dependID]; List<PackageBundle> result = new List<PackageBundle>(packageAsset.DependBundleIDs.Length);
result.Add(dependBundle); foreach (var dependID in packageAsset.DependBundleIDs)
{
var dependBundle = GetMainPackageBundle(dependID);
result.Add(dependBundle);
}
return result.ToArray();
} }
else else
{ {
throw new Exception($"Invalid bundle id : {dependID} Asset path : {assetPath}"); throw new Exception("Should never get here !");
} }
} }
return result.ToArray(); else
{
var packageBundle = GetMainPackageBundle(assetPath);
List<PackageBundle> result = new List<PackageBundle>(packageBundle.DependIDs.Length);
foreach (var dependID in packageBundle.DependIDs)
{
var dependBundle = GetMainPackageBundle(dependID);
result.Add(dependBundle);
}
return result.ToArray();
}
} }
/// <summary> /// <summary>

View File

@@ -135,6 +135,12 @@ namespace YooAsset
} }
return result.ToArray(); return result.ToArray();
} }
string IBundleQuery.GetMainBundleName(int bundleID)
{
// 注意:如果清单里未找到资源包会抛出异常!
var packageBundle = ActiveManifest.GetMainPackageBundle(bundleID);
return packageBundle.BundleName;
}
string IBundleQuery.GetMainBundleName(AssetInfo assetInfo) string IBundleQuery.GetMainBundleName(AssetInfo assetInfo)
{ {
if (assetInfo.IsInvalid) if (assetInfo.IsInvalid)

View File

@@ -144,6 +144,12 @@ namespace YooAsset
} }
return result.ToArray(); return result.ToArray();
} }
string IBundleQuery.GetMainBundleName(int bundleID)
{
// 注意:如果清单里未找到资源包会抛出异常!
var packageBundle = ActiveManifest.GetMainPackageBundle(bundleID);
return packageBundle.BundleName;
}
string IBundleQuery.GetMainBundleName(AssetInfo assetInfo) string IBundleQuery.GetMainBundleName(AssetInfo assetInfo)
{ {
if (assetInfo.IsInvalid) if (assetInfo.IsInvalid)

View File

@@ -135,6 +135,12 @@ namespace YooAsset
} }
return result.ToArray(); return result.ToArray();
} }
string IBundleQuery.GetMainBundleName(int bundleID)
{
// 注意:如果清单里未找到资源包会抛出异常!
var packageBundle = ActiveManifest.GetMainPackageBundle(bundleID);
return packageBundle.BundleName;
}
string IBundleQuery.GetMainBundleName(AssetInfo assetInfo) string IBundleQuery.GetMainBundleName(AssetInfo assetInfo)
{ {
if (assetInfo.IsInvalid) if (assetInfo.IsInvalid)

View File

@@ -163,6 +163,12 @@ namespace YooAsset
} }
return result.ToArray(); return result.ToArray();
} }
string IBundleQuery.GetMainBundleName(int bundleID)
{
// 注意:如果清单里未找到资源包会抛出异常!
var packageBundle = ActiveManifest.GetMainPackageBundle(bundleID);
return packageBundle.BundleName;
}
string IBundleQuery.GetMainBundleName(AssetInfo assetInfo) string IBundleQuery.GetMainBundleName(AssetInfo assetInfo)
{ {
if (assetInfo.IsInvalid) if (assetInfo.IsInvalid)

View File

@@ -318,9 +318,19 @@ namespace YooAsset
/// 强制回收所有资源 /// 强制回收所有资源
/// </summary> /// </summary>
public UnloadAllAssetsOperation UnloadAllAssetsAsync() public UnloadAllAssetsOperation UnloadAllAssetsAsync()
{
var options = new UnloadAllAssetsOptions();
return UnloadAllAssetsAsync(options);
}
/// <summary>
/// 强制回收所有资源
/// </summary>
/// <param name="options">卸载选项</param>
public UnloadAllAssetsOperation UnloadAllAssetsAsync(UnloadAllAssetsOptions options)
{ {
DebugCheckInitialize(); DebugCheckInitialize();
var operation = new UnloadAllAssetsOperation(_resourceManager); var operation = new UnloadAllAssetsOperation(_resourceManager, options);
OperationSystem.StartOperation(PackageName, operation); OperationSystem.StartOperation(PackageName, operation);
return operation; return operation;
} }

View File

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

View File

@@ -29,7 +29,7 @@ namespace YooAsset
/// <summary> /// <summary>
/// 清单文件格式版本 /// 清单文件格式版本
/// </summary> /// </summary>
public const string ManifestFileVersion = "2.2.5"; public const string ManifestFileVersion = "2.3.0";
/// <summary> /// <summary>

View File

@@ -222,6 +222,15 @@ namespace YooAsset
} }
OperationSystem.MaxTimeSlice = milliseconds; OperationSystem.MaxTimeSlice = milliseconds;
} }
/// <summary>
/// 设置异步系统参数,快速启动模式的开关
/// 注意:该模式默认开启
/// </summary>
public static void SetOperationSystemQuickStartMode(bool state)
{
OperationSystem.QuickStartMode = state;
}
#endregion #endregion
#region #region

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 879f2b393f883554899ab3345f0dc998
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,68 @@
#if UNITY_WEBGL && DOUYINMINIGAME
using System.IO;
using UnityEngine;
using UnityEngine.SceneManagement;
using TTSDK;
namespace YooAsset
{
internal class TTAssetBundleResult : BundleResult
{
private readonly IFileSystem _fileSystem;
private readonly PackageBundle _packageBundle;
private readonly AssetBundle _assetBundle;
public TTAssetBundleResult(IFileSystem fileSystem, PackageBundle packageBundle, AssetBundle assetBundle)
{
_fileSystem = fileSystem;
_packageBundle = packageBundle;
_assetBundle = assetBundle;
}
public override void UnloadBundleFile()
{
if (_assetBundle != null)
{
_assetBundle.TTUnload(true);
}
}
public override string GetBundleFilePath()
{
return _fileSystem.GetBundleFilePath(_packageBundle);
}
public override byte[] ReadBundleFileData()
{
return _fileSystem.ReadBundleFileData(_packageBundle);
}
public override string ReadBundleFileText()
{
return _fileSystem.ReadBundleFileText(_packageBundle);
}
public override FSLoadAssetOperation LoadAssetAsync(AssetInfo assetInfo)
{
var operation = new AssetBundleLoadAssetOperation(_packageBundle, _assetBundle, assetInfo);
OperationSystem.StartOperation(_fileSystem.PackageName, operation);
return operation;
}
public override FSLoadAllAssetsOperation LoadAllAssetsAsync(AssetInfo assetInfo)
{
var operation = new AssetBundleLoadAllAssetsOperation(_packageBundle, _assetBundle, assetInfo);
OperationSystem.StartOperation(_fileSystem.PackageName, operation);
return operation;
}
public override FSLoadSubAssetsOperation LoadSubAssetsAsync(AssetInfo assetInfo)
{
var operation = new AssetBundleLoadSubAssetsOperation(_packageBundle, _assetBundle, assetInfo);
OperationSystem.StartOperation(_fileSystem.PackageName, operation);
return operation;
}
public override FSLoadSceneOperation LoadSceneOperation(AssetInfo assetInfo, LoadSceneParameters loadParams, bool suspendLoad)
{
var operation = new AssetBundleLoadSceneOperation(assetInfo, loadParams, suspendLoad);
OperationSystem.StartOperation(_fileSystem.PackageName, operation);
return operation;
}
}
}
#endif

View File

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

View File

@@ -7,7 +7,7 @@ internal class TTFSDownloadFileOperation : DefaultDownloadFileOperation
{ {
private TiktokFileSystem _fileSystem; private TiktokFileSystem _fileSystem;
private ESteps _steps = ESteps.None; private ESteps _steps = ESteps.None;
internal TTFSDownloadFileOperation(TiktokFileSystem fileSystem, PackageBundle bundle, DownloadParam param) : base(bundle, param) internal TTFSDownloadFileOperation(TiktokFileSystem fileSystem, PackageBundle bundle, DownloadParam param) : base(bundle, param)
{ {
_fileSystem = fileSystem; _fileSystem = fileSystem;
@@ -84,7 +84,7 @@ internal class TTFSDownloadFileOperation : DefaultDownloadFileOperation
private void CreateWebRequest() private void CreateWebRequest()
{ {
//TODO : 抖音小游戏没有找到预下载方法 //TODO : 抖音小游戏没有找到预下载方法
_webRequest = UnityWebRequestAssetBundle.GetAssetBundle(_requestURL); _webRequest = UnityWebRequest.Get(_requestURL);
_webRequest.disposeDownloadHandlerOnDispose = true; _webRequest.disposeDownloadHandlerOnDispose = true;
_webRequest.SendWebRequest(); _webRequest.SendWebRequest();
} }

View File

@@ -3,16 +3,7 @@ using YooAsset;
internal partial class TTFSInitializeOperation : FSInitializeFileSystemOperation internal partial class TTFSInitializeOperation : FSInitializeFileSystemOperation
{ {
private enum ESteps
{
None,
RecordCacheFiles,
Done,
}
private readonly TiktokFileSystem _fileSystem; private readonly TiktokFileSystem _fileSystem;
private RecordTiktokCacheFilesOperation _recordTiktokCacheFilesOp;
private ESteps _steps = ESteps.None;
public TTFSInitializeOperation(TiktokFileSystem fileSystem) public TTFSInitializeOperation(TiktokFileSystem fileSystem)
{ {
@@ -20,36 +11,10 @@ internal partial class TTFSInitializeOperation : FSInitializeFileSystemOperation
} }
internal override void InternalOnStart() internal override void InternalOnStart()
{ {
_steps = ESteps.RecordCacheFiles; Status = EOperationStatus.Succeed;
} }
internal override void InternalOnUpdate() internal override void InternalOnUpdate()
{ {
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.RecordCacheFiles)
{
if (_recordTiktokCacheFilesOp == null)
{
_recordTiktokCacheFilesOp = new RecordTiktokCacheFilesOperation(_fileSystem);
OperationSystem.StartOperation(_fileSystem.PackageName, _recordTiktokCacheFilesOp);
}
if (_recordTiktokCacheFilesOp.IsDone == false)
return;
if (_recordTiktokCacheFilesOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _recordTiktokCacheFilesOp.Error;
}
}
} }
} }
#endif #endif

View File

@@ -2,20 +2,19 @@
using UnityEngine; using UnityEngine;
using UnityEngine.Networking; using UnityEngine.Networking;
using YooAsset; using YooAsset;
using TTSDK;
internal class TTFSLoadBundleOperation : FSLoadBundleOperation internal class TTFSLoadBundleOperation : FSLoadBundleOperation
{ {
private enum ESteps private enum ESteps
{ {
None, None,
LoadBundleFile, DownloadAssetBundle,
Done, Done,
} }
private readonly TiktokFileSystem _fileSystem; private readonly TiktokFileSystem _fileSystem;
private readonly PackageBundle _bundle; private readonly PackageBundle _bundle;
private UnityWebRequest _webRequest; private DownloadAssetBundleOperation _downloadAssetBundleOp;
private ESteps _steps = ESteps.None; private ESteps _steps = ESteps.None;
internal TTFSLoadBundleOperation(TiktokFileSystem fileSystem, PackageBundle bundle) internal TTFSLoadBundleOperation(TiktokFileSystem fileSystem, PackageBundle bundle)
@@ -25,41 +24,52 @@ internal class TTFSLoadBundleOperation : FSLoadBundleOperation
} }
internal override void InternalOnStart() internal override void InternalOnStart()
{ {
_steps = ESteps.LoadBundleFile; _steps = ESteps.DownloadAssetBundle;
} }
internal override void InternalOnUpdate() internal override void InternalOnUpdate()
{ {
if (_steps == ESteps.None || _steps == ESteps.Done) if (_steps == ESteps.None || _steps == ESteps.Done)
return; return;
if (_steps == ESteps.LoadBundleFile) if (_steps == ESteps.DownloadAssetBundle)
{ {
if (_webRequest == null) if (_downloadAssetBundleOp == null)
{ {
string mainURL = _fileSystem.RemoteServices.GetRemoteMainURL(_bundle.FileName); DownloadParam downloadParam = new DownloadParam(int.MaxValue, 60);
_webRequest = TTAssetBundle.GetAssetBundle(mainURL); downloadParam.MainURL = _fileSystem.RemoteServices.GetRemoteMainURL(_bundle.FileName); ;
_webRequest.SendWebRequest(); downloadParam.FallbackURL = _fileSystem.RemoteServices.GetRemoteFallbackURL(_bundle.FileName);
if (_bundle.Encrypted)
{
_downloadAssetBundleOp = new DownloadWebEncryptAssetBundleOperation(false, _fileSystem.DecryptionServices, _bundle, downloadParam);
OperationSystem.StartOperation(_fileSystem.PackageName, _downloadAssetBundleOp);
}
else
{
_downloadAssetBundleOp = new DownloadTiktokAssetBundleOperation(_bundle, downloadParam);
OperationSystem.StartOperation(_fileSystem.PackageName, _downloadAssetBundleOp);
}
} }
DownloadProgress = _webRequest.downloadProgress; DownloadProgress = _downloadAssetBundleOp.DownloadProgress;
DownloadedBytes = (long)_webRequest.downloadedBytes; DownloadedBytes = (long)_downloadAssetBundleOp.DownloadedBytes;
Progress = DownloadProgress; Progress = DownloadProgress;
if (_webRequest.isDone == false) if (_downloadAssetBundleOp.IsDone == false)
return; return;
if (CheckRequestResult()) if (_downloadAssetBundleOp.Status == EOperationStatus.Succeed)
{ {
var assetBundle = (_webRequest.downloadHandler as DownloadHandlerTTAssetBundle).assetBundle; var assetBundle = _downloadAssetBundleOp.Result;
if (assetBundle == null) if (assetBundle == null)
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Error = $"{nameof(DownloadHandlerTTAssetBundle)} loaded asset bundle is null !";
Status = EOperationStatus.Failed; Status = EOperationStatus.Failed;
Error = $"{nameof(DownloadAssetBundleOperation)} loaded asset bundle is null !";
} }
else else
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Result = new AssetBundleResult(_fileSystem, _bundle, assetBundle, null); Result = new TTAssetBundleResult(_fileSystem, _bundle, assetBundle);
Status = EOperationStatus.Succeed; Status = EOperationStatus.Succeed;
} }
} }
@@ -67,6 +77,7 @@ internal class TTFSLoadBundleOperation : FSLoadBundleOperation
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Failed; Status = EOperationStatus.Failed;
Error = _downloadAssetBundleOp.Error;
} }
} }
} }
@@ -82,31 +93,11 @@ internal class TTFSLoadBundleOperation : FSLoadBundleOperation
} }
public override void AbortDownloadOperation() public override void AbortDownloadOperation()
{ {
} if (_steps == ESteps.DownloadAssetBundle)
private bool CheckRequestResult()
{
#if UNITY_2020_3_OR_NEWER
if (_webRequest.result != UnityWebRequest.Result.Success)
{ {
Error = _webRequest.error; if (_downloadAssetBundleOp != null)
return false; _downloadAssetBundleOp.SetAbort();
} }
else
{
return true;
}
#else
if (_webRequest.isNetworkError || _webRequest.isHttpError)
{
Error = _webRequest.error;
return false;
}
else
{
return true;
}
#endif
} }
} }
#endif #endif

View File

@@ -0,0 +1,127 @@
#if UNITY_WEBGL && DOUYINMINIGAME
using UnityEngine;
using UnityEngine.Networking;
using TTSDK;
namespace YooAsset
{
internal class DownloadTiktokAssetBundleOperation : DownloadAssetBundleOperation
{
private ESteps _steps = ESteps.None;
internal DownloadTiktokAssetBundleOperation(PackageBundle bundle, DownloadParam param) : base(bundle, param)
{
}
internal override void InternalOnStart()
{
_steps = ESteps.CreateRequest;
}
internal override void InternalOnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
// 创建下载器
if (_steps == ESteps.CreateRequest)
{
// 获取请求地址
_requestURL = GetRequestURL();
// 重置变量
ResetRequestFiled();
// 创建下载器
CreateWebRequest();
_steps = ESteps.CheckRequest;
}
// 检测下载结果
if (_steps == ESteps.CheckRequest)
{
DownloadProgress = _webRequest.downloadProgress;
DownloadedBytes = (long)_webRequest.downloadedBytes;
Progress = DownloadProgress;
if (_webRequest.isDone == false)
{
//TODO 需要验证抖音插件请求器的下载进度
//CheckRequestTimeout();
return;
}
// 检查网络错误
if (CheckRequestResult())
{
var downloadHanlder = (DownloadHandlerTTAssetBundle)_webRequest.downloadHandler;
AssetBundle assetBundle = downloadHanlder.assetBundle;
if (assetBundle == null)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = "Download handler asset bundle object is null !";
}
else
{
_steps = ESteps.Done;
Result = assetBundle;
Status = EOperationStatus.Succeed;
//TODO 需要验证抖音插件请求器的下载进度
DownloadProgress = 1f;
DownloadedBytes = Bundle.FileSize;
Progress = 1f;
}
}
else
{
_steps = ESteps.TryAgain;
}
// 注意:最终释放请求器
DisposeWebRequest();
}
// 重新尝试下载
if (_steps == ESteps.TryAgain)
{
if (FailedTryAgain <= 0)
{
Status = EOperationStatus.Failed;
_steps = ESteps.Done;
YooLogger.Error(Error);
return;
}
_tryAgainTimer += Time.unscaledDeltaTime;
if (_tryAgainTimer > 1f)
{
FailedTryAgain--;
_steps = ESteps.CreateRequest;
YooLogger.Warning(Error);
}
}
}
internal override void InternalOnAbort()
{
_steps = ESteps.Done;
DisposeWebRequest();
}
private void CreateWebRequest()
{
_webRequest = TTAssetBundle.GetAssetBundle(_requestURL);
_webRequest.disposeDownloadHandlerOnDispose = true;
_webRequest.SendWebRequest();
}
private void DisposeWebRequest()
{
if (_webRequest != null)
{
//注意引擎底层会自动调用Abort方法
_webRequest.Dispose();
_webRequest = null;
}
}
}
}
#endif

View File

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

View File

@@ -1,57 +0,0 @@
#if UNITY_WEBGL && DOUYINMINIGAME
using YooAsset;
using TTSDK;
internal class RecordTiktokCacheFilesOperation : AsyncOperationBase
{
private enum ESteps
{
None,
RecordCacheFiles,
WaitResponse,
Done,
}
private readonly TiktokFileSystem _fileSystem;
private ESteps _steps = ESteps.None;
public RecordTiktokCacheFilesOperation(TiktokFileSystem fileSystem)
{
_fileSystem = fileSystem;
}
internal override void InternalOnStart()
{
_steps = ESteps.RecordCacheFiles;
}
internal override void InternalOnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.RecordCacheFiles)
{
_steps = ESteps.WaitResponse;
var fileSystemMgr = _fileSystem.GetFileSystemMgr();
var getSavedFileListParam = new GetSavedFileListParam();
getSavedFileListParam.success = (TTGetSavedFileListResponse response) =>
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
foreach (var fileInfo in response.fileList)
{
//TODO 需要确认存储文件为Bundle文件
_fileSystem.RecordBundleFile(fileInfo.filePath);
}
};
getSavedFileListParam.fail = (TTGetSavedFileListResponse response) =>
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = response.errMsg;
};
fileSystemMgr.GetSavedFileList(getSavedFileListParam);
}
}
}
#endif

View File

@@ -8,11 +8,20 @@ using System;
public static class TiktokFileSystemCreater public static class TiktokFileSystemCreater
{ {
public static FileSystemParameters CreateByteGameFileSystemParameters(IRemoteServices remoteServices, string packageRoot) public static FileSystemParameters CreateFileSystemParameters(string packageRoot, IRemoteServices remoteServices)
{ {
string fileSystemClass = $"{nameof(TiktokFileSystem)},YooAsset.RuntimeExtension"; string fileSystemClass = $"{nameof(TiktokFileSystem)},YooAsset.RuntimeExtension";
var fileSystemParams = new FileSystemParameters(fileSystemClass, packageRoot); var fileSystemParams = new FileSystemParameters(fileSystemClass, packageRoot);
fileSystemParams.AddParameter("REMOTE_SERVICES", remoteServices); fileSystemParams.AddParameter(FileSystemParametersDefine.REMOTE_SERVICES, remoteServices);
return fileSystemParams;
}
public static FileSystemParameters CreateFileSystemParameters(string packageRoot, IRemoteServices remoteServices, IWebDecryptionServices decryptionServices)
{
string fileSystemClass = $"{nameof(TiktokFileSystem)},YooAsset.RuntimeExtension";
var fileSystemParams = new FileSystemParameters(fileSystemClass, packageRoot);
fileSystemParams.AddParameter(FileSystemParametersDefine.REMOTE_SERVICES, remoteServices);
fileSystemParams.AddParameter(FileSystemParametersDefine.DECRYPTION_SERVICES, decryptionServices);
return fileSystemParams; return fileSystemParams;
} }
} }
@@ -53,8 +62,7 @@ internal class TiktokFileSystem : IFileSystem
} }
} }
private readonly HashSet<string> _recorders = new HashSet<string>(); private readonly Dictionary<string, string> _cacheFilePathMapping = new Dictionary<string, string>(10000);
private readonly Dictionary<string, string> _cacheFilePaths = new Dictionary<string, string>(10000);
private TTFileSystemManager _fileSystemMgr; private TTFileSystemManager _fileSystemMgr;
private string _ttCacheRoot = string.Empty; private string _ttCacheRoot = string.Empty;
@@ -81,7 +89,7 @@ internal class TiktokFileSystem : IFileSystem
{ {
get get
{ {
return _recorders.Count; return 0;
} }
} }
@@ -90,6 +98,11 @@ internal class TiktokFileSystem : IFileSystem
/// 自定义参数:远程服务接口 /// 自定义参数:远程服务接口
/// </summary> /// </summary>
public IRemoteServices RemoteServices { private set; get; } = null; public IRemoteServices RemoteServices { private set; get; } = null;
/// <summary>
/// 自定义参数:解密方法类
/// </summary>
public IWebDecryptionServices DecryptionServices { private set; get; }
#endregion #endregion
@@ -147,10 +160,14 @@ internal class TiktokFileSystem : IFileSystem
public virtual void SetParameter(string name, object value) public virtual void SetParameter(string name, object value)
{ {
if (name == "REMOTE_SERVICES") if (name == FileSystemParametersDefine.REMOTE_SERVICES)
{ {
RemoteServices = (IRemoteServices)value; RemoteServices = (IRemoteServices)value;
} }
else if (name == FileSystemParametersDefine.DECRYPTION_SERVICES)
{
DecryptionServices = (IWebDecryptionServices)value;
}
else else
{ {
YooLogger.Warning($"Invalid parameter : {name}"); YooLogger.Warning($"Invalid parameter : {name}");
@@ -185,8 +202,7 @@ internal class TiktokFileSystem : IFileSystem
} }
public virtual bool Exists(PackageBundle bundle) public virtual bool Exists(PackageBundle bundle)
{ {
string filePath = GetCacheFileLoadPath(bundle); return CheckCacheFileExist(bundle);
return _recorders.Contains(filePath);
} }
public virtual bool NeedDownload(PackageBundle bundle) public virtual bool NeedDownload(PackageBundle bundle)
{ {
@@ -210,19 +226,27 @@ internal class TiktokFileSystem : IFileSystem
} }
public virtual byte[] ReadBundleFileData(PackageBundle bundle) public virtual byte[] ReadBundleFileData(PackageBundle bundle)
{ {
string filePath = GetCacheFileLoadPath(bundle); if (CheckCacheFileExist(bundle))
if (CheckCacheFileExist(filePath)) {
string filePath = GetCacheFileLoadPath(bundle);
return _fileSystemMgr.ReadFileSync(filePath); return _fileSystemMgr.ReadFileSync(filePath);
}
else else
{
return Array.Empty<byte>(); return Array.Empty<byte>();
}
} }
public virtual string ReadBundleFileText(PackageBundle bundle) public virtual string ReadBundleFileText(PackageBundle bundle)
{ {
string filePath = GetCacheFileLoadPath(bundle); if (CheckCacheFileExist(bundle))
if (CheckCacheFileExist(filePath)) {
string filePath = GetCacheFileLoadPath(bundle);
return _fileSystemMgr.ReadFileSync(filePath, "utf8"); return _fileSystemMgr.ReadFileSync(filePath, "utf8");
}
else else
{
return string.Empty; return string.Empty;
}
} }
#region #region
@@ -230,56 +254,20 @@ internal class TiktokFileSystem : IFileSystem
{ {
return _fileSystemMgr; return _fileSystemMgr;
} }
public bool CheckCacheFileExist(string filePath) public bool CheckCacheFileExist(PackageBundle bundle)
{ {
return _fileSystemMgr.AccessSync(filePath); string url = RemoteServices.GetRemoteMainURL(bundle.FileName);
return _fileSystemMgr.IsUrlCached(url);
} }
private string GetCacheFileLoadPath(PackageBundle bundle) private string GetCacheFileLoadPath(PackageBundle bundle)
{ {
if (_cacheFilePaths.TryGetValue(bundle.BundleGUID, out string filePath) == false) if (_cacheFilePathMapping.TryGetValue(bundle.BundleGUID, out string filePath) == false)
{ {
filePath = _fileSystemMgr.GetLocalCachedPathForUrl(bundle.FileName); filePath = _fileSystemMgr.GetLocalCachedPathForUrl(bundle.FileName);
_cacheFilePaths.Add(bundle.BundleGUID, filePath); _cacheFilePathMapping.Add(bundle.BundleGUID, filePath);
} }
return filePath; return filePath;
} }
#endregion #endregion
#region
public List<string> GetAllRecords()
{
return _recorders.ToList();
}
public bool RecordBundleFile(string filePath)
{
if (_recorders.Contains(filePath))
{
YooLogger.Error($"{nameof(TiktokFileSystem)} has element : {filePath}");
return false;
}
_recorders.Add(filePath);
return true;
}
public void TryRecordBundle(PackageBundle bundle)
{
string filePath = GetCacheFileLoadPath(bundle);
if (_recorders.Contains(filePath) == false)
{
_recorders.Add(filePath);
}
}
public void ClearAllRecords()
{
_recorders.Clear();
}
public void ClearRecord(string filePath)
{
if (_recorders.Contains(filePath))
{
_recorders.Remove(filePath);
}
}
#endregion
} }
#endif #endif

View File

@@ -42,7 +42,6 @@ internal class WXFSClearAllBundleFilesOperation : FSClearCacheFilesOperation
YooLogger.Log("微信缓存清理成功!"); YooLogger.Log("微信缓存清理成功!");
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Succeed; Status = EOperationStatus.Succeed;
_fileSystem.ClearAllRecords();
} }
else else
{ {

View File

@@ -4,6 +4,7 @@ using System.IO;
using UnityEngine; using UnityEngine;
using YooAsset; using YooAsset;
using WeChatWASM; using WeChatWASM;
using static UnityEngine.Networking.UnityWebRequest;
internal class WXFSClearUnusedBundleFilesAsync : FSClearCacheFilesOperation internal class WXFSClearUnusedBundleFilesAsync : FSClearCacheFilesOperation
{ {
@@ -11,6 +12,7 @@ internal class WXFSClearUnusedBundleFilesAsync : FSClearCacheFilesOperation
{ {
None, None,
GetUnusedCacheFiles, GetUnusedCacheFiles,
WaitingSearch,
ClearUnusedCacheFiles, ClearUnusedCacheFiles,
Done, Done,
} }
@@ -37,20 +39,46 @@ internal class WXFSClearUnusedBundleFilesAsync : FSClearCacheFilesOperation
if (_steps == ESteps.GetUnusedCacheFiles) if (_steps == ESteps.GetUnusedCacheFiles)
{ {
_unusedCacheFiles = GetUnusedCacheFiles(); _steps = ESteps.WaitingSearch;
_unusedFileTotalCount = _unusedCacheFiles.Count;
_steps = ESteps.ClearUnusedCacheFiles; var fileSystemMgr = _fileSystem.GetFileSystemMgr();
YooLogger.Log($"Found unused cache files count : {_unusedFileTotalCount}"); var statOption = new WXStatOption();
statOption.path = _fileSystem.FileRoot;
statOption.recursive = true;
statOption.success = (WXStatResponse response) =>
{
foreach (var fileStat in response.stats)
{
// 注意存储文件必须按照Bundle文件哈希值存储
string bundleGUID = Path.GetFileNameWithoutExtension(fileStat.path);
if (_manifest.TryGetPackageBundleByBundleGUID(bundleGUID, out PackageBundle value) == false)
{
string fullPath = WX.GetCachePath(fileStat.path);
if (_unusedCacheFiles.Contains(fullPath) == false)
_unusedCacheFiles.Add(fullPath);
}
}
_steps = ESteps.ClearUnusedCacheFiles;
_unusedFileTotalCount = _unusedCacheFiles.Count;
YooLogger.Log($"Found unused cache files count : {_unusedFileTotalCount}");
};
statOption.fail = (WXStatResponse response) =>
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = response.errMsg;
};
fileSystemMgr.Stat(statOption);
} }
if (_steps == ESteps.ClearUnusedCacheFiles) if (_steps == ESteps.ClearUnusedCacheFiles)
{ {
for (int i = _unusedCacheFiles.Count - 1; i >= 0; i--) for (int i = _unusedCacheFiles.Count - 1; i >= 0; i--)
{ {
string clearFilePath = _unusedCacheFiles[i]; string filePath = _unusedCacheFiles[i];
_unusedCacheFiles.RemoveAt(i); _unusedCacheFiles.RemoveAt(i);
_fileSystem.ClearRecord(clearFilePath); WX.RemoveFile(filePath, null);
WX.RemoveFile(clearFilePath, null);
if (OperationSystem.IsBusy) if (OperationSystem.IsBusy)
break; break;
@@ -68,30 +96,5 @@ internal class WXFSClearUnusedBundleFilesAsync : FSClearCacheFilesOperation
} }
} }
} }
private List<string> GetUnusedCacheFiles()
{
var allRecords = _fileSystem.GetAllRecords();
List<string> result = new List<string>(allRecords.Count);
foreach (var filePath in allRecords)
{
// 如果存储文件名是按照Bundle文件哈希值存储
string bundleGUID = Path.GetFileNameWithoutExtension(filePath);
if (_manifest.TryGetPackageBundleByBundleGUID(bundleGUID, out PackageBundle value) == false)
{
result.Add(filePath);
}
// 如果存储文件名是按照Bundle文件名称存储
/*
string bundleName = Path.GetFileNameWithoutExtension(filePath);
if (_manifest.TryGetPackageBundleByBundleName(bundleName, out PackageBundle value) == false)
{
result.Add(filePath);
}
*/
}
return result;
}
} }
#endif #endif

View File

@@ -42,7 +42,9 @@ internal class WXFSDownloadFileOperation : DefaultDownloadFileOperation
Progress = DownloadProgress; Progress = DownloadProgress;
if (_webRequest.isDone == false) if (_webRequest.isDone == false)
{ {
CheckRequestTimeout(); //TODO 由于微信小游戏插件的问题,暂时不能判定超时!
// Issue : https://github.com/wechat-miniprogram/minigame-unity-webgl-transform/issues/108#
//CheckRequestTimeout();
return; return;
} }
@@ -51,7 +53,12 @@ internal class WXFSDownloadFileOperation : DefaultDownloadFileOperation
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Succeed; Status = EOperationStatus.Succeed;
_fileSystem.TryRecordBundle(Bundle); //记录下载文件
//TODO 解决微信小游戏插件问题
// Issue : https://github.com/wechat-miniprogram/minigame-unity-webgl-transform/issues/108#
DownloadProgress = 1f;
DownloadedBytes = Bundle.FileSize;
Progress = 1f;
} }
else else
{ {
@@ -85,7 +92,7 @@ internal class WXFSDownloadFileOperation : DefaultDownloadFileOperation
private void CreateWebRequest() private void CreateWebRequest()
{ {
_webRequest = WXAssetBundle.GetAssetBundle(_requestURL); _webRequest = UnityWebRequest.Get(_requestURL);
_webRequest.SetRequestHeader("wechatminigame-preload", "1"); _webRequest.SetRequestHeader("wechatminigame-preload", "1");
_webRequest.disposeDownloadHandlerOnDispose = true; _webRequest.disposeDownloadHandlerOnDispose = true;
_webRequest.SendWebRequest(); _webRequest.SendWebRequest();

View File

@@ -3,16 +3,7 @@ using YooAsset;
internal partial class WXFSInitializeOperation : FSInitializeFileSystemOperation internal partial class WXFSInitializeOperation : FSInitializeFileSystemOperation
{ {
private enum ESteps
{
None,
RecordCacheFiles,
Done,
}
private readonly WechatFileSystem _fileSystem; private readonly WechatFileSystem _fileSystem;
private RecordWechatCacheFilesOperation _recordWechatCacheFilesOp;
private ESteps _steps = ESteps.None;
public WXFSInitializeOperation(WechatFileSystem fileSystem) public WXFSInitializeOperation(WechatFileSystem fileSystem)
{ {
@@ -20,36 +11,10 @@ internal partial class WXFSInitializeOperation : FSInitializeFileSystemOperation
} }
internal override void InternalOnStart() internal override void InternalOnStart()
{ {
_steps = ESteps.RecordCacheFiles; Status = EOperationStatus.Succeed;
} }
internal override void InternalOnUpdate() internal override void InternalOnUpdate()
{ {
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.RecordCacheFiles)
{
if (_recordWechatCacheFilesOp == null)
{
_recordWechatCacheFilesOp = new RecordWechatCacheFilesOperation(_fileSystem);
OperationSystem.StartOperation(_fileSystem.PackageName, _recordWechatCacheFilesOp);
}
if (_recordWechatCacheFilesOp.IsDone == false)
return;
if (_recordWechatCacheFilesOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _recordWechatCacheFilesOp.Error;
}
}
} }
} }
#endif #endif

View File

@@ -1,21 +1,18 @@
#if UNITY_WEBGL && WEIXINMINIGAME #if UNITY_WEBGL && WEIXINMINIGAME
using UnityEngine;
using UnityEngine.Networking;
using YooAsset; using YooAsset;
using WeChatWASM;
internal class WXFSLoadBundleOperation : FSLoadBundleOperation internal class WXFSLoadBundleOperation : FSLoadBundleOperation
{ {
private enum ESteps private enum ESteps
{ {
None, None,
LoadBundleFile, DownloadAssetBundle,
Done, Done,
} }
private readonly WechatFileSystem _fileSystem; private readonly WechatFileSystem _fileSystem;
private readonly PackageBundle _bundle; private readonly PackageBundle _bundle;
private UnityWebRequest _webRequest; private DownloadAssetBundleOperation _downloadAssetBundleOp;
private ESteps _steps = ESteps.None; private ESteps _steps = ESteps.None;
internal WXFSLoadBundleOperation(WechatFileSystem fileSystem, PackageBundle bundle) internal WXFSLoadBundleOperation(WechatFileSystem fileSystem, PackageBundle bundle)
@@ -25,49 +22,60 @@ internal class WXFSLoadBundleOperation : FSLoadBundleOperation
} }
internal override void InternalOnStart() internal override void InternalOnStart()
{ {
_steps = ESteps.LoadBundleFile; _steps = ESteps.DownloadAssetBundle;
} }
internal override void InternalOnUpdate() internal override void InternalOnUpdate()
{ {
if (_steps == ESteps.None || _steps == ESteps.Done) if (_steps == ESteps.None || _steps == ESteps.Done)
return; return;
if (_steps == ESteps.LoadBundleFile) if (_steps == ESteps.DownloadAssetBundle)
{ {
if (_webRequest == null) if (_downloadAssetBundleOp == null)
{ {
string mainURL = _fileSystem.RemoteServices.GetRemoteMainURL(_bundle.FileName); DownloadParam downloadParam = new DownloadParam(int.MaxValue, 60);
_webRequest = WXAssetBundle.GetAssetBundle(mainURL); downloadParam.MainURL = _fileSystem.RemoteServices.GetRemoteMainURL(_bundle.FileName); ;
_webRequest.SendWebRequest(); downloadParam.FallbackURL = _fileSystem.RemoteServices.GetRemoteFallbackURL(_bundle.FileName);
if (_bundle.Encrypted)
{
_downloadAssetBundleOp = new DownloadWebEncryptAssetBundleOperation(false, _fileSystem.DecryptionServices, _bundle, downloadParam);
OperationSystem.StartOperation(_fileSystem.PackageName, _downloadAssetBundleOp);
}
else
{
_downloadAssetBundleOp = new DownloadWechatAssetBundleOperation(_bundle, downloadParam);
OperationSystem.StartOperation(_fileSystem.PackageName, _downloadAssetBundleOp);
}
} }
DownloadProgress = _webRequest.downloadProgress; DownloadProgress = _downloadAssetBundleOp.DownloadProgress;
DownloadedBytes = (long)_webRequest.downloadedBytes; DownloadedBytes = (long)_downloadAssetBundleOp.DownloadedBytes;
Progress = DownloadProgress; Progress = DownloadProgress;
if (_webRequest.isDone == false) if (_downloadAssetBundleOp.IsDone == false)
return; return;
if (CheckRequestResult()) if (_downloadAssetBundleOp.Status == EOperationStatus.Succeed)
{ {
var assetBundle = (_webRequest.downloadHandler as DownloadHandlerWXAssetBundle).assetBundle; var assetBundle = _downloadAssetBundleOp.Result;
if (assetBundle == null) if (assetBundle == null)
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Error = $"{nameof(DownloadHandlerWXAssetBundle)} loaded asset bundle is null !";
Status = EOperationStatus.Failed; Status = EOperationStatus.Failed;
Error = $"{nameof(DownloadAssetBundleOperation)} loaded asset bundle is null !";
} }
else else
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Result = new WXAssetBundleResult(_fileSystem, _bundle, assetBundle); Result = new WXAssetBundleResult(_fileSystem, _bundle, assetBundle);
Status = EOperationStatus.Succeed; Status = EOperationStatus.Succeed;
_fileSystem.TryRecordBundle(_bundle); //记录下载文件
} }
} }
else else
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Failed; Status = EOperationStatus.Failed;
Error = _downloadAssetBundleOp.Error;
} }
} }
} }
@@ -83,31 +91,11 @@ internal class WXFSLoadBundleOperation : FSLoadBundleOperation
} }
public override void AbortDownloadOperation() public override void AbortDownloadOperation()
{ {
} if (_steps == ESteps.DownloadAssetBundle)
private bool CheckRequestResult()
{
#if UNITY_2020_3_OR_NEWER
if (_webRequest.result != UnityWebRequest.Result.Success)
{ {
Error = _webRequest.error; if (_downloadAssetBundleOp != null)
return false; _downloadAssetBundleOp.SetAbort();
} }
else
{
return true;
}
#else
if (_webRequest.isNetworkError || _webRequest.isHttpError)
{
Error = _webRequest.error;
return false;
}
else
{
return true;
}
#endif
} }
} }
#endif #endif

View File

@@ -0,0 +1,129 @@
#if UNITY_WEBGL && WEIXINMINIGAME
using UnityEngine;
using UnityEngine.Networking;
using WeChatWASM;
namespace YooAsset
{
internal class DownloadWechatAssetBundleOperation : DownloadAssetBundleOperation
{
private ESteps _steps = ESteps.None;
internal DownloadWechatAssetBundleOperation(PackageBundle bundle, DownloadParam param) : base(bundle, param)
{
}
internal override void InternalOnStart()
{
_steps = ESteps.CreateRequest;
}
internal override void InternalOnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
// 创建下载器
if (_steps == ESteps.CreateRequest)
{
// 获取请求地址
_requestURL = GetRequestURL();
// 重置变量
ResetRequestFiled();
// 创建下载器
CreateWebRequest();
_steps = ESteps.CheckRequest;
}
// 检测下载结果
if (_steps == ESteps.CheckRequest)
{
DownloadProgress = _webRequest.downloadProgress;
DownloadedBytes = (long)_webRequest.downloadedBytes;
Progress = DownloadProgress;
if (_webRequest.isDone == false)
{
//TODO 由于微信小游戏插件的问题,暂时不能判定超时!
// Issue : https://github.com/wechat-miniprogram/minigame-unity-webgl-transform/issues/108#
//CheckRequestTimeout();
return;
}
// 检查网络错误
if (CheckRequestResult())
{
var downloadHanlder = (DownloadHandlerWXAssetBundle)_webRequest.downloadHandler;
AssetBundle assetBundle = downloadHanlder.assetBundle;
if (assetBundle == null)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = "Download handler asset bundle object is null !";
}
else
{
_steps = ESteps.Done;
Result = assetBundle;
Status = EOperationStatus.Succeed;
//TODO 解决微信小游戏插件问题
// Issue : https://github.com/wechat-miniprogram/minigame-unity-webgl-transform/issues/108#
DownloadProgress = 1f;
DownloadedBytes = Bundle.FileSize;
Progress = 1f;
}
}
else
{
_steps = ESteps.TryAgain;
}
// 注意:最终释放请求器
DisposeWebRequest();
}
// 重新尝试下载
if (_steps == ESteps.TryAgain)
{
if (FailedTryAgain <= 0)
{
Status = EOperationStatus.Failed;
_steps = ESteps.Done;
YooLogger.Error(Error);
return;
}
_tryAgainTimer += Time.unscaledDeltaTime;
if (_tryAgainTimer > 1f)
{
FailedTryAgain--;
_steps = ESteps.CreateRequest;
YooLogger.Warning(Error);
}
}
}
internal override void InternalOnAbort()
{
_steps = ESteps.Done;
DisposeWebRequest();
}
private void CreateWebRequest()
{
_webRequest = WXAssetBundle.GetAssetBundle(_requestURL);
_webRequest.disposeDownloadHandlerOnDispose = true;
_webRequest.SendWebRequest();
}
private void DisposeWebRequest()
{
if (_webRequest != null)
{
//注意引擎底层会自动调用Abort方法
_webRequest.Dispose();
_webRequest = null;
}
}
}
}
#endif

View File

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

View File

@@ -1,58 +0,0 @@
#if UNITY_WEBGL && WEIXINMINIGAME
using YooAsset;
using WeChatWASM;
using System.IO;
internal class RecordWechatCacheFilesOperation : AsyncOperationBase
{
private enum ESteps
{
None,
RecordCacheFiles,
WaitResponse,
Done,
}
private readonly WechatFileSystem _fileSystem;
private ESteps _steps = ESteps.None;
public RecordWechatCacheFilesOperation(WechatFileSystem fileSystem)
{
_fileSystem = fileSystem;
}
internal override void InternalOnStart()
{
_steps = ESteps.RecordCacheFiles;
}
internal override void InternalOnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.RecordCacheFiles)
{
_steps = ESteps.WaitResponse;
var fileSystemMgr = _fileSystem.GetFileSystemMgr();
var getSavedFileListOption = new GetSavedFileListOption();
getSavedFileListOption.success = (GetSavedFileListSuccessCallbackResult response) =>
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
foreach (var fileInfo in response.fileList)
{
//TODO 需要确认存储文件为Bundle文件
_fileSystem.RecordBundleFile(fileInfo.filePath);
}
};
getSavedFileListOption.fail = (FileError fileError) =>
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = fileError.errMsg;
};
fileSystemMgr.GetSavedFileList(getSavedFileListOption);
}
}
}
#endif

View File

@@ -8,11 +8,19 @@ using WeChatWASM;
public static class WechatFileSystemCreater public static class WechatFileSystemCreater
{ {
public static FileSystemParameters CreateWechatFileSystemParameters(IRemoteServices remoteServices, string packageRoot) public static FileSystemParameters CreateFileSystemParameters(string packageRoot, IRemoteServices remoteServices)
{ {
string fileSystemClass = $"{nameof(WechatFileSystem)},YooAsset.RuntimeExtension"; string fileSystemClass = $"{nameof(WechatFileSystem)},YooAsset.RuntimeExtension";
var fileSystemParams = new FileSystemParameters(fileSystemClass, packageRoot); var fileSystemParams = new FileSystemParameters(fileSystemClass, packageRoot);
fileSystemParams.AddParameter("REMOTE_SERVICES", remoteServices); fileSystemParams.AddParameter(FileSystemParametersDefine.REMOTE_SERVICES, remoteServices);
return fileSystemParams;
}
public static FileSystemParameters CreateFileSystemParameters(string packageRoot, IRemoteServices remoteServices, IWebDecryptionServices decryptionServices)
{
string fileSystemClass = $"{nameof(WechatFileSystem)},YooAsset.RuntimeExtension";
var fileSystemParams = new FileSystemParameters(fileSystemClass, packageRoot);
fileSystemParams.AddParameter(FileSystemParametersDefine.REMOTE_SERVICES, remoteServices);
fileSystemParams.AddParameter(FileSystemParametersDefine.DECRYPTION_SERVICES, decryptionServices);
return fileSystemParams; return fileSystemParams;
} }
} }
@@ -53,8 +61,7 @@ internal class WechatFileSystem : IFileSystem
} }
} }
private readonly HashSet<string> _recorders = new HashSet<string>(); private readonly Dictionary<string, string> _cacheFilePathMapping = new Dictionary<string, string>(10000);
private readonly Dictionary<string, string> _cacheFilePaths = new Dictionary<string, string>(10000);
private WXFileSystemManager _fileSystemMgr; private WXFileSystemManager _fileSystemMgr;
private string _wxCacheRoot = string.Empty; private string _wxCacheRoot = string.Empty;
@@ -63,6 +70,8 @@ internal class WechatFileSystem : IFileSystem
/// </summary> /// </summary>
public string PackageName { private set; get; } public string PackageName { private set; get; }
private readonly string _packageRoot = YooAssetSettingsData.Setting.DefaultYooFolderName;
/// <summary> /// <summary>
/// 文件根目录 /// 文件根目录
/// </summary> /// </summary>
@@ -81,7 +90,7 @@ internal class WechatFileSystem : IFileSystem
{ {
get get
{ {
return _recorders.Count; return 0;
} }
} }
@@ -90,6 +99,11 @@ internal class WechatFileSystem : IFileSystem
/// 自定义参数:远程服务接口 /// 自定义参数:远程服务接口
/// </summary> /// </summary>
public IRemoteServices RemoteServices { private set; get; } = null; public IRemoteServices RemoteServices { private set; get; } = null;
/// <summary>
/// 自定义参数:解密方法类
/// </summary>
public IWebDecryptionServices DecryptionServices { private set; get; }
#endregion #endregion
@@ -163,25 +177,34 @@ internal class WechatFileSystem : IFileSystem
public virtual void SetParameter(string name, object value) public virtual void SetParameter(string name, object value)
{ {
if (name == "REMOTE_SERVICES") if (name == FileSystemParametersDefine.REMOTE_SERVICES)
{ {
RemoteServices = (IRemoteServices)value; RemoteServices = (IRemoteServices)value;
} }
else if (name == FileSystemParametersDefine.DECRYPTION_SERVICES)
{
DecryptionServices = (IWebDecryptionServices)value;
}
else else
{ {
YooLogger.Warning($"Invalid parameter : {name}"); YooLogger.Warning($"Invalid parameter : {name}");
} }
} }
public virtual void OnCreate(string packageName, string rootDirectory) public virtual void OnCreate(string packageName, string packageRoot)
{ {
PackageName = packageName; PackageName = packageName;
_wxCacheRoot = rootDirectory; _wxCacheRoot = packageRoot;
if (string.IsNullOrEmpty(_wxCacheRoot)) if (string.IsNullOrEmpty(_wxCacheRoot))
{ {
throw new System.Exception("请配置微信小游戏缓存根目录!"); throw new System.Exception("请配置微信小游戏缓存根目录!");
} }
if (_wxCacheRoot.StartsWith(WX.PluginCachePath) == false)
{
_wxCacheRoot = PathUtility.Combine(WX.PluginCachePath, _wxCacheRoot);
}
// 注意CDN服务未启用的情况下使用微信WEB服务器 // 注意CDN服务未启用的情况下使用微信WEB服务器
if (RemoteServices == null) if (RemoteServices == null)
{ {
@@ -202,7 +225,7 @@ internal class WechatFileSystem : IFileSystem
public virtual bool Exists(PackageBundle bundle) public virtual bool Exists(PackageBundle bundle)
{ {
string filePath = GetCacheFileLoadPath(bundle); string filePath = GetCacheFileLoadPath(bundle);
return _recorders.Contains(filePath); return CheckCacheFileExist(filePath);
} }
public virtual bool NeedDownload(PackageBundle bundle) public virtual bool NeedDownload(PackageBundle bundle)
{ {
@@ -248,55 +271,21 @@ internal class WechatFileSystem : IFileSystem
} }
public bool CheckCacheFileExist(string filePath) public bool CheckCacheFileExist(string filePath)
{ {
string result = _fileSystemMgr.AccessSync(filePath); string result = WX.GetCachePath(filePath);
return result.Equals("access:ok"); if (string.IsNullOrEmpty(result))
return false;
else
return true;
} }
public string GetCacheFileLoadPath(PackageBundle bundle) public string GetCacheFileLoadPath(PackageBundle bundle)
{ {
if (_cacheFilePaths.TryGetValue(bundle.BundleGUID, out string filePath) == false) if (_cacheFilePathMapping.TryGetValue(bundle.BundleGUID, out string filePath) == false)
{ {
filePath = PathUtility.Combine(_wxCacheRoot, bundle.FileName); filePath = PathUtility.Combine(_wxCacheRoot, bundle.FileName);
_cacheFilePaths.Add(bundle.BundleGUID, filePath); _cacheFilePathMapping.Add(bundle.BundleGUID, filePath);
} }
return filePath; return filePath;
} }
#endregion #endregion
#region
public List<string> GetAllRecords()
{
return _recorders.ToList();
}
public bool RecordBundleFile(string filePath)
{
if (_recorders.Contains(filePath))
{
YooLogger.Error($"{nameof(WechatFileSystem)} has element : {filePath}");
return false;
}
_recorders.Add(filePath);
return true;
}
public void TryRecordBundle(PackageBundle bundle)
{
string filePath = GetCacheFileLoadPath(bundle);
if (_recorders.Contains(filePath) == false)
{
_recorders.Add(filePath);
}
}
public void ClearAllRecords()
{
_recorders.Clear();
}
public void ClearRecord(string filePath)
{
if (_recorders.Contains(filePath))
{
_recorders.Remove(filePath);
}
}
#endregion
} }
#endif #endif

View File

@@ -1,14 +1,12 @@
using System.Collections; #if UNITY_2019_4_OR_NEWER
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using UnityEngine; using UnityEngine;
using UnityEditor; using UnityEditor;
using YooAsset.Editor; using YooAsset.Editor;
#if UNITY_2019_4_OR_NEWER
using UnityEditor.UIElements; using UnityEditor.UIElements;
using UnityEngine.UIElements; using UnityEngine.UIElements;
#endif
[CreateAssetMenu(fileName = "TextureSchema", menuName = "YooAssetArt/Create TextureSchema")] [CreateAssetMenu(fileName = "TextureSchema", menuName = "YooAssetArt/Create TextureSchema")]
public class TextureSchema : ScannerSchema public class TextureSchema : ScannerSchema
@@ -23,6 +21,12 @@ public class TextureSchema : ScannerSchema
/// </summary> /// </summary>
public int MaxHeight = 1024; public int MaxHeight = 1024;
/// <summary>
/// 测试列表
/// </summary>
public List<string> TestStringValues = new List<string>();
/// <summary> /// <summary>
/// 获取用户指南信息 /// 获取用户指南信息
/// </summary> /// </summary>
@@ -37,9 +41,9 @@ public class TextureSchema : ScannerSchema
public override ScanReport RunScanner(AssetArtScanner scanner) public override ScanReport RunScanner(AssetArtScanner scanner)
{ {
// 创建扫描报告 // 创建扫描报告
string title = "扫描所有纹理资产"; string name = "扫描所有纹理资产";
string desc = GetUserGuide(); string desc = GetUserGuide();
var report = new ScanReport(title, desc); var report = new ScanReport(name, desc);
report.AddHeader("资源路径", 600, 500, 1000).SetStretchable().SetSearchable().SetSortable().SetHeaderType(EHeaderType.AssetPath); report.AddHeader("资源路径", 600, 500, 1000).SetStretchable().SetSearchable().SetSortable().SetHeaderType(EHeaderType.AssetPath);
report.AddHeader("图片宽度", 100).SetSortable().SetHeaderType(EHeaderType.LongValue); report.AddHeader("图片宽度", 100).SetSortable().SetHeaderType(EHeaderType.LongValue);
report.AddHeader("图片高度", 100).SetSortable().SetHeaderType(EHeaderType.LongValue); report.AddHeader("图片高度", 100).SetSortable().SetHeaderType(EHeaderType.LongValue);
@@ -105,9 +109,9 @@ public class TextureSchema : ScannerSchema
// 添加扫描信息 // 添加扫描信息
ReportElement result = new ReportElement(assetGUID); ReportElement result = new ReportElement(assetGUID);
result.AddScanInfo("资源路径", assetPath); result.AddScanInfo("资源路径", assetPath);
result.AddScanInfo("图片宽度", texture.width.ToString()); result.AddScanInfo("图片宽度", texture.width);
result.AddScanInfo("图片高度", texture.height.ToString()); result.AddScanInfo("图片高度", texture.height);
result.AddScanInfo("内存大小", memorySize.ToString()); result.AddScanInfo("内存大小", memorySize);
result.AddScanInfo("苹果格式", iosFormat.ToString()); result.AddScanInfo("苹果格式", iosFormat.ToString());
result.AddScanInfo("安卓格式", androidFormat.ToString()); result.AddScanInfo("安卓格式", androidFormat.ToString());
result.AddScanInfo("错误信息", errorInfo); result.AddScanInfo("错误信息", errorInfo);
@@ -157,7 +161,6 @@ public class TextureSchema : ScannerSchema
/// </summary> /// </summary>
public override SchemaInspector CreateInspector() public override SchemaInspector CreateInspector()
{ {
#if UNITY_2019_4_OR_NEWER
var container = new VisualElement(); var container = new VisualElement();
// 图片最大宽度 // 图片最大宽度
@@ -180,11 +183,16 @@ public class TextureSchema : ScannerSchema
}); });
container.Add(maxHeightField); container.Add(maxHeightField);
SchemaInspector inspector = new SchemaInspector(); // 创建测试列表
inspector.Containner = container; #if UNITY_2021_3_OR_NEWER
return inspector; ReorderableListView reorderableListView = new ReorderableListView();
#else reorderableListView.SourceData = TestStringValues;
return null; reorderableListView.HeaderName = "测试列表";
container.Add(reorderableListView);
#endif #endif
SchemaInspector inspector = new SchemaInspector(container);
return inspector;
} }
} }
#endif

View File

@@ -74,10 +74,11 @@ internal class FsmInitializePackage : IStateNode
#if UNITY_WEBGL && WEIXINMINIGAME && !UNITY_EDITOR #if UNITY_WEBGL && WEIXINMINIGAME && !UNITY_EDITOR
string defaultHostServer = GetHostServerURL(); string defaultHostServer = GetHostServerURL();
string fallbackHostServer = GetHostServerURL(); string fallbackHostServer = GetHostServerURL();
string packageRoot = $"{WeChatWASM.WX.env.USER_DATA_PATH}/__GAME_FILE_CACHE"; //注意:如果有子目录,请修改此处!
IRemoteServices remoteServices = new RemoteServices(defaultHostServer, fallbackHostServer); IRemoteServices remoteServices = new RemoteServices(defaultHostServer, fallbackHostServer);
createParameters.WebServerFileSystemParameters = WechatFileSystemCreater.CreateWechatFileSystemParameters(remoteServices); createParameters.WebServerFileSystemParameters = WechatFileSystemCreater.CreateFileSystemParameters(packageRoot, remoteServices);
#else #else
createParameters.WebServerFileSystemParameters = FileSystemParameters.CreateDefaultWebServerFileSystemParameters(); createParameters.WebServerFileSystemParameters = FileSystemParameters.CreateDefaultWebServerFileSystemParameters(new WebDecryption());
#endif #endif
initializationOperation = package.InitializeAsync(createParameters); initializationOperation = package.InitializeAsync(createParameters);
} }
@@ -148,4 +149,24 @@ internal class FsmInitializePackage : IStateNode
return $"{_fallbackHostServer}/{fileName}"; return $"{_fallbackHostServer}/{fileName}";
} }
} }
private class WebDecryption : IWebDecryptionServices
{
public const byte KEY = 64;
public WebDecryptResult LoadAssetBundle(WebDecryptFileInfo fileInfo)
{
byte[] copyData = new byte[fileInfo.FileData.Length];
Buffer.BlockCopy(fileInfo.FileData, 0, copyData, 0, fileInfo.FileData.Length);
for (int i = 0; i < copyData.Length; i++)
{
copyData[i] ^= KEY;
}
WebDecryptResult decryptResult = new WebDecryptResult();
decryptResult.Result = AssetBundle.LoadFromMemory(copyData);
return decryptResult;
}
}
} }

View File

@@ -14,3 +14,7 @@ MonoBehaviour:
m_EditorClassIdentifier: m_EditorClassIdentifier:
MaxWidth: 1024 MaxWidth: 1024
MaxHeight: 1024 MaxHeight: 1024
TestStringValues:
- test1
- test2
- test3

View File

@@ -4,6 +4,7 @@ using System.Text;
using UnityEngine; using UnityEngine;
using YooAsset; using YooAsset;
#region
/// <summary> /// <summary>
/// 资源文件解密流 /// 资源文件解密流
/// </summary> /// </summary>
@@ -29,6 +30,35 @@ public class BundleStream : FileStream
} }
} }
/// <summary>
/// 文件流加密方式
/// </summary>
public class FileStreamEncryption : IEncryptionServices
{
public EncryptResult Encrypt(EncryptFileInfo fileInfo)
{
if (fileInfo.BundleName.Contains("_gameres_audio"))
{
var fileData = File.ReadAllBytes(fileInfo.FileLoadPath);
for (int i = 0; i < fileData.Length; i++)
{
fileData[i] ^= BundleStream.KEY;
}
EncryptResult result = new EncryptResult();
result.Encrypted = true;
result.EncryptedData = fileData;
return result;
}
else
{
EncryptResult result = new EncryptResult();
result.Encrypted = false;
return result;
}
}
}
/// <summary> /// <summary>
/// 资源文件流加载解密类 /// 资源文件流加载解密类
/// </summary> /// </summary>
@@ -81,6 +111,37 @@ public class FileStreamDecryption : IDecryptionServices
return 1024; return 1024;
} }
} }
#endregion
#region
/// <summary>
/// 文件偏移加密方式
/// </summary>
public class FileOffsetEncryption : IEncryptionServices
{
public EncryptResult Encrypt(EncryptFileInfo fileInfo)
{
// 注意:只对音频资源包加密
if (fileInfo.BundleName.Contains("_gameres_audio"))
{
int offset = 32;
byte[] fileData = File.ReadAllBytes(fileInfo.FileLoadPath);
var encryptedData = new byte[fileData.Length + offset];
Buffer.BlockCopy(fileData, 0, encryptedData, offset, fileData.Length);
EncryptResult result = new EncryptResult();
result.Encrypted = true;
result.EncryptedData = encryptedData;
return result;
}
else
{
EncryptResult result = new EncryptResult();
result.Encrypted = false;
return result;
}
}
}
/// <summary> /// <summary>
/// 资源文件偏移加载解密类 /// 资源文件偏移加载解密类
@@ -132,61 +193,4 @@ public class FileOffsetDecryption : IDecryptionServices
return 32; return 32;
} }
} }
#endregion
/// <summary>
/// 文件偏移加密方式
/// </summary>
public class FileOffsetEncryption : IEncryptionServices
{
public EncryptResult Encrypt(EncryptFileInfo fileInfo)
{
// 注意:只对音频资源包加密
if (fileInfo.BundleName.Contains("_gameres_audio"))
{
int offset = 32;
byte[] fileData = File.ReadAllBytes(fileInfo.FileLoadPath);
var encryptedData = new byte[fileData.Length + offset];
Buffer.BlockCopy(fileData, 0, encryptedData, offset, fileData.Length);
EncryptResult result = new EncryptResult();
result.Encrypted = true;
result.EncryptedData = encryptedData;
return result;
}
else
{
EncryptResult result = new EncryptResult();
result.Encrypted = false;
return result;
}
}
}
/// <summary>
/// 文件流加密方式
/// </summary>
public class FileStreamEncryption : IEncryptionServices
{
public EncryptResult Encrypt(EncryptFileInfo fileInfo)
{
if (fileInfo.BundleName.Contains("_gameres_audio"))
{
var fileData = File.ReadAllBytes(fileInfo.FileLoadPath);
for (int i = 0; i < fileData.Length; i++)
{
fileData[i] ^= BundleStream.KEY;
}
EncryptResult result = new EncryptResult();
result.Encrypted = true;
result.EncryptedData = fileData;
return result;
}
else
{
EncryptResult result = new EncryptResult();
result.Encrypted = false;
return result;
}
}
}

View File

@@ -1,7 +1,7 @@
{ {
"name": "com.tuyoogame.yooasset", "name": "com.tuyoogame.yooasset",
"displayName": "YooAsset", "displayName": "YooAsset",
"version": "2.2.10", "version": "2.3.0-preview",
"unity": "2019.4", "unity": "2019.4",
"description": "unity3d resources management system.", "description": "unity3d resources management system.",
"author": { "author": {