Compare commits

..

13 Commits
2.3.6 ... 2.3.7

Author SHA1 Message Date
何冠峰
9fb7f8bbfe Update CHANGELOG.md 2025-04-01 14:20:52 +08:00
何冠峰
b0382afad0 Update package.json 2025-04-01 14:20:46 +08:00
何冠峰
1ab7689174 fix #524
新增初始化参数 BundleLoadingMaxConcurrency
2025-04-01 11:44:10 +08:00
何冠峰
29d456c065 fix #523 2025-04-01 10:22:01 +08:00
何冠峰
b0dc829b04 fix #515
资源路径大小写不敏感逻辑优化
2025-03-31 19:06:03 +08:00
何冠峰
b3ead90832 fix #526 2025-03-31 18:13:07 +08:00
何冠峰
7bf00d4ff6 update space shooter 2025-03-31 17:28:10 +08:00
何冠峰
030e94d8ff update test sample 2025-03-31 17:27:58 +08:00
何冠峰
cf05254121 fix #519
FileSystemParametersDefine新增参数:INSTALL_CLEAR_MODE
2025-03-31 17:26:46 +08:00
何冠峰
3f786bca3b Merge branch 'dev' of https://github.com/tuyoogame/YooAsset into dev 2025-03-26 15:12:04 +08:00
何冠峰
98719d212f Merge pull request #520 from SongQQQ/fix-UWPError
修复了UWP平台报错
2025-03-26 14:35:24 +08:00
SONG\11700
3409f7ce4d 修复了UWP平台报错 2025-03-26 12:07:59 +08:00
何冠峰
f57b354e9b fix : UWP平台的适配问题。
修复UWP平台获取WWW加载路径未适配的问题。
2025-03-26 11:45:50 +08:00
27 changed files with 269 additions and 45 deletions

View File

