Compare commits

...

23 Commits

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

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

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

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-26 00:01:48 +08:00
何冠峰
ea34be1f00 fix #646 2025-10-15 17:27:08 +08:00
何冠峰
831a9981e3 Update SearchCacheFilesOperation.cs 2025-10-14 16:58:06 +08:00
何冠峰
9de4aaa658 Merge pull request #656 from AlanLiu90/dev
优化SearchCacheFilesOperation
2025-10-14 16:43:07 +08:00
Alan Liu
3579a23bd5 优化SearchCacheFilesOperation 2025-10-13 18:55:49 +08:00
何冠峰
c865ddc7f2 feat #650 2025-10-10 10:20:02 +08:00
何冠峰
0bde506aec feat #648 2025-10-09 19:10:26 +08:00
何冠峰
15005b3d30 sample : 程序集宏支持
YOO_MACRO_SUPPORT开启扩展代码
2025-10-09 19:07:03 +08:00
何冠峰
4caf733ac6 fix #652 2025-10-09 16:17:44 +08:00
何冠峰
014b17f5cb feat #643 2025-10-09 16:14:31 +08:00
何冠峰
f3ebda0c04 refactor : 重构资源清单反序列化逻辑 2025-09-30 15:35:32 +08:00
何冠峰
5602addaca fix #645
修复极端情况下Shader变种收集不完整的问题
2025-09-24 16:37:46 +08:00
何冠峰
c4ae67aa8e perf: 资源扫描不再主动生成报告文件 2025-09-23 11:08:55 +08:00
何冠峰
bbcc3bf971 style : 修改代码注释说明 2025-09-19 10:05:45 +08:00
何冠峰
8b0e75b9b3 feat : 扩展Taptap小游戏文件类 2025-09-19 10:05:16 +08:00
54 changed files with 633 additions and 311 deletions

View File

