Compare commits

...

6 Commits

Author SHA1 Message Date
何冠峰
f627b5b59a Update CHANGELOG.md 2025-09-10 12:05:31 +08:00
何冠峰
549ec74519 Update CHANGELOG.md 2025-09-09 20:06:53 +08:00
何冠峰
247ee31348 Update package.json 2025-09-09 20:06:31 +08:00
何冠峰
90d3a53bc3 fix #631 2025-09-09 19:06:17 +08:00
何冠峰
19f1d67a61 feat : 弱引用资源句柄 2025-09-09 18:31:02 +08:00
何冠峰
a71c46d1c4 feat : 构建过程图集依赖计算增加开关 2025-09-08 19:00:55 +08:00
12 changed files with 256 additions and 34 deletions

View File

@@ -2,6 +2,106 @@
All notable changes to this package will be documented in this file.
## [2.3.15] - 2025-09-09
**重要**:升级了资源清单版本,不兼容老版本。建议重新提审安装包。
### Improvements
- 重构了UniTask扩展库的目录结构和说明文档。
- 重构了内置文件系统类的加载和拷贝逻辑,解决在一些特殊机型上遇到的偶发性拷贝失败问题。
- 增加了生成内置清单文件的窗口工具详情见扩展工程里CreateBuildinCatalog目录。
- 优化了异步操作系统的繁忙检测机制。
- (#621) 资源配置页面可以展示DependCollector和StaticCollector包含的文件列表内容。
- (#627) 优化了资源清单部分字段类型CRC字段从字符串类型调整为整形可以降低清单尺寸。
### Fixed
- 修复了构建页面扩展类缺少指定属性报错的问题。
- (#611) 修复了资源扫描器配置页面,修改备注信息后会丢失焦点的问题。
- (#622) 修复了纯鸿蒙系统读取内置加密文件失败的问题。
- (#620) 修复了LINUX系统URL地址转换失败的问题。
- (#631) 修复了NET 4.x程序集库Math.Clamp导致的编译错误。
### Added
- 新增了支持支付宝小游戏的文件系统扩展类。
- 新增了支持Taptap小游戏的文件系统扩展类。
- 新增了资源系统初始化参数UseWeakReferenceHandle
目前处于预览版可以在引擎设置页面开启宏YOOASSET_EXPERIMENTAL
```csharp
/// <summary>
/// 启用弱引用资源句柄
/// </summary>
public bool UseWeakReferenceHandle = false;
```
- 内置文件系统和缓存文件系统新增初始化参数FILE_VERIFY_MAX_CONCURRENCY
```csharp
/// <summary>
/// 自定义参数:初始化的时候缓存文件校验最大并发数
/// </summary>
public int FileVerifyMaxConcurrency { private set; get; }
```
- (#623) 内置构建管线新增构建参数StripUnityVersion
```csharp
/// <summary>
/// 从文件头里剥离Unity版本信息
/// </summary>
public bool StripUnityVersion = false;
```
- 可编程构建管线新增构建参数TrackSpriteAtlasDependencies
```csharp
/// <summary>
/// 自动建立资源对象对图集的依赖关系
/// </summary>
public bool TrackSpriteAtlasDependencies = false;
```
- (#617) 新增资源收集配置参数SupportExtensionless
在不需要模糊加载模式的前提下,关闭此选项,可以降低运行时内存大小。
该选项默认开启!
```csharp
public class CollectCommand
{
/// <summary>
/// 支持无后缀名的资源定位地址
/// </summary>
public bool SupportExtensionless { set; get; }
}
```
- (#625) 异步操作系统类新增监听方法。
```csharp
class OperationSystem
{
/// <summary>
/// 监听任务开始
/// </summary>
public static void RegisterStartCallback(Action<string, AsyncOperationBase> callback);
/// <summary>
/// 监听任务结束
/// </summary>
public static void RegisterFinishCallback(Action<string, AsyncOperationBase> callback);
}
```
## [2.3.14] - 2025-07-23
**重要****所有下载相关的超时参数timeout已更新判定逻辑**

View File

@@ -308,25 +308,34 @@ namespace YooAsset.Editor
// 注意:如果是可编程构建管线,需要补充内置资源包
// 注意:该步骤依赖前面的操作!
var buildResultContext = context.TryGetContextObject<TaskBuilding_SBP.BuildResultContext>();
if (buildResultContext != null)
{
ProcessBuiltinBundleReference(context, manifest, buildResultContext.BuiltinShadersBundleName);
ProcessBuiltinBundleReference(context, manifest, buildResultContext.MonoScriptsBundleName);
ProcessBuiltinBundleReference(manifest, buildResultContext.BuiltinShadersBundleName);
ProcessBuiltinBundleReference(manifest, buildResultContext.MonoScriptsBundleName);
// 注意:检测是否开启图集模式
// 说明:需要记录主资源对象对图集的依赖关系!
if (EditorSettings.spritePackerMode != SpritePackerMode.Disabled)
var buildParametersContext = context.TryGetContextObject<BuildParametersContext>();
var buildParameters = buildParametersContext.Parameters;
if (buildParameters is ScriptableBuildParameters scriptableBuildParameters)
{
var buildMapContext = context.GetContextObject<BuildMapContext>();
foreach (var spriteAtlasAsset in buildMapContext.SpriteAtlasAssetList)
if (scriptableBuildParameters.TrackSpriteAtlasDependencies)
{
string spriteAtlasBundleName = spriteAtlasAsset.BundleName;
ProcessBuiltinBundleReference(context, manifest, spriteAtlasBundleName);
// 注意:检测是否开启图集模式
// 说明:需要记录主资源对象对图集的依赖关系!
if (EditorSettings.spritePackerMode != SpritePackerMode.Disabled)
{
var buildMapContext = context.GetContextObject<BuildMapContext>();
foreach (var spriteAtlasAsset in buildMapContext.SpriteAtlasAssetList)
{
string spriteAtlasBundleName = spriteAtlasAsset.BundleName;
ProcessBuiltinBundleReference(manifest, spriteAtlasBundleName);
}
}
}
}
}
}
private void ProcessBuiltinBundleReference(BuildContext context, PackageManifest manifest, string builtinBundleName)
private void ProcessBuiltinBundleReference(PackageManifest manifest, string builtinBundleName)
{
if (string.IsNullOrEmpty(builtinBundleName))
return;

View File

@@ -29,6 +29,11 @@ namespace YooAsset.Editor
/// </summary>
public bool IgnoreTypeTreeChanges = true;
/// <summary>
/// 自动建立资源对象对图集的依赖关系
/// </summary>
public bool TrackSpriteAtlasDependencies = false;
/// <summary>
/// 生成代码防裁剪配置

View File

@@ -172,7 +172,7 @@ namespace YooAsset
else if (name == FileSystemParametersDefine.FILE_VERIFY_MAX_CONCURRENCY)
{
int convertValue = Convert.ToInt32(value);
FileVerifyMaxConcurrency = Math.Clamp(convertValue, 1, int.MaxValue);
FileVerifyMaxConcurrency = Mathf.Clamp(convertValue, 1, int.MaxValue);
}
else if (name == FileSystemParametersDefine.APPEND_FILE_EXTENSION)
{

View File

@@ -2,6 +2,7 @@
using System.IO;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace YooAsset
{
@@ -231,7 +232,7 @@ namespace YooAsset
else if (name == FileSystemParametersDefine.FILE_VERIFY_MAX_CONCURRENCY)
{
int convertValue = Convert.ToInt32(value);
FileVerifyMaxConcurrency = Math.Clamp(convertValue, 1, int.MaxValue);
FileVerifyMaxConcurrency = Mathf.Clamp(convertValue, 1, int.MaxValue);
}
else if (name == FileSystemParametersDefine.APPEND_FILE_EXTENSION)
{
@@ -244,12 +245,12 @@ namespace YooAsset
else if (name == FileSystemParametersDefine.DOWNLOAD_MAX_CONCURRENCY)
{
int convertValue = Convert.ToInt32(value);
DownloadMaxConcurrency = Math.Clamp(convertValue, 1, int.MaxValue);
DownloadMaxConcurrency = Mathf.Clamp(convertValue, 1, int.MaxValue);
}
else if (name == FileSystemParametersDefine.DOWNLOAD_MAX_REQUEST_PER_FRAME)
{
int convertValue = Convert.ToInt32(value);
DownloadMaxRequestPerFrame = Math.Clamp(convertValue, 1, int.MaxValue);
DownloadMaxRequestPerFrame = Mathf.Clamp(convertValue, 1, int.MaxValue);
}
else if (name == FileSystemParametersDefine.RESUME_DOWNLOAD_MINMUM_SIZE)
{

View File

@@ -47,6 +47,15 @@ namespace YooAsset
/// WebGL平台强制同步加载资源对象
/// </summary>
public bool WebGLForceSyncLoadAsset = false;
#if YOOASSET_EXPERIMENTAL
/// <summary>
/// 启用弱引用资源句柄
/// </summary>
public bool UseWeakReferenceHandle = false;
#else
internal bool UseWeakReferenceHandle = false;
#endif
}
/// <summary>

View File

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

View File

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

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System;
namespace YooAsset
{
@@ -72,6 +73,7 @@ namespace YooAsset
private readonly LoadBundleFileOperation _mainBundleLoader;
private readonly List<LoadBundleFileOperation> _bundleLoaders = new List<LoadBundleFileOperation>(10);
private readonly HashSet<HandleBase> _handles = new HashSet<HandleBase>();
private readonly LinkedList<WeakReference<HandleBase>> _weakReferences = new LinkedList<WeakReference<HandleBase>>();
public ProviderOperation(ResourceManager manager, string providerGUID, AssetInfo assetInfo)
{
@@ -210,6 +212,11 @@ namespace YooAsset
if (_steps == ESteps.ProcessBundleResult)
return false;
if (_resManager.UseWeakReferenceHandle)
{
TryCleanupWeakReference();
}
return RefCount <= 0;
}
@@ -222,7 +229,15 @@ namespace YooAsset
RefCount++;
HandleBase handle = HandleFactory.CreateHandle(this, typeof(T));
_handles.Add(handle);
if (_resManager.UseWeakReferenceHandle)
{
var weakRef = new WeakReference<HandleBase>(handle);
_weakReferences.AddLast(weakRef);
}
else
{
_handles.Add(handle);
}
return handle as T;
}
@@ -234,8 +249,16 @@ namespace YooAsset
if (RefCount <= 0)
throw new System.Exception("Should never get here !");
if (_handles.Remove(handle) == false)
throw new System.Exception("Should never get here !");
if (_resManager.UseWeakReferenceHandle)
{
if (RemoveWeakReference(handle) == false)
throw new System.Exception("Should never get here !");
}
else
{
if (_handles.Remove(handle) == false)
throw new System.Exception("Should never get here !");
}
// 引用计数减少
RefCount--;
@@ -246,10 +269,24 @@ namespace YooAsset
/// </summary>
public void ReleaseAllHandles()
{
List<HandleBase> tempers = _handles.ToList();
foreach (var handle in tempers)
if (_resManager.UseWeakReferenceHandle)
{
handle.Release();
List<WeakReference<HandleBase>> tempers = _weakReferences.ToList();
foreach (var weakRef in tempers)
{
if (weakRef.TryGetTarget(out HandleBase target))
{
target.Release();
}
}
}
else
{
List<HandleBase> tempers = _handles.ToList();
foreach (var handle in tempers)
{
handle.Release();
}
}
}
@@ -264,12 +301,29 @@ namespace YooAsset
// 注意:创建临时列表是为了防止外部逻辑在回调函数内创建或者释放资源句柄。
// 注意:回调方法如果发生异常,会阻断列表里的后续回调方法!
List<HandleBase> tempers = _handles.ToList();
foreach (var hande in tempers)
if (_resManager.UseWeakReferenceHandle)
{
if (hande.IsValid)
List<WeakReference<HandleBase>> tempers = _weakReferences.ToList();
foreach (var weakRef in tempers)
{
hande.InvokeCallback();
if (weakRef.TryGetTarget(out HandleBase target))
{
if (target.IsValid)
{
target.InvokeCallback();
}
}
}
}
else
{
List<HandleBase> tempers = _handles.ToList();
foreach (var handle in tempers)
{
if (handle.IsValid)
{
handle.InvokeCallback();
}
}
}
}
@@ -294,6 +348,50 @@ namespace YooAsset
return status;
}
/// <summary>
/// 移除指定句柄的弱引用对象
/// </summary>
private bool RemoveWeakReference(HandleBase handle)
{
bool removed = false;
var currentNode = _weakReferences.First;
while (currentNode != null)
{
var nextNode = currentNode.Next;
if (currentNode.Value.TryGetTarget(out HandleBase target))
{
if (ReferenceEquals(target, handle))
{
_weakReferences.Remove(currentNode);
removed = true;
break;
}
}
currentNode = nextNode;
}
return removed;
}
/// <summary>
/// 清理所有失效的弱引用
/// </summary>
private void TryCleanupWeakReference()
{
var currentNode = _weakReferences.First;
while (currentNode != null)
{
var nextNode = currentNode.Next;
if (currentNode.Value.TryGetTarget(out HandleBase target) == false)
{
_weakReferences.Remove(currentNode);
// 引用计数减少
RefCount--;
}
currentNode = nextNode;
}
}
#region
/// <summary>
/// 出生的场景

View File

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

View File

@@ -15,7 +15,10 @@ namespace YooAsset
private long _sceneCreateIndex = 0;
private IBundleQuery _bundleQuery;
private int _bundleLoadingMaxConcurrency;
private bool _webGLForceSyncLoadAsset;
// 开发者配置选项
public bool WebGLForceSyncLoadAsset { private set; get; }
public bool UseWeakReferenceHandle { private set; get; }
/// <summary>
/// 所属包裹
@@ -44,7 +47,8 @@ namespace YooAsset
public void Initialize(InitializeParameters parameters, IBundleQuery bundleServices)
{
_bundleLoadingMaxConcurrency = parameters.BundleLoadingMaxConcurrency;
_webGLForceSyncLoadAsset = parameters.WebGLForceSyncLoadAsset;
WebGLForceSyncLoadAsset = parameters.WebGLForceSyncLoadAsset;
UseWeakReferenceHandle = parameters.UseWeakReferenceHandle;
_bundleQuery = bundleServices;
SceneManager.sceneUnloaded += OnSceneUnloaded;
}
@@ -331,10 +335,6 @@ namespace YooAsset
{
return BundleLoadingCounter >= _bundleLoadingMaxConcurrency;
}
internal bool WebGLForceSyncLoadAsset()
{
return _webGLForceSyncLoadAsset;
}
private LoadBundleFileOperation CreateBundleFileLoaderInternal(BundleInfo bundleInfo)
{

View File

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