@@ -2,6 +2,62 @@
All notable changes to this package will be documented in this file.
## [2.3.7] - 2025-04-01
### Improvements
- (#526) 运行时资源清单的哈希值验证兼容了MD5和CRC32两种方式。
- (#515) 优化了资源路径大小写不敏感的逻辑代码减少字符串操作产生的GC。
- (#523) UnloadUnusedAssetsOperation方法支持了分帧处理。
### Fixed
- (#520) 修复了UWP平台获取WWW加载路径未适配的问题。
### Added
- 新增了文件系统初始化参数INSTALL_CLEAR_MODE
```csharp
/// <summary>
/// 覆盖安装清理模式
/// </summary>
public enum EOverwriteInstallClearMode
{
/// <summary>
/// 不做任何处理
/// </summary>
None = 0,
/// <summary>
/// 清理所有缓存文件(包含资源文件和清单文件)
/// </summary>
ClearAllCacheFiles = 1,
/// <summary>
/// 清理所有缓存的资源文件
/// </summary>
ClearAllBundleFiles = 2,
/// <summary>
/// 清理所有缓存的清单文件
/// </summary>
ClearAllManifestFiles = 3,
}
```
- 新增了初始化参数BundleLoadingMaxConcurrency
```csharp
public abstract class InitializeParameters
{
/// <summary>
/// 同时加载Bundle文件的最大并发数
/// </summary>
public int BundleLoadingMaxConcurrency = int.MaxValue;
}
```
## [2.3.6] - 2025-03-25
### Improvements

View File

@@ -67,7 +67,7 @@ namespace YooAsset
}
#elif UNITY_STANDALONE_OSX
url = new System.Uri(path).ToString();
#elif UNITY_STANDALONE
#elif UNITY_STANDALONE || UNITY_WSA
url = StringUtility.Format("file:///{0}", path);
#else
throw new System.NotImplementedException();

View File

@@ -58,6 +58,11 @@ namespace YooAsset
/// </summary>
public EFileVerifyLevel FileVerifyLevel { private set; get; } = EFileVerifyLevel.Middle;
/// <summary>
/// 自定义参数:覆盖安装缓存清理模式
/// </summary>
public EOverwriteInstallClearMode InstallClearMode { private set; get; } = EOverwriteInstallClearMode.ClearAllManifestFiles;
/// <summary>
/// 自定义参数:数据文件追加文件格式
/// </summary>
@@ -145,6 +150,10 @@ namespace YooAsset
{
FileVerifyLevel = (EFileVerifyLevel)value;
}
else if (name == FileSystemParametersDefine.INSTALL_CLEAR_MODE)
{
InstallClearMode = (EOverwriteInstallClearMode)value;
}
else if (name == FileSystemParametersDefine.APPEND_FILE_EXTENSION)
{
AppendFileExtension = Convert.ToBoolean(value);
@@ -184,6 +193,7 @@ namespace YooAsset
_unpackFileSystem = new DefaultUnpackFileSystem();
_unpackFileSystem.SetParameter(FileSystemParametersDefine.REMOTE_SERVICES, remoteServices);
_unpackFileSystem.SetParameter(FileSystemParametersDefine.FILE_VERIFY_LEVEL, FileVerifyLevel);
_unpackFileSystem.SetParameter(FileSystemParametersDefine.INSTALL_CLEAR_MODE, InstallClearMode);
_unpackFileSystem.SetParameter(FileSystemParametersDefine.APPEND_FILE_EXTENSION, AppendFileExtension);
_unpackFileSystem.SetParameter(FileSystemParametersDefine.DECRYPTION_SERVICES, DecryptionServices);
_unpackFileSystem.OnCreate(packageName, null);

View File

@@ -69,8 +69,7 @@ namespace YooAsset
if (_steps == ESteps.VerifyFileData)
{
string fileHash = HashUtility.BytesCRC32(_webDataRequestOp.Result);
if (fileHash == _packageHash)
if (ManifestTools.VerifyManifestData(_webDataRequestOp.Result, _packageHash))
{
_steps = ESteps.LoadManifest;
}

View File

@@ -65,6 +65,11 @@ namespace YooAsset
/// </summary>
public EFileVerifyLevel FileVerifyLevel { private set; get; } = EFileVerifyLevel.Middle;
/// <summary>
/// 自定义参数:覆盖安装缓存清理模式
/// </summary>
public EOverwriteInstallClearMode InstallClearMode { private set; get; } = EOverwriteInstallClearMode.ClearAllManifestFiles;
/// <summary>
/// 自定义参数:数据文件追加文件格式
/// </summary>
@@ -188,6 +193,10 @@ namespace YooAsset
{
FileVerifyLevel = (EFileVerifyLevel)value;
}
else if (name == FileSystemParametersDefine.INSTALL_CLEAR_MODE)
{
InstallClearMode = (EOverwriteInstallClearMode)value;
}
else if (name == FileSystemParametersDefine.APPEND_FILE_EXTENSION)
{
AppendFileExtension = Convert.ToBoolean(value);
@@ -227,8 +236,8 @@ namespace YooAsset
_packageRoot = packageRoot;
_cacheBundleFilesRoot = PathUtility.Combine(_packageRoot, DefaultCacheFileSystemDefine.BundleFilesFolderName);
_tempFilesRoot = PathUtility.Combine(_packageRoot, DefaultCacheFileSystemDefine.TempFilesFolderName);
_cacheManifestFilesRoot = PathUtility.Combine(_packageRoot, DefaultCacheFileSystemDefine.ManifestFilesFolderName);
_tempFilesRoot = PathUtility.Combine(_packageRoot, DefaultCacheFileSystemDefine.TempFilesFolderName);
}
public virtual void OnDestroy()
{
@@ -500,7 +509,18 @@ namespace YooAsset
}
/// <summary>
/// 删除所有清单文件
/// 删除所有缓存的资源文件
/// </summary>
public void DeleteAllBundleFiles()
{
if (Directory.Exists(_cacheBundleFilesRoot))
{
Directory.Delete(_cacheBundleFilesRoot, true);
}
}
/// <summary>
/// 删除所有缓存的清单文件
/// </summary>
public void DeleteAllManifestFiles()
{

View File

@@ -0,0 +1,29 @@

namespace YooAsset
{
/// <summary>
/// 覆盖安装清理模式
/// </summary>
public enum EOverwriteInstallClearMode
{
/// <summary>
/// 不做任何处理
/// </summary>
None = 0,
/// <summary>
/// 清理所有缓存文件(包含资源文件和清单文件)
/// </summary>
ClearAllCacheFiles = 1,
/// <summary>
/// 清理所有缓存的资源文件
/// </summary>
ClearAllBundleFiles = 2,
/// <summary>
/// 清理所有缓存的清单文件
/// </summary>
ClearAllManifestFiles = 3,
}
}

View File

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

View File

@@ -46,9 +46,32 @@ namespace YooAsset
// 如果水印发生变化,则说明覆盖安装后首次打开游戏
if (appFootPrint.IsDirty())
{
_fileSystem.DeleteAllManifestFiles();
if (_fileSystem.InstallClearMode == EOverwriteInstallClearMode.None)
{
YooLogger.Warning("Do nothing when overwrite install application !");
}
else if (_fileSystem.InstallClearMode == EOverwriteInstallClearMode.ClearAllCacheFiles)
{
_fileSystem.DeleteAllBundleFiles();
_fileSystem.DeleteAllManifestFiles();
YooLogger.Warning("Delete all cache files when overwrite install application !");
}
else if (_fileSystem.InstallClearMode == EOverwriteInstallClearMode.ClearAllBundleFiles)
{
_fileSystem.DeleteAllBundleFiles();
YooLogger.Warning("Delete all bundle files when overwrite install application !");
}
else if (_fileSystem.InstallClearMode == EOverwriteInstallClearMode.ClearAllManifestFiles)
{
_fileSystem.DeleteAllManifestFiles();
YooLogger.Warning("Delete all manifest files when overwrite install application !");
}
else
{
throw new System.NotImplementedException(_fileSystem.InstallClearMode.ToString());
}
appFootPrint.Coverage(_fileSystem.PackageName);
YooLogger.Warning("Delete manifest files when application foot print dirty !");
}
_steps = ESteps.SearchCacheFiles;

View File

@@ -59,8 +59,7 @@ namespace YooAsset
if (_steps == ESteps.VerifyFileData)
{
string fileHash = HashUtility.BytesCRC32(_fileData);
if (fileHash == _packageHash)
if (ManifestTools.VerifyManifestData(_fileData, _packageHash))
{
_steps = ESteps.LoadManifest;
}

View File

@@ -59,8 +59,7 @@ namespace YooAsset
if (_steps == ESteps.VerifyFileData)
{
string fileHash = HashUtility.BytesCRC32(_fileData);
if (fileHash == _packageHash)
if (ManifestTools.VerifyManifestData(_fileData, _packageHash))
{
_steps = ESteps.LoadManifest;
}

View File

@@ -14,7 +14,8 @@ namespace YooAsset
base.OnCreate(packageName, rootDirectory);
// 注意:重写保存根目录和临时目录
_cacheBundleFilesRoot = PathUtility.Combine(_packageRoot, DefaultUnpackFileSystemDefine.SaveFilesFolderName);
_cacheBundleFilesRoot = PathUtility.Combine(_packageRoot, DefaultUnpackFileSystemDefine.SaveBundleFilesFolderName);
_cacheManifestFilesRoot = PathUtility.Combine(_packageRoot, DefaultUnpackFileSystemDefine.SaveManifestFilesFolderName);
_tempFilesRoot = PathUtility.Combine(_packageRoot, DefaultUnpackFileSystemDefine.TempFilesFolderName);
}
}

View File

@@ -11,8 +11,13 @@ namespace YooAsset
/// <summary>
/// 保存的资源文件的文件夹名称
/// </summary>
public const string SaveFilesFolderName = "UnpackFiles";
public const string SaveBundleFilesFolderName = "UnpackBundleFiles";
/// <summary>
/// 保存的清单文件的文件夹名称
/// </summary>
public const string SaveManifestFilesFolderName = "UnpackManifestFiles";
/// <summary>
/// 下载的临时文件的文件夹名称
/// </summary>

View File

@@ -72,8 +72,7 @@ namespace YooAsset
if (_steps == ESteps.VerifyFileData)
{
string fileHash = HashUtility.BytesCRC32(_webDataRequestOp.Result);
if (fileHash == _packageHash)
if (ManifestTools.VerifyManifestData(_webDataRequestOp.Result, _packageHash))
{
_steps = ESteps.LoadManifest;
}

View File

@@ -69,8 +69,7 @@ namespace YooAsset
if (_steps == ESteps.VerifyFileData)
{
string fileHash = HashUtility.BytesCRC32(_webDataRequestOp.Result);
if (fileHash == _packageHash)
if (ManifestTools.VerifyManifestData(_webDataRequestOp.Result, _packageHash))
{
_steps = ESteps.LoadManifest;
}

View File

@@ -4,6 +4,7 @@ namespace YooAsset
public class FileSystemParametersDefine
{
public const string FILE_VERIFY_LEVEL = "FILE_VERIFY_LEVEL";
public const string INSTALL_CLEAR_MODE = "INSTALL_CLEAR_MODE";
public const string REMOTE_SERVICES = "REMOTE_SERVICES";
public const string DECRYPTION_SERVICES = "DECRYPTION_SERVICES";
public const string APPEND_FILE_EXTENSION = "APPEND_FILE_EXTENSION";

View File

@@ -38,6 +38,10 @@ namespace YooAsset
/// </summary>
public abstract class InitializeParameters
{
/// <summary>
/// 同时加载Bundle文件的最大并发数
/// </summary>
public int BundleLoadingMaxConcurrency = int.MaxValue;
}
/// <summary>

View File

@@ -9,7 +9,8 @@ namespace YooAsset
private enum ESteps
{
None,
LoadFile,
CheckConcurrency,
LoadBundleFile,
Done,
}
@@ -57,17 +58,32 @@ namespace YooAsset
}
internal override void InternalStart()
{
_steps = ESteps.LoadFile;
_steps = ESteps.CheckConcurrency;
}
internal override void InternalUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.LoadFile)
if (_steps == ESteps.CheckConcurrency)
{
if (IsWaitForAsyncComplete)
{
_steps = ESteps.LoadBundleFile;
}
else
{
if (_resourceManager.BundleLoadingIsBusy())
return;
_steps = ESteps.LoadBundleFile;
}
}
if (_steps == ESteps.LoadBundleFile)
{
if (_loadBundleOp == null)
{
_resourceManager.BundleLoadingCounter++;
_loadBundleOp = LoadBundleInfo.LoadBundleFile();
_loadBundleOp.StartOperation();
AddChildOperation(_loadBundleOp);
@@ -103,6 +119,9 @@ namespace YooAsset
Status = EOperationStatus.Failed;
Error = _loadBundleOp.Error;
}
// 统计计数减少
_resourceManager.BundleLoadingCounter--;
}
}
internal override void InternalWaitForAsyncComplete()

View File

@@ -15,6 +15,7 @@ namespace YooAsset
private readonly ResourceManager _resManager;
private readonly int _loopCount;
private int _loopCounter = 0;
private ESteps _steps = ESteps.None;
internal UnloadUnusedAssetsOperation(ResourceManager resourceManager, int loopCount)
@@ -25,6 +26,7 @@ namespace YooAsset
internal override void InternalStart()
{
_steps = ESteps.UnloadUnused;
_loopCounter = _loopCount;
}
internal override void InternalUpdate()
{
@@ -33,13 +35,23 @@ namespace YooAsset
if (_steps == ESteps.UnloadUnused)
{
for (int i = 0; i < _loopCount; i++)
while (_loopCounter > 0)
{
_loopCounter--;
LoopUnloadUnused();
if (IsWaitForAsyncComplete == false)
{
if (OperationSystem.IsBusy)
break;
}
}
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
if (_loopCounter <= 0)
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
}
}
internal override void InternalWaitForAsyncComplete()

View File

@@ -14,6 +14,7 @@ namespace YooAsset
internal readonly List<SceneHandle> SceneHandles = new List<SceneHandle>(100);
private long _sceneCreateIndex = 0;
private IBundleQuery _bundleQuery;
private int _bundleLoadingMaxConcurrency;
/// <summary>
/// 所属包裹
@@ -25,6 +26,11 @@ namespace YooAsset
/// </summary>
public bool LockLoadOperation = false;
/// <summary>
/// 统计正在加载的Bundle文件数量
/// </summary>
public int BundleLoadingCounter = 0;
public ResourceManager(string packageName)
{
@@ -34,8 +40,9 @@ namespace YooAsset
/// <summary>
/// 初始化
/// </summary>
public void Initialize(IBundleQuery bundleServices)
public void Initialize(InitializeParameters parameters, IBundleQuery bundleServices)
{
_bundleLoadingMaxConcurrency = parameters.BundleLoadingMaxConcurrency;
_bundleQuery = bundleServices;
SceneManager.sceneUnloaded += OnSceneUnloaded;
}
@@ -310,6 +317,10 @@ namespace YooAsset
{
return LoaderDic.Count > 0;
}
internal bool BundleLoadingIsBusy()
{
return BundleLoadingCounter >= _bundleLoadingMaxConcurrency;
}
private LoadBundleFileOperation CreateBundleFileLoaderInternal(BundleInfo bundleInfo)
{

View File

@@ -8,6 +8,30 @@ namespace YooAsset
{
internal static class ManifestTools
{
/// <summary>
/// 验证清单文件的二进制数据
/// </summary>
public static bool VerifyManifestData(byte[] fileData, string hashValue)
{
if (fileData == null || fileData.Length == 0)
return false;
if (string.IsNullOrEmpty(hashValue))
return false;
// 注意:兼容俩种验证方式
// 注意计算MD5的哈希值通常为32个字符
string fileHash;
if (hashValue.Length == 32)
fileHash = HashUtility.BytesMD5(fileData);
else
fileHash = HashUtility.BytesCRC32(fileData);
if (fileHash == hashValue)
return true;
else
return false;
}
/// <summary>
/// 序列化JSON文件
/// </summary>
@@ -197,9 +221,16 @@ namespace YooAsset
manifest.AssetDic = new Dictionary<string, PackageAsset>(assetCount);
if (manifest.EnableAddressable)
{
manifest.AssetPathMapping1 = new Dictionary<string, string>(assetCount * 3);
}
else
manifest.AssetPathMapping1 = new Dictionary<string, string>(assetCount * 2);
{
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);
@@ -221,8 +252,6 @@ namespace YooAsset
// 填充AssetPathMapping1
{
string location = packageAsset.AssetPath;
if (manifest.LocationToLower)
location = location.ToLower();
// 添加原生路径的映射
if (manifest.AssetPathMapping1.ContainsKey(location))

View File

@@ -138,9 +138,6 @@ namespace YooAsset
if (string.IsNullOrEmpty(location))
return string.Empty;
if (LocationToLower)
location = location.ToLower();
if (AssetPathMapping1.TryGetValue(location, out string assetPath))
return assetPath;
else
@@ -307,9 +304,6 @@ namespace YooAsset
return string.Empty;
}
if (LocationToLower)
location = location.ToLower();
if (AssetPathMapping1.TryGetValue(location, out string assetPath))
{
return assetPath;

View File

@@ -100,7 +100,7 @@ namespace YooAsset
var playModeImpl = new PlayModeImpl(PackageName, _playMode);
_bundleQuery = playModeImpl;
_playModeImpl = playModeImpl;
_resourceManager.Initialize(_bundleQuery);
_resourceManager.Initialize(parameters, _bundleQuery);
// 初始化资源系统
InitializationOperation initializeOperation;
@@ -162,6 +162,10 @@ namespace YooAsset
throw new Exception($"Editor simulate mode only support unity editor.");
#endif
// 检测初始化参数
if (parameters.BundleLoadingMaxConcurrency <= 0)
throw new Exception($"{nameof(parameters.BundleLoadingMaxConcurrency)} value must be greater than zero.");
// 鉴定运行模式
if (parameters is EditorSimulateModeParameters)
_playMode = EPlayMode.EditorSimulateMode;

View File

@@ -126,7 +126,7 @@ public class PatchWindow : MonoBehaviour
{
UserEventDefine.UserTryRequestPackageVersion.SendEventMessage();
};
ShowMessageBox($"Failed to update static version, please check the network status.", callback);
ShowMessageBox($"Failed to request package version, please check the network status.", callback);
}
else if (message is PatchEventDefine.PackageManifestUpdateFailed)
{

View File

@@ -71,7 +71,7 @@ public static class TestPackageBuilder
buildParameters.ClearBuildCacheFiles = true;
buildParameters.UseAssetDependencyDB = true;
buildParameters.BuiltinShadersBundleName = builtinShaderBundleName;
buildParameters.EncryptionServices = new FileStreamEncryption();
buildParameters.EncryptionServices = new FileStreamTestEncryption();
var pipeline = new ScriptableBuildPipeline();
BuildResult buildResult = pipeline.Run(buildParameters, false);
@@ -108,7 +108,7 @@ public static class TestPackageBuilder
buildParameters.CompressOption = ECompressOption.LZ4;
buildParameters.ClearBuildCacheFiles = true;
buildParameters.UseAssetDependencyDB = true;
buildParameters.EncryptionServices = new FileStreamEncryption();
buildParameters.EncryptionServices = new FileStreamTestEncryption();
var pipeline = new BuiltinBuildPipeline();
BuildResult buildResult = pipeline.Run(buildParameters, false);

View File

@@ -60,7 +60,7 @@ public class T2_TestBuldinFileSystem : IPrebuildSetup, IPostBuildCleanup
// 初始化资源包
var initParams = new OfflinePlayModeParameters();
var decryption = new FileStreamDecryption();
var decryption = new FileStreamTestDecryption();
initParams.BuildinFileSystemParameters = FileSystemParameters.CreateDefaultBuildinFileSystemParameters(decryption, packageRoot);
var initializeOp = package.InitializeAsync(initParams);
yield return initializeOp;

View File

@@ -34,7 +34,7 @@ public class TestBundleEncryption
/// <summary>
/// 文件流加密方式
/// </summary>
public class FileStreamEncryption : IEncryptionServices
public class FileStreamTestEncryption : IEncryptionServices
{
public EncryptResult Encrypt(EncryptFileInfo fileInfo)
{
@@ -64,7 +64,7 @@ public class FileStreamEncryption : IEncryptionServices
/// <summary>
/// 文件偏移加密方式
/// </summary>
public class FileOffsetEncryption : IEncryptionServices
public class FileOffsetTestEncryption : IEncryptionServices
{
public EncryptResult Encrypt(EncryptFileInfo fileInfo)
{
@@ -119,7 +119,7 @@ public class BundleStream : FileStream
/// <summary>
/// 资源文件流解密类
/// </summary>
public class FileStreamDecryption : IDecryptionServices
public class FileStreamTestDecryption : IDecryptionServices
{
/// <summary>
/// 同步方式获取解密的资源包对象
@@ -172,7 +172,7 @@ public class FileStreamDecryption : IDecryptionServices
/// <summary>
/// 资源文件偏移解密类
/// </summary>
public class FileOffsetDecryption : IDecryptionServices
public class FileOffsetTestDecryption : IDecryptionServices
{
/// <summary>
/// 同步方式获取解密的资源包对象
@@ -224,7 +224,7 @@ public class FileOffsetDecryption : IDecryptionServices
/// WebGL平台解密类
/// 注意WebGL平台支持内存解密
/// </summary>
public class WebFileStreamDecryption : IWebDecryptionServices
public class WebFileStreamTestDecryption : IWebDecryptionServices
{
public WebDecryptResult LoadAssetBundle(WebDecryptFileInfo fileInfo)
{

View File

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