@@ -2,6 +2,67 @@
All notable changes to this package will be documented in this file.
## [2.3.17] - 2025-10-30
**非常重要**:修复了#627优化导致的资源清单CRC值为空的问题
该问题会导致下载的损坏文件验证通过。
影响范围v2.3.15版本v2.3.16版本。
**非常重要**(#661) 修复了Package销毁过程中遇到正在加载的AssetBundle会导致无法卸载的问题。
该问题是偶现引擎会提示AssetBundle已经加载无法加载新的文件导致资源对象加载失败
影响范围:所有版本!
### Improvements
- 重构并统一了资源清单的反序列化逻辑。
### Fixed
- (#645) 修复了着色器变种收集工具,在极端情况下变种收集不完整的问题。
- (#646) 修复了EditorSimulateMode模式下开启模拟下载tag不生效的问题。
- (#667) 修复了所有编辑器窗口针对中文IME的输入问题。
- (#670) 修复了Catalog文件生成过程中白名单未考虑自定义清单前缀名。
### Improvements
- (#650) 解决互相依赖的资源包无法卸载的问题。需要开启宏定义YOOASSET_EXPERIMENTAL
- (#655) 优化了初始化的时候缓存文件搜索效率。安卓平台性能提升1倍IOS平台性能提升3倍。
### Added
- (#643) 新增构建参数,可以节省资源清单运行时内存
```csharp
class ScriptableBuildParameters
{
/// <summary>
/// 使用可寻址地址代替资源路径
/// 说明:开启此项可以节省运行时清单占用的内存!
/// </summary>
public bool ReplaceAssetPathWithAddress = false;
}
```
- (#648) 新增初始化参数,可以自动释放引用计数为零的资源包
```csharp
class InitializeParameters
{
/// <summary>
/// 当资源引用计数为零的时候自动释放资源包
/// </summary>
public bool AutoUnloadBundleWhenUnused = false;
}
```
### Changed
- 程序集宏定义代码转移到扩展工程。参考MacroSupport文件夹。
## [2.3.16] - 2025-09-17
### Improvements

View File

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

View File

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

View File

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

View File

@@ -96,12 +96,12 @@ namespace YooAsset.Editor
/// <summary>
/// 获取构建管线里需要的数据
/// </summary>
public UnityEditor.AssetBundleBuild[] GetPipelineBuilds()
public UnityEditor.AssetBundleBuild[] GetPipelineBuilds(bool replaceAssetPathWithAddres)
{
List<UnityEditor.AssetBundleBuild> builds = new List<UnityEditor.AssetBundleBuild>(_bundleInfoDic.Count);
foreach (var bundleInfo in _bundleInfoDic.Values)
{
builds.Add(bundleInfo.CreatePipelineBuild());
builds.Add(bundleInfo.CreatePipelineBuild(replaceAssetPathWithAddres));
}
return builds.ToArray();
}

View File

@@ -19,7 +19,7 @@ namespace YooAsset.Editor
/// <summary>
/// 创建补丁清单文件到输出目录
/// </summary>
protected void CreateManifestFile(bool processBundleDepends, bool processBundleTags, BuildContext context)
protected void CreateManifestFile(bool processBundleDepends, bool processBundleTags, bool replaceAssetPathWithAddress, BuildContext context)
{
var buildMapContext = context.GetContextObject<BuildMapContext>();
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
@@ -36,6 +36,7 @@ namespace YooAsset.Editor
manifest.SupportExtensionless = buildMapContext.Command.SupportExtensionless;
manifest.LocationToLower = buildMapContext.Command.LocationToLower;
manifest.IncludeAssetGUID = buildMapContext.Command.IncludeAssetGUID;
manifest.ReplaceAssetPathWithAddress = replaceAssetPathWithAddress;
manifest.OutputNameStyle = (int)buildParameters.FileNameStyle;
manifest.BuildBundleType = buildParameters.BuildBundleType;
manifest.BuildPipeline = buildParameters.BuildPipeline;
@@ -58,7 +59,13 @@ namespace YooAsset.Editor
// 4. 处理内置资源包
if (processBundleDepends)
{
// 注意:初始化资源清单建立引用关系
manifest.Initialize();
ProcessBuiltinBundleDependency(context, manifest);
}
// 创建资源清单文本文件
{
@@ -302,9 +309,6 @@ namespace YooAsset.Editor
#region YOOASSET_LEGACY_DEPENDENCY
private void ProcessBuiltinBundleDependency(BuildContext context, PackageManifest manifest)
{
// 注意:初始化资源清单建立引用关系
ManifestTools.InitManifest(manifest);
// 注意:如果是可编程构建管线,需要补充内置资源包
// 注意:该步骤依赖前面的操作!
var buildResultContext = context.TryGetContextObject<TaskBuilding_SBP.BuildResultContext>();

View File

@@ -54,6 +54,7 @@ namespace YooAsset.Editor
buildReport.Summary.CompressOption = builtinBuildParameters.CompressOption;
buildReport.Summary.DisableWriteTypeTree = builtinBuildParameters.DisableWriteTypeTree;
buildReport.Summary.IgnoreTypeTreeChanges = builtinBuildParameters.IgnoreTypeTreeChanges;
buildReport.Summary.ReplaceAssetPathWithAddress = builtinBuildParameters.ReplaceAssetPathWithAddress;
}
else if (buildParameters is ScriptableBuildParameters)
{
@@ -61,6 +62,7 @@ namespace YooAsset.Editor
buildReport.Summary.CompressOption = scriptableBuildParameters.CompressOption;
buildReport.Summary.DisableWriteTypeTree = scriptableBuildParameters.DisableWriteTypeTree;
buildReport.Summary.IgnoreTypeTreeChanges = scriptableBuildParameters.IgnoreTypeTreeChanges;
buildReport.Summary.ReplaceAssetPathWithAddress = scriptableBuildParameters.ReplaceAssetPathWithAddress;
buildReport.Summary.WriteLinkXML = scriptableBuildParameters.WriteLinkXML;
buildReport.Summary.CacheServerHost = scriptableBuildParameters.CacheServerHost;
buildReport.Summary.CacheServerPort = scriptableBuildParameters.CacheServerPort;

View File

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

View File

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

View File

@@ -27,6 +27,12 @@ namespace YooAsset.Editor
/// </summary>
public bool IgnoreTypeTreeChanges = true;
/// <summary>
/// 使用可寻址地址代替资源路径
/// 说明:开启此项可以节省运行时清单占用的内存!
/// </summary>
public bool ReplaceAssetPathWithAddress = false;
/// <summary>
/// 获取内置构建管线的构建选项

View File

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

View File

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

View File

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

View File

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

View File

@@ -29,6 +29,12 @@ namespace YooAsset.Editor
/// </summary>
public bool IgnoreTypeTreeChanges = true;
/// <summary>
/// 使用可寻址地址代替资源路径
/// 说明:开启此项可以节省运行时清单占用的内存!
/// </summary>
public bool ReplaceAssetPathWithAddress = false;
/// <summary>
/// 自动建立资源对象对图集的依赖关系
/// </summary>

View File

@@ -236,6 +236,7 @@ namespace YooAsset.Editor
// 包裹名称
_packageNameTxt = root.Q<TextField>("PackageName");
_packageNameTxt.isDelayed = true;
_packageNameTxt.RegisterValueChangedCallback(evt =>
{
var selectPackage = _packageListView.selectedItem as AssetBundleCollectorPackage;
@@ -249,6 +250,7 @@ namespace YooAsset.Editor
// 包裹备注
_packageDescTxt = root.Q<TextField>("PackageDesc");
_packageDescTxt.isDelayed = true;
_packageDescTxt.RegisterValueChangedCallback(evt =>
{
var selectPackage = _packageListView.selectedItem as AssetBundleCollectorPackage;
@@ -286,6 +288,7 @@ namespace YooAsset.Editor
// 分组名称
_groupNameTxt = root.Q<TextField>("GroupName");
_groupNameTxt.isDelayed = true;
_groupNameTxt.RegisterValueChangedCallback(evt =>
{
var selectPackage = _packageListView.selectedItem as AssetBundleCollectorPackage;
@@ -300,6 +303,7 @@ namespace YooAsset.Editor
// 分组备注
_groupDescTxt = root.Q<TextField>("GroupDesc");
_groupDescTxt.isDelayed = true;
_groupDescTxt.RegisterValueChangedCallback(evt =>
{
var selectPackage = _packageListView.selectedItem as AssetBundleCollectorPackage;
@@ -314,6 +318,7 @@ namespace YooAsset.Editor
// 分组的资源标签
_groupTagsTxt = root.Q<TextField>("GroupTags");
_groupTagsTxt.isDelayed = true;
_groupTagsTxt.RegisterValueChangedCallback(evt =>
{
var selectPackage = _packageListView.selectedItem as AssetBundleCollectorPackage;
@@ -817,6 +822,7 @@ namespace YooAsset.Editor
var textField = new TextField();
textField.name = "TextField0";
textField.label = "User Data";
textField.isDelayed = true;
textField.style.width = 200;
elementBottom.Add(textField);
var label = textField.Q<Label>();
@@ -826,6 +832,7 @@ namespace YooAsset.Editor
var textField = new TextField();
textField.name = "TextField1";
textField.label = "Asset Tags";
textField.isDelayed = true;
textField.style.width = 100;
textField.style.marginLeft = 20;
textField.style.flexGrow = 1;

View File

@@ -81,6 +81,7 @@ namespace YooAsset.Editor
public ECompressOption CompressOption;
public bool DisableWriteTypeTree;
public bool IgnoreTypeTreeChanges;
public bool ReplaceAssetPathWithAddress;
public bool WriteLinkXML = true;
public string CacheServerHost;
public int CacheServerPort;

View File

@@ -74,6 +74,7 @@ namespace YooAsset.Editor
BindListViewItem("CompressOption", $"{buildReport.Summary.CompressOption}");
BindListViewItem("DisableWriteTypeTree", $"{buildReport.Summary.DisableWriteTypeTree}");
BindListViewItem("IgnoreTypeTreeChanges", $"{buildReport.Summary.IgnoreTypeTreeChanges}");
BindListViewItem("ReplaceAssetPathWithAddress", $"{buildReport.Summary.ReplaceAssetPathWithAddress}");
BindListViewItem(string.Empty, string.Empty);
BindListViewHeader("Build Results");

View File

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

View File

@@ -90,7 +90,7 @@ namespace YooAsset
public string CopyBuildinPackageManifestDestRoot { private set; get; }
/// <summary>
/// 自定义参数:解密方法
/// 自定义参数:解密服务接口的实例
/// </summary>
public IDecryptionServices DecryptionServices { private set; get; }
@@ -100,7 +100,7 @@ namespace YooAsset
public IManifestRestoreServices ManifestServices { private set; get; }
/// <summary>
/// 自定义参数:拷贝内置文件服务
/// 自定义参数:拷贝内置文件接口的实例
/// </summary>
public ICopyLocalFileServices CopyLocalFileServices { private set; get; }
#endregion

View File

@@ -57,7 +57,7 @@ namespace YooAsset
#region
/// <summary>
/// 自定义参数:远程服务接口
/// 自定义参数:远程服务接口的实例类
/// </summary>
public IRemoteServices RemoteServices { private set; get; }
@@ -112,7 +112,7 @@ namespace YooAsset
public List<long> ResumeDownloadResponseCodes { private set; get; } = null;
/// <summary>
/// 自定义参数:解密方法
/// 自定义参数:解密服务接口的实例
/// </summary>
public IDecryptionServices DecryptionServices { private set; get; }
@@ -122,7 +122,7 @@ namespace YooAsset
public IManifestRestoreServices ManifestServices { private set; get; }
/// <summary>
/// 自定义参数:拷贝内置文件服务
/// 自定义参数:拷贝内置文件接口的实例
/// </summary>
public ICopyLocalFileServices CopyLocalFileServices { private set; get; }
#endregion

View File

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

View File

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

View File

@@ -8,6 +8,7 @@ namespace YooAsset
None,
CheckExist,
DownloadFile,
AbortDownload,
LoadAssetBundle,
CheckResult,
Done,
@@ -48,6 +49,17 @@ namespace YooAsset
}
}
if (_steps == ESteps.DownloadFile)
{
// 中断下载
if (AbortDownloadFile)
{
if (_downloadFileOp != null)
_downloadFileOp.AbortOperation();
_steps = ESteps.AbortDownload;
}
}
if (_steps == ESteps.DownloadFile)
{
if (_downloadFileOp == null)
@@ -79,6 +91,23 @@ namespace YooAsset
}
}
if (_steps == ESteps.AbortDownload)
{
if (_downloadFileOp != null)
{
if (IsWaitForAsyncComplete)
_downloadFileOp.WaitForAsyncComplete();
_downloadFileOp.UpdateOperation();
if (_downloadFileOp.IsDone == false)
return;
}
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = "Abort download file !";
}
if (_steps == ESteps.LoadAssetBundle)
{
if (IsWaitForAsyncComplete)

View File

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

View File

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

View File

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

View File

@@ -43,6 +43,11 @@ namespace YooAsset
/// </summary>
public int BundleLoadingMaxConcurrency = int.MaxValue;
/// <summary>
/// 当资源引用计数为零的时候自动释放资源包
/// </summary>
public bool AutoUnloadBundleWhenUnused = false;
/// <summary>
/// WebGL平台强制同步加载资源对象
/// </summary>

View File

@@ -36,6 +36,9 @@ namespace YooAsset
{
get
{
if (_watch == null)
return false;
// NOTE : 单次调用开销约1微秒
return _watch.ElapsedMilliseconds - _frameTime >= MaxTimeSlice;
}

View File

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

View File

@@ -173,6 +173,13 @@ namespace YooAsset
if (Result != null)
Result.UnloadBundleFile();
if (IsDone == false)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = "Bundle loader destroyed !";
}
}
/// <summary>
@@ -180,11 +187,7 @@ namespace YooAsset
/// </summary>
public bool CanDestroyLoader()
{
// 注意:正在加载中的任务不可以销毁
if (_steps == ESteps.LoadBundleFile)
return false;
if (RefCount > 0)
if (CanReleasableLoader() == false)
return false;
// YOOASSET_LEGACY_DEPENDENCY
@@ -194,14 +197,34 @@ namespace YooAsset
{
foreach (var bundleID in LoadBundleInfo.Bundle.ReferenceBundleIDs)
{
#if YOOASSET_EXPERIMENTAL
if (_resManager.CheckBundleReleasable(bundleID) == false)
return false;
#else
if (_resManager.CheckBundleDestroyed(bundleID) == false)
return false;
#endif
}
}
return true;
}
/// <summary>
/// 是否可以释放
/// </summary>
public bool CanReleasableLoader()
{
// 注意:正在加载中的任务不可以销毁
if (_steps == ESteps.LoadBundleFile)
return false;
if (RefCount > 0)
return false;
return true;
}
/// <summary>
/// 添加附属的资源提供者
/// </summary>
@@ -240,5 +263,28 @@ namespace YooAsset
_removeList.Clear();
}
}
/// <summary>
/// 尝试终止加载器
/// </summary>
public void TryAbortLoader()
{
if (IsDone == false)
{
if (_steps == ESteps.CheckConcurrency)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = "Abort bundle loader !";
}
if (_steps == ESteps.LoadBundleFile)
{
// 注意:终止下载器
if (_loadBundleOp != null)
_loadBundleOp.AbortDownloadFile = true;
}
}
}
}
}

View File

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

View File

@@ -308,6 +308,17 @@ namespace YooAsset
}
}
/// <summary>
/// 尝试卸载资源包
/// </summary>
public void TryUnloadBundle()
{
if (_resManager.AutoUnloadBundleWhenUnused)
{
_resManager.TryUnloadUnusedAsset(MainAssetInfo, 10);
}
}
/// <summary>
/// 结束流程
/// </summary>

View File

@@ -17,6 +17,7 @@ namespace YooAsset
private int _bundleLoadingMaxConcurrency;
// 开发者配置选项
public bool AutoUnloadBundleWhenUnused { private set; get; }
public bool WebGLForceSyncLoadAsset { private set; get; }
public bool UseWeakReferenceHandle { private set; get; }
@@ -47,6 +48,7 @@ namespace YooAsset
public void Initialize(InitializeParameters parameters, IBundleQuery bundleServices)
{
_bundleLoadingMaxConcurrency = parameters.BundleLoadingMaxConcurrency;
AutoUnloadBundleWhenUnused = parameters.AutoUnloadBundleWhenUnused;
WebGLForceSyncLoadAsset = parameters.WebGLForceSyncLoadAsset;
UseWeakReferenceHandle = parameters.UseWeakReferenceHandle;
_bundleQuery = bundleServices;
@@ -327,6 +329,14 @@ namespace YooAsset
return true;
return bundleFileLoader.IsDestroyed;
}
internal bool CheckBundleReleasable(int bundleID)
{
string bundleName = _bundleQuery.GetMainBundleName(bundleID);
var bundleFileLoader = TryGetBundleFileLoader(bundleName);
if (bundleFileLoader == null)
return true;
return bundleFileLoader.CanReleasableLoader();
}
internal bool HasAnyLoader()
{
return LoaderDic.Count > 0;

View File

@@ -16,6 +16,13 @@ namespace YooAsset
/// <summary>
/// 文件格式版本
/// </summary>
public const string FileVersion = "2025.8.28";
public const string FileVersion = "2025.9.30";
public const string VERSION_2025_8_28 = "2025.8.28";
public const string VERSION_2025_9_30 = "2025.9.30";
/// <summary>
/// 版本兼容
/// </summary>
public const bool BackwardCompatible = true;
}
}

View File

@@ -62,6 +62,7 @@ namespace YooAsset
buffer.WriteBool(manifest.SupportExtensionless);
buffer.WriteBool(manifest.LocationToLower);
buffer.WriteBool(manifest.IncludeAssetGUID);
buffer.WriteBool(manifest.ReplaceAssetPathWithAddress);
buffer.WriteInt32(manifest.OutputNameStyle);
buffer.WriteInt32(manifest.BuildBundleType);
buffer.WriteUTF8(manifest.BuildPipeline);
@@ -119,7 +120,18 @@ namespace YooAsset
/// </summary>
public static PackageManifest DeserializeFromJson(string jsonContent)
{
return JsonUtility.FromJson<PackageManifest>(jsonContent);
var manifest = JsonUtility.FromJson<PackageManifest>(jsonContent);
// 初始化资源包
for (int i = 0; i < manifest.BundleList.Count; i++)
{
var packageBundle = manifest.BundleList[i];
packageBundle.InitBundle(manifest);
}
// 初始化资源清单
manifest.Initialize();
return manifest;
}
/// <summary>
@@ -127,218 +139,12 @@ namespace YooAsset
/// </summary>
public static PackageManifest DeserializeFromBinary(byte[] binaryData, IManifestRestoreServices services)
{
// 创建缓存器
BufferReader buffer;
if (services != null)
{
var resultBytes = services.RestoreManifest(binaryData);
buffer = new BufferReader(resultBytes);
}
else
{
buffer = new BufferReader(binaryData);
}
// 读取文件标记
uint fileSign = buffer.ReadUInt32();
if (fileSign != ManifestDefine.FileSign)
throw new Exception("Invalid manifest file !");
// 读取文件版本
string fileVersion = buffer.ReadUTF8();
if (fileVersion != ManifestDefine.FileVersion)
throw new Exception($"The manifest file version are not compatible : {fileVersion} != {ManifestDefine.FileVersion}");
PackageManifest manifest = new PackageManifest();
{
// 读取文件头信息
manifest.FileVersion = fileVersion;
manifest.EnableAddressable = buffer.ReadBool();
manifest.SupportExtensionless = buffer.ReadBool();
manifest.LocationToLower = buffer.ReadBool();
manifest.IncludeAssetGUID = buffer.ReadBool();
manifest.OutputNameStyle = buffer.ReadInt32();
manifest.BuildBundleType = buffer.ReadInt32();
manifest.BuildPipeline = buffer.ReadUTF8();
manifest.PackageName = buffer.ReadUTF8();
manifest.PackageVersion = buffer.ReadUTF8();
manifest.PackageNote = buffer.ReadUTF8();
// 检测配置
if (manifest.EnableAddressable && manifest.LocationToLower)
throw new Exception("Addressable not support location to lower !");
// 读取资源列表
int packageAssetCount = buffer.ReadInt32();
CreateAssetCollection(manifest, packageAssetCount);
for (int i = 0; i < packageAssetCount; i++)
{
var packageAsset = new PackageAsset();
packageAsset.Address = buffer.ReadUTF8();
packageAsset.AssetPath = buffer.ReadUTF8();
packageAsset.AssetGUID = buffer.ReadUTF8();
packageAsset.AssetTags = buffer.ReadUTF8Array();
packageAsset.BundleID = buffer.ReadInt32();
packageAsset.DependBundleIDs = buffer.ReadInt32Array();
FillAssetCollection(manifest, packageAsset);
}
// 读取资源包列表
int packageBundleCount = buffer.ReadInt32();
CreateBundleCollection(manifest, packageBundleCount);
for (int i = 0; i < packageBundleCount; i++)
{
var packageBundle = new PackageBundle();
packageBundle.BundleName = buffer.ReadUTF8();
packageBundle.UnityCRC = buffer.ReadUInt32();
packageBundle.FileHash = buffer.ReadUTF8();
packageBundle.FileCRC = buffer.ReadUInt32();
packageBundle.FileSize = buffer.ReadInt64();
packageBundle.Encrypted = buffer.ReadBool();
packageBundle.Tags = buffer.ReadUTF8Array();
packageBundle.DependBundleIDs = buffer.ReadInt32Array();
FillBundleCollection(manifest, packageBundle);
}
}
// 初始化资源清单
InitManifest(manifest);
return manifest;
DeserializeManifestOperation operation = new DeserializeManifestOperation(services, binaryData);
operation.StartOperation();
operation.WaitForAsyncComplete();
return operation.Manifest;
}
#region
public static void InitManifest(PackageManifest manifest)
{
// 填充资源包内包含的主资源列表
foreach (var packageAsset in manifest.AssetList)
{
int bundleID = packageAsset.BundleID;
if (bundleID >= 0 && bundleID < manifest.BundleList.Count)
{
var packageBundle = manifest.BundleList[bundleID];
packageBundle.IncludeMainAssets.Add(packageAsset);
}
else
{
throw new Exception($"Invalid bundle id : {bundleID} Asset path : {packageAsset.AssetPath}");
}
}
// 填充资源包引用关系
for (int index = 0; index < manifest.BundleList.Count; index++)
{
var sourceBundle = manifest.BundleList[index];
foreach (int dependIndex in sourceBundle.DependBundleIDs)
{
var dependBundle = manifest.BundleList[dependIndex];
dependBundle.AddReferenceBundleID(index);
}
}
}
public static void CreateAssetCollection(PackageManifest manifest, int assetCount)
{
manifest.AssetList = new List<PackageAsset>(assetCount);
manifest.AssetDic = new Dictionary<string, PackageAsset>(assetCount);
if (manifest.EnableAddressable)
{
manifest.AssetPathMapping1 = new Dictionary<string, string>(assetCount * 3);
}
else
{
if (manifest.LocationToLower)
manifest.AssetPathMapping1 = new Dictionary<string, string>(assetCount * 2, StringComparer.OrdinalIgnoreCase);
else
manifest.AssetPathMapping1 = new Dictionary<string, string>(assetCount * 2);
}
if (manifest.IncludeAssetGUID)
manifest.AssetPathMapping2 = new Dictionary<string, string>(assetCount);
else
manifest.AssetPathMapping2 = new Dictionary<string, string>();
}
public static void FillAssetCollection(PackageManifest manifest, PackageAsset packageAsset)
{
// 添加到列表集合
manifest.AssetList.Add(packageAsset);
// 注意:我们不允许原始路径存在重名
string assetPath = packageAsset.AssetPath;
if (manifest.AssetDic.ContainsKey(assetPath))
throw new System.Exception($"AssetPath have existed : {assetPath}");
else
manifest.AssetDic.Add(assetPath, packageAsset);
// 填充AssetPathMapping1
{
string location = packageAsset.AssetPath;
// 添加原生路径的映射
if (manifest.AssetPathMapping1.ContainsKey(location))
throw new System.Exception($"Location have existed : {location}");
else
manifest.AssetPathMapping1.Add(location, packageAsset.AssetPath);
// 添加无后缀名路径的映射
if (manifest.SupportExtensionless)
{
string locationWithoutExtension = Path.ChangeExtension(location, null);
if (ReferenceEquals(location, locationWithoutExtension) == false)
{
if (manifest.AssetPathMapping1.ContainsKey(locationWithoutExtension))
YooLogger.Warning($"Location have existed : {locationWithoutExtension}");
else
manifest.AssetPathMapping1.Add(locationWithoutExtension, packageAsset.AssetPath);
}
}
}
// 添加可寻址地址
if (manifest.EnableAddressable)
{
string location = packageAsset.Address;
if (string.IsNullOrEmpty(location) == false)
{
if (manifest.AssetPathMapping1.ContainsKey(location))
throw new System.Exception($"Location have existed : {location}");
else
manifest.AssetPathMapping1.Add(location, packageAsset.AssetPath);
}
}
// 填充AssetPathMapping2
if (manifest.IncludeAssetGUID)
{
if (manifest.AssetPathMapping2.ContainsKey(packageAsset.AssetGUID))
throw new System.Exception($"AssetGUID have existed : {packageAsset.AssetGUID}");
else
manifest.AssetPathMapping2.Add(packageAsset.AssetGUID, packageAsset.AssetPath);
}
}
public static void CreateBundleCollection(PackageManifest manifest, int bundleCount)
{
manifest.BundleList = new List<PackageBundle>(bundleCount);
manifest.BundleDic1 = new Dictionary<string, PackageBundle>(bundleCount);
manifest.BundleDic2 = new Dictionary<string, PackageBundle>(bundleCount);
manifest.BundleDic3 = new Dictionary<string, PackageBundle>(bundleCount);
}
public static void FillBundleCollection(PackageManifest manifest, PackageBundle packageBundle)
{
// 初始化资源包
packageBundle.InitBundle(manifest);
// 添加到列表集合
manifest.BundleList.Add(packageBundle);
manifest.BundleDic1.Add(packageBundle.BundleName, packageBundle);
manifest.BundleDic2.Add(packageBundle.FileName, packageBundle);
manifest.BundleDic3.Add(packageBundle.BundleGUID, packageBundle);
}
#endregion
/// <summary>
/// 获取资源文件的后缀名
/// </summary>

View File

@@ -13,13 +13,15 @@ namespace YooAsset
}
private readonly ResourcePackage _resourcePackage;
private readonly UnloadAllAssetsOptions _options;
private UnloadAllAssetsOperation _unloadAllAssetsOp;
private ESteps _steps = ESteps.None;
public DestroyOperation(ResourcePackage resourcePackage)
public DestroyOperation(ResourcePackage resourcePackage, UnloadAllAssetsOptions options)
{
_resourcePackage = resourcePackage;
_options = options;
}
internal override void InternalStart()
@@ -64,7 +66,7 @@ namespace YooAsset
{
if (_unloadAllAssetsOp == null)
{
_unloadAllAssetsOp = _resourcePackage.UnloadAllAssetsAsync();
_unloadAllAssetsOp = _resourcePackage.UnloadAllAssetsAsync(_options);
_unloadAllAssetsOp.StartOperation();
AddChildOperation(_unloadAllAssetsOp);
}

View File

@@ -84,7 +84,10 @@ namespace YooAsset
// 读取文件版本
string fileVersion = _buffer.ReadUTF8();
if (fileVersion != ManifestDefine.FileVersion)
Version fileVer = new Version(fileVersion);
Version ver2025_8_28 = new Version(ManifestDefine.VERSION_2025_8_28);
Version ver2025_9_30 = new Version(ManifestDefine.VERSION_2025_9_30);
if (fileVer < ver2025_8_28)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
@@ -99,6 +102,10 @@ namespace YooAsset
Manifest.SupportExtensionless = _buffer.ReadBool();
Manifest.LocationToLower = _buffer.ReadBool();
Manifest.IncludeAssetGUID = _buffer.ReadBool();
if (fileVer >= ver2025_9_30)
Manifest.ReplaceAssetPathWithAddress = _buffer.ReadBool();
else
Manifest.ReplaceAssetPathWithAddress = false;
Manifest.OutputNameStyle = _buffer.ReadInt32();
Manifest.BuildBundleType = _buffer.ReadInt32();
Manifest.BuildPipeline = _buffer.ReadUTF8();
@@ -109,6 +116,8 @@ namespace YooAsset
// 检测配置
if (Manifest.EnableAddressable && Manifest.LocationToLower)
throw new System.Exception("Addressable not support location to lower !");
if (Manifest.EnableAddressable == false && Manifest.ReplaceAssetPathWithAddress)
throw new System.Exception("Replace asset path with address need enable Addressable !");
_steps = ESteps.PrepareAssetList;
}
@@ -117,26 +126,44 @@ namespace YooAsset
{
_packageAssetCount = _buffer.ReadInt32();
_progressTotalValue = _packageAssetCount;
ManifestTools.CreateAssetCollection(Manifest, _packageAssetCount);
CreateAssetCollection(Manifest, _packageAssetCount);
_steps = ESteps.DeserializeAssetList;
}
if (_steps == ESteps.DeserializeAssetList)
{
bool replaceAssetPath = false;
if (UnityEngine.Application.isPlaying)
{
if (Manifest.EnableAddressable && Manifest.ReplaceAssetPathWithAddress)
replaceAssetPath = true;
}
while (_packageAssetCount > 0)
{
var packageAsset = new PackageAsset();
packageAsset.Address = _buffer.ReadUTF8();
packageAsset.AssetPath = _buffer.ReadUTF8();
if (replaceAssetPath)
{
packageAsset.AssetPath = packageAsset.Address;
_buffer.SkipUTF8(); //跳过解析AssetPath
}
else
{
packageAsset.AssetPath = _buffer.ReadUTF8();
}
packageAsset.AssetGUID = _buffer.ReadUTF8();
packageAsset.AssetTags = _buffer.ReadUTF8Array();
packageAsset.BundleID = _buffer.ReadInt32();
packageAsset.DependBundleIDs = _buffer.ReadInt32Array();
ManifestTools.FillAssetCollection(Manifest, packageAsset);
FillAssetCollection(Manifest, packageAsset, replaceAssetPath);
_packageAssetCount--;
Progress = 1f - _packageAssetCount / _progressTotalValue;
if (OperationSystem.IsBusy)
break;
if (IsWaitForAsyncComplete == false)
{
if (OperationSystem.IsBusy)
break;
}
}
if (_packageAssetCount <= 0)
@@ -149,7 +176,7 @@ namespace YooAsset
{
_packageBundleCount = _buffer.ReadInt32();
_progressTotalValue = _packageBundleCount;
ManifestTools.CreateBundleCollection(Manifest, _packageBundleCount);
CreateBundleCollection(Manifest, _packageBundleCount);
_steps = ESteps.DeserializeBundleList;
}
if (_steps == ESteps.DeserializeBundleList)
@@ -165,12 +192,15 @@ namespace YooAsset
packageBundle.Encrypted = _buffer.ReadBool();
packageBundle.Tags = _buffer.ReadUTF8Array();
packageBundle.DependBundleIDs = _buffer.ReadInt32Array();
ManifestTools.FillBundleCollection(Manifest, packageBundle);
FillBundleCollection(Manifest, packageBundle);
_packageBundleCount--;
Progress = 1f - _packageBundleCount / _progressTotalValue;
if (OperationSystem.IsBusy)
break;
if (IsWaitForAsyncComplete == false)
{
if (OperationSystem.IsBusy)
break;
}
}
if (_packageBundleCount <= 0)
@@ -181,7 +211,7 @@ namespace YooAsset
if (_steps == ESteps.InitManifest)
{
ManifestTools.InitManifest(Manifest);
Manifest.Initialize();
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
@@ -194,5 +224,117 @@ namespace YooAsset
Error = e.Message;
}
}
internal override void InternalWaitForAsyncComplete()
{
while (true)
{
if (ExecuteWhileDone())
{
_steps = ESteps.Done;
break;
}
}
}
private void CreateAssetCollection(PackageManifest manifest, int assetCount)
{
manifest.AssetList = new List<PackageAsset>(assetCount);
manifest.AssetDic = new Dictionary<string, PackageAsset>(assetCount);
if (manifest.EnableAddressable)
{
manifest.AssetPathMapping1 = new Dictionary<string, string>(assetCount * 3);
}
else
{
if (manifest.LocationToLower)
manifest.AssetPathMapping1 = new Dictionary<string, string>(assetCount * 2, StringComparer.OrdinalIgnoreCase);
else
manifest.AssetPathMapping1 = new Dictionary<string, string>(assetCount * 2);
}
if (manifest.IncludeAssetGUID)
manifest.AssetPathMapping2 = new Dictionary<string, string>(assetCount);
else
manifest.AssetPathMapping2 = new Dictionary<string, string>();
}
private void FillAssetCollection(PackageManifest manifest, PackageAsset packageAsset, bool replaceAssetPath)
{
// 添加到列表集合
manifest.AssetList.Add(packageAsset);
// 注意:我们不允许原始路径存在重名
string assetPath = packageAsset.AssetPath;
if (manifest.AssetDic.ContainsKey(assetPath))
throw new System.Exception($"AssetPath have existed : {assetPath}");
else
manifest.AssetDic.Add(assetPath, packageAsset);
// 填充AssetPathMapping1
{
string location = packageAsset.AssetPath;
// 添加原生路径的映射
if (manifest.AssetPathMapping1.ContainsKey(location))
throw new System.Exception($"Location have existed : {location}");
else
manifest.AssetPathMapping1.Add(location, packageAsset.AssetPath);
// 添加无后缀名路径的映射
if (manifest.SupportExtensionless)
{
string locationWithoutExtension = Path.ChangeExtension(location, null);
if (ReferenceEquals(location, locationWithoutExtension) == false)
{
if (manifest.AssetPathMapping1.ContainsKey(locationWithoutExtension))
YooLogger.Warning($"Location have existed : {locationWithoutExtension}");
else
manifest.AssetPathMapping1.Add(locationWithoutExtension, packageAsset.AssetPath);
}
}
}
// 填充AssetPathMapping2
if (manifest.IncludeAssetGUID)
{
if (manifest.AssetPathMapping2.ContainsKey(packageAsset.AssetGUID))
throw new System.Exception($"AssetGUID have existed : {packageAsset.AssetGUID}");
else
manifest.AssetPathMapping2.Add(packageAsset.AssetGUID, packageAsset.AssetPath);
}
// 添加可寻址地址
if (manifest.EnableAddressable && replaceAssetPath == false)
{
string location = packageAsset.Address;
if (string.IsNullOrEmpty(location) == false)
{
if (manifest.AssetPathMapping1.ContainsKey(location))
throw new System.Exception($"Location have existed : {location}");
else
manifest.AssetPathMapping1.Add(location, packageAsset.AssetPath);
}
}
}
private void CreateBundleCollection(PackageManifest manifest, int bundleCount)
{
manifest.BundleList = new List<PackageBundle>(bundleCount);
manifest.BundleDic1 = new Dictionary<string, PackageBundle>(bundleCount);
manifest.BundleDic2 = new Dictionary<string, PackageBundle>(bundleCount);
manifest.BundleDic3 = new Dictionary<string, PackageBundle>(bundleCount);
}
private void FillBundleCollection(PackageManifest manifest, PackageBundle packageBundle)
{
// 初始化资源包
packageBundle.InitBundle(manifest);
// 添加到列表集合
manifest.BundleList.Add(packageBundle);
manifest.BundleDic1.Add(packageBundle.BundleName, packageBundle);
manifest.BundleDic2.Add(packageBundle.FileName, packageBundle);
manifest.BundleDic3.Add(packageBundle.BundleGUID, packageBundle);
}
}
}

View File

@@ -28,6 +28,11 @@ namespace YooAsset
/// </summary>
public bool IncludeAssetGUID;
/// <summary>
/// 使用可寻址地址代替资源路径
/// </summary>
public bool ReplaceAssetPathWithAddress;
/// <summary>
/// 文件名称样式
/// </summary>

View File

@@ -36,6 +36,11 @@ namespace YooAsset
/// </summary>
public bool IncludeAssetGUID;
/// <summary>
/// 使用可寻址地址代替资源路径
/// </summary>
public bool ReplaceAssetPathWithAddress;
/// <summary>
/// 文件名称样式
/// </summary>
@@ -113,6 +118,38 @@ namespace YooAsset
public Dictionary<string, PackageBundle> BundleDic3;
/// <summary>
/// 初始化资源清单
/// </summary>
public void Initialize()
{
// 填充资源包内包含的主资源列表
foreach (var packageAsset in AssetList)
{
int bundleID = packageAsset.BundleID;
if (bundleID >= 0 && bundleID < BundleList.Count)
{
var packageBundle = BundleList[bundleID];
packageBundle.IncludeMainAssets.Add(packageAsset);
}
else
{
throw new Exception($"Invalid bundle id : {bundleID} Asset path : {packageAsset.AssetPath}");
}
}
// 填充资源包引用关系
for (int index = 0; index < BundleList.Count; index++)
{
var sourceBundle = BundleList[index];
foreach (int dependIndex in sourceBundle.DependBundleIDs)
{
var dependBundle = BundleList[dependIndex];
dependBundle.AddReferenceBundleID(index);
}
}
}
/// <summary>
/// 获取包裹的详细信息
/// </summary>
@@ -124,6 +161,7 @@ namespace YooAsset
details.SupportExtensionless = SupportExtensionless;
details.LocationToLower = LocationToLower;
details.IncludeAssetGUID = IncludeAssetGUID;
details.ReplaceAssetPathWithAddress = ReplaceAssetPathWithAddress;
details.OutputNameStyle = OutputNameStyle;
details.BuildBundleType = BuildBundleType;
details.BuildPipeline = BuildPipeline;

View File

@@ -209,7 +209,10 @@ namespace YooAsset
/// </summary>
public DestroyOperation DestroyAsync()
{
var operation = new DestroyOperation(this);
var options = new UnloadAllAssetsOptions();
options.ReleaseAllHandles = true;
options.LockLoadOperation = true;
var operation = new DestroyOperation(this, options);
OperationSystem.StartOperation(null, operation);
return operation;
}

View File

@@ -120,6 +120,15 @@ namespace YooAsset
return (ulong)ReadInt64();
}
public void SkipUTF8()
{
ushort count = ReadUInt16();
if (count == 0)
return;
CheckReaderIndex(count);
_index += count;
}
public string ReadUTF8()
{
ushort count = ReadUInt16();

View File

@@ -76,13 +76,7 @@ namespace YooAsset
/// <summary>
/// Gets the computed hash value.
/// </summary>
public uint CRCValue
{
get
{
return _currentCrc;
}
}
public uint CRCValue { private set; get; }
/// <summary>
/// Initializes a new instance of the <see cref="CRC32Algorithm"/> class.
@@ -115,6 +109,8 @@ namespace YooAsset
/// </summary>
protected override byte[] HashFinal()
{
CRCValue = _currentCrc;
if (BitConverter.IsLittleEndian)
return new[] { (byte)_currentCrc, (byte)(_currentCrc >> 8), (byte)(_currentCrc >> 16), (byte)(_currentCrc >> 24) };
else

View File

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

View File

@@ -1,6 +1,6 @@
using System.Collections.Generic;
#if YOO_ASSET_EXPERIMENT
#if YOO_MACRO_SUPPORT
namespace YooAsset.Editor
{
public class MacroDefine

View File

@@ -5,7 +5,7 @@ using System.Text;
using System.Xml;
using UnityEditor;
#if YOO_ASSET_EXPERIMENT
#if YOO_MACRO_SUPPORT
namespace YooAsset.Editor
{
[InitializeOnLoad]

View File

@@ -6,7 +6,7 @@ using System.Xml;
using UnityEditor;
using UnityEngine;
#if YOO_ASSET_EXPERIMENT
#if YOO_MACRO_SUPPORT
namespace YooAsset.Editor.Experiment
{
[InitializeOnLoad]

View File

@@ -106,6 +106,9 @@ public static class ShaderVariantCollector
if (_steps == ESteps.CollectSleeping)
{
if (ShaderUtil.anythingCompiling)
return;
if (_elapsedTime.ElapsedMilliseconds > SleepMilliseconds)
{
DestroyAllSpheres();

View File

@@ -8,10 +8,20 @@ using TapTapMiniGame;
public static class TaptapFileSystemCreater
{
public static FileSystemParameters CreateFileSystemParameters(string packageRoot)
public static FileSystemParameters CreateFileSystemParameters(string packageRoot, IRemoteServices remoteServices)
{
string fileSystemClass = $"{nameof(TaptapFileSystem)},YooAsset.MiniGame";
var fileSystemParams = new FileSystemParameters(fileSystemClass, packageRoot);
fileSystemParams.AddParameter(FileSystemParametersDefine.REMOTE_SERVICES, remoteServices);
return fileSystemParams;
}
public static FileSystemParameters CreateFileSystemParameters(string packageRoot, IRemoteServices remoteServices, IWebDecryptionServices decryptionServices)
{
string fileSystemClass = $"{nameof(TaptapFileSystem)},YooAsset.MiniGame";
var fileSystemParams = new FileSystemParameters(fileSystemClass, packageRoot);
fileSystemParams.AddParameter(FileSystemParametersDefine.REMOTE_SERVICES, remoteServices);
fileSystemParams.AddParameter(FileSystemParametersDefine.DECRYPTION_SERVICES, decryptionServices);
return fileSystemParams;
}
}

View File

@@ -6,7 +6,6 @@
"GUID:5efd170ecd8084500bed5692932fe14e",
"GUID:bb21d6197862c4c3e863390dec9859a7",
"GUID:870f26a2ffa82429195df0861505c5d5",
"GUID:870f26a2ffa82429195df0861505c5d5",
"GUID:6921e41464907054da1a045ea64ca16f"
],
"includePlatforms": [],

View File

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