mirror of
https://github.com/tuyoogame/YooAsset.git
synced 2026-05-28 19:48:47 +00:00
feat : support encrypted ArchiveBundle
This commit is contained in:
@@ -27,14 +27,6 @@ namespace YooAsset.Editor
|
||||
/// <inheritdoc />
|
||||
protected override void CheckBuildParametersCore()
|
||||
{
|
||||
// ArchiveBundle 不支持资源包加密
|
||||
if (BundleEncryptor != null)
|
||||
{
|
||||
string message = BuildLogger.GetErrorMessage(ErrorCode.BundleEncryptionNotSupported,
|
||||
$"ArchiveFileBuildPipeline does not support bundle encryption. Please remove the BundleEncryptor configuration.");
|
||||
throw new NotSupportedException(message);
|
||||
}
|
||||
|
||||
// 校验文件对齐参数范围
|
||||
if (FileAlignment < 0 || FileAlignment > MaxFileAlignment)
|
||||
{
|
||||
|
||||
@@ -38,26 +38,51 @@ namespace YooAsset
|
||||
|
||||
if (_steps == ESteps.LoadBundle)
|
||||
{
|
||||
if (_options.Bundle.IsEncrypted)
|
||||
if (_options.Bundle.IsEncrypted == false)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
SetError($"ArchiveBundle encrypted loading is not supported: '{_options.FilePath}'.");
|
||||
return;
|
||||
}
|
||||
if (FileUtility.IsFileIOSupported(_options.FilePath) == false)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
SetError($"FileIO is not supported for builtin path: '{_options.FilePath}'.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (FileUtility.IsFileIOSupported(_options.FilePath) == false)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
SetError($"FileIO is not supported for builtin path: '{_options.FilePath}'.");
|
||||
return;
|
||||
LoadResult result = LoadFromFile();
|
||||
if (result.Succeeded == false)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
SetError(result.Error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
LoadResult result = ParseArchiveFile();
|
||||
if (result.Succeeded == false)
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
SetError(result.Error);
|
||||
return;
|
||||
var decryptor = _options.ArchiveBundleDecryptor;
|
||||
if (decryptor == null)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
SetError($"{_options.CacheName} archive bundle decryptor is null.");
|
||||
return;
|
||||
}
|
||||
|
||||
LoadResult result;
|
||||
if (decryptor is IBundleMemoryDecryptor memoryDecryptor)
|
||||
{
|
||||
result = LoadFromMemory(memoryDecryptor);
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
SetError($"{_options.CacheName} does not support '{decryptor.GetType().Name}' for ArchiveBundle.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.Succeeded == false)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
SetError(result.Error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_steps = ESteps.CheckResult;
|
||||
@@ -83,16 +108,33 @@ namespace YooAsset
|
||||
ExecuteBatch();
|
||||
}
|
||||
|
||||
private LoadResult ParseArchiveFile()
|
||||
private LoadResult LoadFromFile()
|
||||
{
|
||||
try
|
||||
{
|
||||
_archiveBundle = ArchiveBundleHelper.LoadArchiveBundle(_options.FilePath);
|
||||
_archiveBundle = ArchiveBundleHelper.LoadFromFile(_options.FilePath);
|
||||
return LoadResult.Default();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return LoadResult.Failure($"Failed to parse archive file: {ex.Message}.");
|
||||
return LoadResult.Failure($"Failed to load archive bundle file: {ex.Message}.");
|
||||
}
|
||||
}
|
||||
private LoadResult LoadFromMemory(IBundleMemoryDecryptor decryptor)
|
||||
{
|
||||
try
|
||||
{
|
||||
var args = new BundleDecryptArgs(_options.Bundle, null, _options.FilePath);
|
||||
byte[] binaryData = decryptor.GetDecryptedData(args);
|
||||
if (binaryData == null)
|
||||
return LoadResult.Failure($"{_options.CacheName} decryptor returned null data.");
|
||||
|
||||
_archiveBundle = ArchiveBundleHelper.LoadFromMemory(binaryData);
|
||||
return LoadResult.Default();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return LoadResult.Failure($"Failed to load archive bundle file from memory: {ex.Message}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,11 +21,17 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
public string FilePath { get; }
|
||||
|
||||
public LoadLocalArchiveBundleOptions(string cacheName, PackageBundle bundle, string filePath)
|
||||
/// <summary>
|
||||
/// ArchiveBundle 解密器
|
||||
/// </summary>
|
||||
public IBundleDecryptor ArchiveBundleDecryptor { get; }
|
||||
|
||||
public LoadLocalArchiveBundleOptions(string cacheName, PackageBundle bundle, string filePath, IBundleDecryptor archiveBundleDecryptor)
|
||||
{
|
||||
CacheName = cacheName;
|
||||
Bundle = bundle;
|
||||
FilePath = filePath;
|
||||
ArchiveBundleDecryptor = archiveBundleDecryptor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,14 +56,14 @@ namespace YooAsset
|
||||
if (decryptor == null)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
SetError($"{_options.CacheName} decryptor is null.");
|
||||
SetError($"{_options.CacheName} asset bundle decryptor is null.");
|
||||
return;
|
||||
}
|
||||
|
||||
LoadResult result;
|
||||
if (decryptor is IBundleOffsetDecryptor offsetDecryptor)
|
||||
{
|
||||
result = LoadFromFileWithOffset(offsetDecryptor);
|
||||
result = LoadFromFile(offsetDecryptor);
|
||||
}
|
||||
else if (decryptor is IBundleMemoryDecryptor memoryDecryptor)
|
||||
{
|
||||
@@ -76,7 +76,7 @@ namespace YooAsset
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
SetError($"{_options.CacheName} does not support '{decryptor.GetType().Name}'.");
|
||||
SetError($"{_options.CacheName} does not support '{decryptor.GetType().Name}' for AssetBundle.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -137,18 +137,17 @@ namespace YooAsset
|
||||
else
|
||||
_createRequest = AssetBundle.LoadFromFileAsync(_options.FilePath);
|
||||
}
|
||||
private LoadResult LoadFromFileWithOffset(IBundleOffsetDecryptor decryptor)
|
||||
private LoadResult LoadFromFile(IBundleOffsetDecryptor decryptor)
|
||||
{
|
||||
var args = new BundleDecryptArgs(_options.Bundle, null, _options.FilePath);
|
||||
long rawOffset = decryptor.GetFileOffset(args);
|
||||
if (rawOffset < 0)
|
||||
return LoadResult.Failure($"{_options.CacheName} decryptor returned negative offset: {rawOffset}.");
|
||||
ulong offset = (ulong)rawOffset;
|
||||
long offset = decryptor.GetFileOffset(args);
|
||||
if (offset < 0)
|
||||
return LoadResult.Failure($"{_options.CacheName} decryptor returned negative offset: {offset}.");
|
||||
|
||||
if (IsWaitForCompletion)
|
||||
_assetBundle = AssetBundle.LoadFromFile(_options.FilePath, 0, offset);
|
||||
_assetBundle = AssetBundle.LoadFromFile(_options.FilePath, 0, (ulong)offset);
|
||||
else
|
||||
_createRequest = AssetBundle.LoadFromFileAsync(_options.FilePath, 0, offset);
|
||||
_createRequest = AssetBundle.LoadFromFileAsync(_options.FilePath, 0, (ulong)offset);
|
||||
|
||||
return LoadResult.Default();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
@@ -62,7 +61,7 @@ namespace YooAsset
|
||||
if (decryptor == null)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
SetError($"{_options.CacheName} decryptor is null.");
|
||||
SetError($"{_options.CacheName} raw bundle decryptor is null.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -74,7 +73,7 @@ namespace YooAsset
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
SetError($"{_options.CacheName} does not support '{decryptor.GetType().Name}'.");
|
||||
SetError($"{_options.CacheName} does not support '{decryptor.GetType().Name}' for RawBundle.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -113,13 +112,12 @@ namespace YooAsset
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] data = File.ReadAllBytes(_options.FilePath);
|
||||
_rawBundle = new RawBundle(data);
|
||||
_rawBundle = RawBundleHelper.LoadFromFile(_options.FilePath);
|
||||
return LoadResult.Default();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return LoadResult.Failure($"Failed to read raw bundle file: {ex.Message}.");
|
||||
return LoadResult.Failure($"Failed to load raw bundle file: {ex.Message}.");
|
||||
}
|
||||
}
|
||||
private LoadResult LoadFromMemory(IBundleMemoryDecryptor decryptor)
|
||||
@@ -129,7 +127,7 @@ namespace YooAsset
|
||||
if (binaryData == null)
|
||||
return LoadResult.Failure($"{_options.CacheName} decryptor returned null data.");
|
||||
|
||||
_rawBundle = new RawBundle(binaryData);
|
||||
_rawBundle = RawBundleHelper.LoadFromMemory(binaryData);
|
||||
return LoadResult.Default();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,12 +199,12 @@ namespace YooAsset
|
||||
if (binaryData == null)
|
||||
return LoadResult.Failure($"{_options.CacheName} decryptor returned null data.");
|
||||
|
||||
_rawBundle = new RawBundle(binaryData);
|
||||
_rawBundle = RawBundleHelper.LoadFromMemory(binaryData);
|
||||
return LoadResult.Default();
|
||||
}
|
||||
else
|
||||
{
|
||||
_rawBundle = new RawBundle(fileData);
|
||||
_rawBundle = RawBundleHelper.LoadFromMemory(fileData);
|
||||
return LoadResult.Default();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,15 +20,22 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
public IBundleDecryptor RawBundleDecryptor { get; }
|
||||
|
||||
/// <summary>
|
||||
/// ArchiveBundle 解密器
|
||||
/// </summary>
|
||||
public IBundleDecryptor ArchiveBundleDecryptor { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 下载后台
|
||||
/// </summary>
|
||||
public IDownloadBackend DownloadBackend { get; }
|
||||
|
||||
public Configuration(IBundleDecryptor assetBundleDecryptor, IBundleDecryptor rawBundleDecryptor, IDownloadBackend downloadBackend)
|
||||
public Configuration(IBundleDecryptor assetBundleDecryptor, IBundleDecryptor rawBundleDecryptor,
|
||||
IBundleDecryptor archiveBundleDecryptor, IDownloadBackend downloadBackend)
|
||||
{
|
||||
AssetBundleDecryptor = assetBundleDecryptor;
|
||||
RawBundleDecryptor = rawBundleDecryptor;
|
||||
ArchiveBundleDecryptor = archiveBundleDecryptor;
|
||||
DownloadBackend = downloadBackend;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,8 @@ namespace YooAsset
|
||||
var options = new LoadLocalArchiveBundleOptions(
|
||||
cacheName: _fileCache.GetType().Name,
|
||||
bundle: _bundle,
|
||||
filePath: _cacheEntry.FilePath);
|
||||
filePath: _cacheEntry.FilePath,
|
||||
archiveBundleDecryptor: _fileCache.Config.ArchiveBundleDecryptor);
|
||||
_loadLocalArchiveBundleOp = new LoadLocalArchiveBundleOperation(options);
|
||||
_loadLocalArchiveBundleOp.StartOperation();
|
||||
AddChildOperation(_loadLocalArchiveBundleOp);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
@@ -22,8 +21,7 @@ namespace YooAsset
|
||||
|
||||
try
|
||||
{
|
||||
byte[] data = File.ReadAllBytes(editorFilePath);
|
||||
var rawBundle = new RawBundle(data);
|
||||
var rawBundle = RawBundleHelper.LoadFromFile(editorFilePath);
|
||||
|
||||
SetResult();
|
||||
BundleHandle = new VirtualRawBundleHandle(_bundle, rawBundle);
|
||||
|
||||
@@ -61,7 +61,8 @@ namespace YooAsset
|
||||
var options = new LoadLocalArchiveBundleOptions(
|
||||
cacheName: _fileCache.GetType().Name,
|
||||
bundle: _bundle,
|
||||
filePath: _cacheEntry.DataFilePath);
|
||||
filePath: _cacheEntry.DataFilePath,
|
||||
archiveBundleDecryptor: _fileCache.Config.ArchiveBundleDecryptor);
|
||||
_loadLocalArchiveBundleOp = new LoadLocalArchiveBundleOperation(options);
|
||||
_loadLocalArchiveBundleOp.StartOperation();
|
||||
AddChildOperation(_loadLocalArchiveBundleOp);
|
||||
|
||||
@@ -30,18 +30,25 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
public IBundleDecryptor RawBundleDecryptor { get; }
|
||||
|
||||
/// <summary>
|
||||
/// ArchiveBundle 解密器
|
||||
/// </summary>
|
||||
public IBundleDecryptor ArchiveBundleDecryptor { get; }
|
||||
|
||||
/// <summary>
|
||||
/// AssetBundle 备用解密器
|
||||
/// </summary>
|
||||
public IBundleMemoryDecryptor AssetBundleFallbackDecryptor { get; }
|
||||
|
||||
public Configuration(int fileVerifyMaxConcurrency, EFileVerifyLevel fileVerifyLevel,
|
||||
IBundleDecryptor assetBundleDecryptor, IBundleDecryptor rawBundleDecryptor, IBundleMemoryDecryptor assetBundleFallbackDecryptor)
|
||||
IBundleDecryptor assetBundleDecryptor, IBundleDecryptor rawBundleDecryptor,
|
||||
IBundleDecryptor archiveBundleDecryptor, IBundleMemoryDecryptor assetBundleFallbackDecryptor)
|
||||
{
|
||||
FileVerifyMaxConcurrency = fileVerifyMaxConcurrency;
|
||||
FileVerifyLevel = fileVerifyLevel;
|
||||
AssetBundleDecryptor = assetBundleDecryptor;
|
||||
RawBundleDecryptor = rawBundleDecryptor;
|
||||
ArchiveBundleDecryptor = archiveBundleDecryptor;
|
||||
AssetBundleFallbackDecryptor = assetBundleFallbackDecryptor;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,15 +56,14 @@ namespace YooAsset
|
||||
}
|
||||
|
||||
private readonly string _archiveFilePath;
|
||||
private readonly byte[] _memoryData;
|
||||
private readonly Dictionary<string, FileEntry> _entries;
|
||||
private readonly Dictionary<string, RawFileObject> _cachedObjects = new Dictionary<string, RawFileObject>();
|
||||
private bool _isUnloaded;
|
||||
|
||||
/// <summary>
|
||||
/// 创建 ArchiveBundle 实例
|
||||
/// 从本地文件创建 ArchiveBundle 实例
|
||||
/// </summary>
|
||||
/// <param name="archiveFilePath">归档文件的本地路径</param>
|
||||
/// <param name="entries">子文件索引字典</param>
|
||||
public ArchiveBundle(string archiveFilePath, Dictionary<string, FileEntry> entries)
|
||||
{
|
||||
if (string.IsNullOrEmpty(archiveFilePath))
|
||||
@@ -73,6 +72,23 @@ namespace YooAsset
|
||||
throw new ArgumentNullException(nameof(entries));
|
||||
|
||||
_archiveFilePath = archiveFilePath;
|
||||
_memoryData = null;
|
||||
_entries = entries;
|
||||
_isUnloaded = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从解密后的内存数据创建 ArchiveBundle 实例
|
||||
/// </summary>
|
||||
public ArchiveBundle(byte[] memoryData, Dictionary<string, FileEntry> entries)
|
||||
{
|
||||
if (memoryData == null)
|
||||
throw new ArgumentNullException(nameof(memoryData));
|
||||
if (entries == null)
|
||||
throw new ArgumentNullException(nameof(entries));
|
||||
|
||||
_archiveFilePath = null;
|
||||
_memoryData = memoryData;
|
||||
_entries = entries;
|
||||
_isUnloaded = false;
|
||||
}
|
||||
@@ -92,8 +108,8 @@ namespace YooAsset
|
||||
if (_cachedObjects.TryGetValue(assetPath, out RawFileObject cached))
|
||||
return cached;
|
||||
|
||||
byte[] fileData = ReadFileData(assetPath);
|
||||
var rawFileObject = RawFileObject.CreateFromBytes(fileData);
|
||||
byte[] assetData = ReadAssetData(assetPath);
|
||||
var rawFileObject = RawFileObject.CreateFromBytes(assetData);
|
||||
_cachedObjects[assetPath] = rawFileObject;
|
||||
return rawFileObject;
|
||||
}
|
||||
@@ -113,14 +129,24 @@ namespace YooAsset
|
||||
_entries.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从归档文件中读取子文件的字节数据
|
||||
/// </summary>
|
||||
private byte[] ReadFileData(string assetPath)
|
||||
private byte[] ReadAssetData(string assetPath)
|
||||
{
|
||||
if (_entries.TryGetValue(assetPath, out FileEntry entry) == false)
|
||||
throw new InvalidOperationException($"Asset not found in archive: '{assetPath}'.");
|
||||
|
||||
if (_memoryData != null)
|
||||
return ReadFromMemory(entry);
|
||||
else
|
||||
return ReadFromFile(entry);
|
||||
}
|
||||
private byte[] ReadFromMemory(FileEntry entry)
|
||||
{
|
||||
byte[] buffer = new byte[entry.DataLength];
|
||||
Buffer.BlockCopy(_memoryData, (int)entry.DataOffset, buffer, 0, (int)entry.DataLength);
|
||||
return buffer;
|
||||
}
|
||||
private byte[] ReadFromFile(FileEntry entry)
|
||||
{
|
||||
byte[] buffer = new byte[entry.DataLength];
|
||||
using (var fs = new FileStream(_archiveFilePath, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
@@ -130,7 +156,7 @@ namespace YooAsset
|
||||
{
|
||||
int read = fs.Read(buffer, bytesRead, buffer.Length - bytesRead);
|
||||
if (read == 0)
|
||||
throw new EndOfStreamException($"Unexpected end of archive file while reading '{assetPath}'.");
|
||||
throw new EndOfStreamException($"Unexpected end of archive file while reading '{entry.AssetPath}'.");
|
||||
bytesRead += read;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,14 +8,36 @@ namespace YooAsset
|
||||
internal static class ArchiveBundleHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 解析 YARK 归档文件
|
||||
/// 从本地文件解析 YARK 归档
|
||||
/// </summary>
|
||||
/// <param name="filePath">归档文件路径</param>
|
||||
/// <returns>解析成功的 ArchiveBundle 实例</returns>
|
||||
public static ArchiveBundle LoadArchiveBundle(string filePath)
|
||||
public static ArchiveBundle LoadFromFile(string filePath)
|
||||
{
|
||||
using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
using (var reader = new BinaryReader(fs))
|
||||
{
|
||||
var entries = ParseEntries(fs, fs.Length);
|
||||
return new ArchiveBundle(filePath, entries);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从解密后的内存数据解析 YARK 归档
|
||||
/// </summary>
|
||||
/// <param name="fileData">解密后的完整归档字节数据</param>
|
||||
/// <returns>解析成功的 ArchiveBundle 实例</returns>
|
||||
public static ArchiveBundle LoadFromMemory(byte[] fileData)
|
||||
{
|
||||
using (var ms = new MemoryStream(fileData, false))
|
||||
{
|
||||
var entries = ParseEntries(ms, fileData.Length);
|
||||
return new ArchiveBundle(fileData, entries);
|
||||
}
|
||||
}
|
||||
|
||||
private static Dictionary<string, ArchiveBundle.FileEntry> ParseEntries(Stream stream, long dataLength)
|
||||
{
|
||||
using (var reader = new BinaryReader(stream, Encoding.UTF8, true))
|
||||
{
|
||||
// 校验文件头魔数(YARK)
|
||||
uint magic = reader.ReadUInt32();
|
||||
@@ -34,7 +56,6 @@ namespace YooAsset
|
||||
if (fileCount > ArchiveBundleConsts.MaxChildFileCount)
|
||||
throw new InvalidOperationException($"Archive child file count {fileCount} exceeds maximum ({ArchiveBundleConsts.MaxChildFileCount}).");
|
||||
|
||||
long fileLength = fs.Length;
|
||||
var entries = new Dictionary<string, ArchiveBundle.FileEntry>(fileCount);
|
||||
for (int i = 0; i < fileCount; i++)
|
||||
{
|
||||
@@ -44,9 +65,9 @@ namespace YooAsset
|
||||
throw new InvalidOperationException($"Invalid path length {pathLen} at entry index {i}.");
|
||||
if (pathLen > ArchiveBundleConsts.MaxChildFilePathBytes)
|
||||
throw new InvalidOperationException($"Path length {pathLen} exceeds maximum ({ArchiveBundleConsts.MaxChildFilePathBytes}) at entry index {i}.");
|
||||
long remaining = fileLength - fs.Position;
|
||||
long remaining = dataLength - stream.Position;
|
||||
if (pathLen > remaining)
|
||||
throw new InvalidOperationException($"Path length {pathLen} exceeds remaining file size at entry index {i}.");
|
||||
throw new InvalidOperationException($"Path length {pathLen} exceeds remaining data size at entry index {i}.");
|
||||
|
||||
string assetPath = Encoding.UTF8.GetString(reader.ReadBytes(pathLen));
|
||||
if (string.IsNullOrEmpty(assetPath))
|
||||
@@ -59,15 +80,15 @@ namespace YooAsset
|
||||
uint crc = reader.ReadUInt32();
|
||||
|
||||
// 校验数据范围是否越过文件边界
|
||||
if (offset < 0 || offset > fileLength)
|
||||
if (offset < 0 || offset > dataLength)
|
||||
throw new InvalidOperationException($"Invalid data offset {offset} for '{assetPath}'.");
|
||||
if (length < 0 || length > fileLength - offset)
|
||||
throw new InvalidOperationException($"Data range [{offset}, {offset + length}) exceeds file size {fileLength} for '{assetPath}'.");
|
||||
if (length < 0 || length > dataLength - offset)
|
||||
throw new InvalidOperationException($"Data range [{offset}, {offset + length}) exceeds data size {dataLength} for '{assetPath}'.");
|
||||
|
||||
entries[assetPath] = new ArchiveBundle.FileEntry(assetPath, offset, length, crc);
|
||||
}
|
||||
|
||||
return new ArchiveBundle(filePath, entries);
|
||||
return entries;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.IO;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal static class RawBundleHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 从本地文件加载 RawBundle
|
||||
/// </summary>
|
||||
public static RawBundle LoadFromFile(string filePath)
|
||||
{
|
||||
byte[] fileData = File.ReadAllBytes(filePath);
|
||||
return new RawBundle(fileData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从内存数据加载 RawBundle
|
||||
/// </summary>
|
||||
public static RawBundle LoadFromMemory(byte[] fileData)
|
||||
{
|
||||
return new RawBundle(fileData);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9d03e8f2341d4c74886f1e7aef83d0c6
|
||||
guid: 37ec8a856caa44b4a993e52d4f1d6fb1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -109,17 +109,22 @@ namespace YooAsset
|
||||
/// <summary>
|
||||
/// AssetBundle 解密器 <see cref="IBundleDecryptor"/>
|
||||
/// </summary>
|
||||
AssetbundleDecryptor,
|
||||
AssetBundleDecryptor,
|
||||
|
||||
/// <summary>
|
||||
/// RawBundle 解密器 <see cref="IBundleDecryptor"/>
|
||||
/// </summary>
|
||||
RawbundleDecryptor,
|
||||
RawBundleDecryptor,
|
||||
|
||||
/// <summary>
|
||||
/// ArchiveBundle 解密器 <see cref="IBundleDecryptor"/>
|
||||
/// </summary>
|
||||
ArchiveBundleDecryptor,
|
||||
|
||||
/// <summary>
|
||||
/// AssetBundle 备用解密器 <see cref="IBundleMemoryDecryptor"/>
|
||||
/// </summary>
|
||||
AssetbundleFallbackDecryptor,
|
||||
AssetBundleFallbackDecryptor,
|
||||
|
||||
/// <summary>
|
||||
/// 资源清单解密器 <see cref="IManifestDecryptor"/>
|
||||
|
||||
@@ -131,6 +131,11 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
public IBundleDecryptor RawBundleDecryptor { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:ArchiveBundle 解密器
|
||||
/// </summary>
|
||||
public IBundleDecryptor ArchiveBundleDecryptor { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:AssetBundle 备用解密器
|
||||
/// </summary>
|
||||
@@ -278,15 +283,19 @@ namespace YooAsset
|
||||
// 限制在合理范围内:1-32
|
||||
UnpackMaxRequestsPerFrame = Mathf.Clamp(convertValue, 1, 32);
|
||||
}
|
||||
else if (paramName == nameof(EFileSystemParameter.AssetbundleDecryptor))
|
||||
else if (paramName == nameof(EFileSystemParameter.AssetBundleDecryptor))
|
||||
{
|
||||
AssetBundleDecryptor = FileSystemHelper.CastParameter<IBundleDecryptor>(paramName, value);
|
||||
}
|
||||
else if (paramName == nameof(EFileSystemParameter.RawbundleDecryptor))
|
||||
else if (paramName == nameof(EFileSystemParameter.RawBundleDecryptor))
|
||||
{
|
||||
RawBundleDecryptor = FileSystemHelper.CastParameter<IBundleDecryptor>(paramName, value);
|
||||
}
|
||||
else if (paramName == nameof(EFileSystemParameter.AssetbundleFallbackDecryptor))
|
||||
else if (paramName == nameof(EFileSystemParameter.ArchiveBundleDecryptor))
|
||||
{
|
||||
ArchiveBundleDecryptor = FileSystemHelper.CastParameter<IBundleDecryptor>(paramName, value);
|
||||
}
|
||||
else if (paramName == nameof(EFileSystemParameter.AssetBundleFallbackDecryptor))
|
||||
{
|
||||
AssetBundleFallbackDecryptor = FileSystemHelper.CastParameter<IBundleMemoryDecryptor>(paramName, value);
|
||||
}
|
||||
@@ -340,6 +349,7 @@ namespace YooAsset
|
||||
var cacheConfig = new BuiltinBundleCache.Configuration(
|
||||
assetBundleDecryptor: AssetBundleDecryptor,
|
||||
rawBundleDecryptor: RawBundleDecryptor,
|
||||
archiveBundleDecryptor: ArchiveBundleDecryptor,
|
||||
downloadBackend: DownloadBackend);
|
||||
BuiltinBundleCache = new BuiltinBundleCache(packageName, _packageRoot, cacheConfig);
|
||||
}
|
||||
@@ -351,6 +361,7 @@ namespace YooAsset
|
||||
fileVerifyLevel: FileVerifyLevel,
|
||||
assetBundleDecryptor: AssetBundleDecryptor,
|
||||
rawBundleDecryptor: RawBundleDecryptor,
|
||||
archiveBundleDecryptor: ArchiveBundleDecryptor,
|
||||
assetBundleFallbackDecryptor: AssetBundleFallbackDecryptor);
|
||||
UnpackBundleCache = new SandboxBundleCache(packageName, _unpackBundleFilesRoot, cacheConfig);
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace YooAsset
|
||||
if (_steps == ESteps.TryCopyFile)
|
||||
{
|
||||
// 注意:Android/OpenHarmony 平台 File.Exists 无法识别包体内文件。
|
||||
// 该步骤仅对 StreamingAssets 为真实文件系统目录的平台(Windows/iOS/Mac)生效。
|
||||
// 说明:该步骤仅对 StreamingAssets 为真实文件系统目录的平台(Windows/iOS/Mac)生效。
|
||||
if (File.Exists(_sourceFilePath))
|
||||
{
|
||||
try
|
||||
|
||||
@@ -123,6 +123,11 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
public IBundleDecryptor RawBundleDecryptor { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:ArchiveBundle 解密器
|
||||
/// </summary>
|
||||
public IBundleDecryptor ArchiveBundleDecryptor { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:AssetBundle 备用解密器
|
||||
/// </summary>
|
||||
@@ -275,15 +280,19 @@ namespace YooAsset
|
||||
{
|
||||
RemoteService = FileSystemHelper.CastParameter<IRemoteService>(paramName, value);
|
||||
}
|
||||
else if (paramName == nameof(EFileSystemParameter.AssetbundleDecryptor))
|
||||
else if (paramName == nameof(EFileSystemParameter.AssetBundleDecryptor))
|
||||
{
|
||||
AssetBundleDecryptor = FileSystemHelper.CastParameter<IBundleDecryptor>(paramName, value);
|
||||
}
|
||||
else if (paramName == nameof(EFileSystemParameter.RawbundleDecryptor))
|
||||
else if (paramName == nameof(EFileSystemParameter.RawBundleDecryptor))
|
||||
{
|
||||
RawBundleDecryptor = FileSystemHelper.CastParameter<IBundleDecryptor>(paramName, value);
|
||||
}
|
||||
else if (paramName == nameof(EFileSystemParameter.AssetbundleFallbackDecryptor))
|
||||
else if (paramName == nameof(EFileSystemParameter.ArchiveBundleDecryptor))
|
||||
{
|
||||
ArchiveBundleDecryptor = FileSystemHelper.CastParameter<IBundleDecryptor>(paramName, value);
|
||||
}
|
||||
else if (paramName == nameof(EFileSystemParameter.AssetBundleFallbackDecryptor))
|
||||
{
|
||||
AssetBundleFallbackDecryptor = FileSystemHelper.CastParameter<IBundleMemoryDecryptor>(paramName, value);
|
||||
}
|
||||
@@ -337,6 +346,7 @@ namespace YooAsset
|
||||
fileVerifyLevel: FileVerifyLevel,
|
||||
assetBundleDecryptor: AssetBundleDecryptor,
|
||||
rawBundleDecryptor: RawBundleDecryptor,
|
||||
archiveBundleDecryptor: ArchiveBundleDecryptor,
|
||||
assetBundleFallbackDecryptor: AssetBundleFallbackDecryptor);
|
||||
BundleCache = new SandboxBundleCache(PackageName, _cacheBundleFilesRoot, cacheConfig);
|
||||
}
|
||||
|
||||
@@ -148,11 +148,11 @@ namespace YooAsset
|
||||
{
|
||||
RemoteService = FileSystemHelper.CastParameter<IRemoteService>(paramName, value);
|
||||
}
|
||||
else if (paramName == nameof(EFileSystemParameter.AssetbundleDecryptor))
|
||||
else if (paramName == nameof(EFileSystemParameter.AssetBundleDecryptor))
|
||||
{
|
||||
AssetBundleDecryptor = FileSystemHelper.CastParameter<IBundleDecryptor>(paramName, value);
|
||||
}
|
||||
else if (paramName == nameof(EFileSystemParameter.RawbundleDecryptor))
|
||||
else if (paramName == nameof(EFileSystemParameter.RawBundleDecryptor))
|
||||
{
|
||||
RawBundleDecryptor = FileSystemHelper.CastParameter<IBundleDecryptor>(paramName, value);
|
||||
}
|
||||
|
||||
@@ -158,11 +158,11 @@ namespace YooAsset
|
||||
{
|
||||
DownloadVerifyLevel = FileSystemHelper.CastParameter<EFileVerifyLevel>(paramName, value);
|
||||
}
|
||||
else if (paramName == nameof(EFileSystemParameter.AssetbundleDecryptor))
|
||||
else if (paramName == nameof(EFileSystemParameter.AssetBundleDecryptor))
|
||||
{
|
||||
AssetBundleDecryptor = FileSystemHelper.CastParameter<IBundleDecryptor>(paramName, value);
|
||||
}
|
||||
else if (paramName == nameof(EFileSystemParameter.RawbundleDecryptor))
|
||||
else if (paramName == nameof(EFileSystemParameter.RawBundleDecryptor))
|
||||
{
|
||||
RawBundleDecryptor = FileSystemHelper.CastParameter<IBundleDecryptor>(paramName, value);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: abd6a8bd2f0d3844b83930abb6014d83
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,122 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using YooAsset;
|
||||
|
||||
/// <summary>
|
||||
/// Bundle 加密和解密示例
|
||||
/// 注意:示例代码仅演示接口用法,实际项目请替换密钥和加密算法。
|
||||
/// </summary>
|
||||
public static class BundleEncryptionSample
|
||||
{
|
||||
private const byte XOR_KEY = 64;
|
||||
private const int FILE_OFFSET = 32;
|
||||
|
||||
/// <summary>
|
||||
/// 内存模式加密器:将加密后的完整文件数据返回给构建管线。
|
||||
/// </summary>
|
||||
public class MemoryEncryptor : IBundleEncryptor
|
||||
{
|
||||
public BundleEncryptResult Encrypt(BundleEncryptArgs args)
|
||||
{
|
||||
byte[] data = File.ReadAllBytes(args.FilePath);
|
||||
Xor(data);
|
||||
return new BundleEncryptResult(true, data);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 内存模式解密器:运行时返回解密后的完整文件数据。
|
||||
/// </summary>
|
||||
public class MemoryDecryptor : IBundleMemoryDecryptor
|
||||
{
|
||||
byte[] IBundleMemoryDecryptor.GetDecryptedData(BundleDecryptArgs args)
|
||||
{
|
||||
byte[] data = args.FileData;
|
||||
if (data == null)
|
||||
data = FileUtility.ReadAllBytes(args.FilePath);
|
||||
|
||||
Xor(data);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 偏移模式加密器:在文件头部插入固定长度的数据。
|
||||
/// </summary>
|
||||
public class OffsetEncryptor : IBundleEncryptor
|
||||
{
|
||||
public BundleEncryptResult Encrypt(BundleEncryptArgs args)
|
||||
{
|
||||
byte[] data = File.ReadAllBytes(args.FilePath);
|
||||
byte[] encryptedData = new byte[data.Length + FILE_OFFSET];
|
||||
Buffer.BlockCopy(data, 0, encryptedData, FILE_OFFSET, data.Length);
|
||||
return new BundleEncryptResult(true, encryptedData);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 偏移模式解密器:运行时返回真实 Bundle 数据起始偏移。
|
||||
/// </summary>
|
||||
public class OffsetDecryptor : IBundleOffsetDecryptor
|
||||
{
|
||||
long IBundleOffsetDecryptor.GetFileOffset(BundleDecryptArgs args)
|
||||
{
|
||||
return FILE_OFFSET;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 流模式加密器:示例中使用 XOR 加密整个文件。
|
||||
/// </summary>
|
||||
public class StreamEncryptor : IBundleEncryptor
|
||||
{
|
||||
public BundleEncryptResult Encrypt(BundleEncryptArgs args)
|
||||
{
|
||||
byte[] data = File.ReadAllBytes(args.FilePath);
|
||||
Xor(data);
|
||||
return new BundleEncryptResult(true, data);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 流模式解密器:运行时返回一个读取时自动解密的文件流。
|
||||
/// </summary>
|
||||
public class StreamDecryptor : IBundleStreamDecryptor
|
||||
{
|
||||
Stream IBundleStreamDecryptor.CreateDecryptionStream(BundleDecryptArgs args)
|
||||
{
|
||||
return new XorFileStream(args.FilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
}
|
||||
|
||||
int IBundleStreamDecryptor.GetBufferSize(BundleDecryptArgs args)
|
||||
{
|
||||
return 1024;
|
||||
}
|
||||
}
|
||||
|
||||
private class XorFileStream : FileStream
|
||||
{
|
||||
public XorFileStream(string path, FileMode mode, FileAccess access, FileShare share)
|
||||
: base(path, mode, access, share)
|
||||
{
|
||||
}
|
||||
|
||||
public override int Read(byte[] array, int offset, int count)
|
||||
{
|
||||
int read = base.Read(array, offset, count);
|
||||
for (int i = offset; i < offset + read; i++)
|
||||
{
|
||||
array[i] ^= XOR_KEY;
|
||||
}
|
||||
return read;
|
||||
}
|
||||
}
|
||||
|
||||
private static void Xor(byte[] data)
|
||||
{
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
data[i] ^= XOR_KEY;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9d21463d1d8d4a72a4f7e929b2f7a325
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -71,7 +71,7 @@ public static class TestPackageBuilder
|
||||
buildParameters.ClearBuildCacheFiles = true;
|
||||
buildParameters.UseAssetDependencyDB = true;
|
||||
buildParameters.BuiltinShadersBundleName = builtinShaderBundleName;
|
||||
buildParameters.BundleEncryptor = new TestFileStreamEncryption();
|
||||
buildParameters.BundleEncryptor = new TestAssetBundleEncryptor();
|
||||
buildParameters.ManifestEncryptor = new TestManifestEncryptor();
|
||||
buildParameters.ManifestDecryptor = new TestManifestDecryptor();
|
||||
|
||||
@@ -115,7 +115,7 @@ public static class TestPackageBuilder
|
||||
buildParameters.CompressOption = ECompressOption.LZ4;
|
||||
buildParameters.ClearBuildCacheFiles = true;
|
||||
buildParameters.UseAssetDependencyDB = true;
|
||||
buildParameters.BundleEncryptor = new TestFileStreamEncryption();
|
||||
buildParameters.BundleEncryptor = new TestAssetBundleEncryptor();
|
||||
buildParameters.ManifestEncryptor = new TestManifestEncryptor();
|
||||
buildParameters.ManifestDecryptor = new TestManifestDecryptor();
|
||||
|
||||
@@ -157,6 +157,7 @@ public static class TestPackageBuilder
|
||||
buildParameters.BundledCopyParams = string.Empty;
|
||||
buildParameters.ClearBuildCacheFiles = true;
|
||||
buildParameters.UseAssetDependencyDB = true;
|
||||
buildParameters.BundleEncryptor = new TestRawBundleEncryptor();
|
||||
|
||||
var pipeline = new RawFileBuildPipeline();
|
||||
BuildResult buildResult = pipeline.Run(buildParameters, false);
|
||||
@@ -197,6 +198,7 @@ public static class TestPackageBuilder
|
||||
buildParameters.ClearBuildCacheFiles = true;
|
||||
buildParameters.UseAssetDependencyDB = true;
|
||||
buildParameters.FileAlignment = 4;
|
||||
buildParameters.BundleEncryptor = new TestArchiveBundleEncryptor();
|
||||
|
||||
var pipeline = new ArchiveFileBuildPipeline();
|
||||
BuildResult buildResult = pipeline.Run(buildParameters, false);
|
||||
|
||||
@@ -14,6 +14,7 @@ using YooAsset;
|
||||
/// 2. 同步加载归档子文件,验证 GetBytes() 和 GetText() 均返回有效数据(archive_file_b)
|
||||
/// 3. 重复加载同一归档子文件,验证缓存命中不会失败(archive_file_c)
|
||||
/// 4. 释放句柄并卸载后重新加载,验证卸载保护和重载链路正常(archive_file_e)
|
||||
/// 5. 加载加密归档子文件,验证 Memory 解密路径(archive_file_x / archive_file_y)
|
||||
/// </remarks>
|
||||
public class TestLoadArchiveBundle
|
||||
{
|
||||
@@ -103,5 +104,44 @@ public class TestLoadArchiveBundle
|
||||
Assert.AreNotSame(previousObj, reloadedObj);
|
||||
reloadHandle.Release();
|
||||
}
|
||||
|
||||
// 异步加载加密归档子文件,验证 Memory 解密路径
|
||||
{
|
||||
var assetHandle = package.LoadAssetAsync<RawFileObject>("archive_file_x");
|
||||
yield return assetHandle;
|
||||
Assert.AreEqual(EOperationStatus.Succeeded, assetHandle.Status);
|
||||
|
||||
var rawFileObject = assetHandle.GetAssetObject<RawFileObject>();
|
||||
Assert.IsNotNull(rawFileObject);
|
||||
|
||||
byte[] fileBytes = rawFileObject.GetBytes();
|
||||
Assert.IsNotNull(fileBytes);
|
||||
Assert.Greater(fileBytes.Length, 0);
|
||||
|
||||
string fileText = rawFileObject.GetText();
|
||||
Assert.IsNotNull(fileText);
|
||||
Assert.IsNotEmpty(fileText);
|
||||
Assert.AreEqual("this is archive file x !", fileText);
|
||||
assetHandle.Release();
|
||||
}
|
||||
|
||||
// 同步加载加密归档子文件,验证 Memory 解密路径
|
||||
{
|
||||
var assetHandle = package.LoadAssetSync<RawFileObject>("archive_file_y");
|
||||
Assert.AreEqual(EOperationStatus.Succeeded, assetHandle.Status);
|
||||
|
||||
var rawFileObject = assetHandle.GetAssetObject<RawFileObject>();
|
||||
Assert.IsNotNull(rawFileObject);
|
||||
|
||||
byte[] fileBytes = rawFileObject.GetBytes();
|
||||
Assert.IsNotNull(fileBytes);
|
||||
Assert.Greater(fileBytes.Length, 0);
|
||||
|
||||
string fileText = rawFileObject.GetText();
|
||||
Assert.IsNotNull(fileText);
|
||||
Assert.IsNotEmpty(fileText);
|
||||
Assert.AreEqual("this is archive file y !", fileText);
|
||||
assetHandle.Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,15 +4,17 @@ using NUnit.Framework;
|
||||
using YooAsset;
|
||||
|
||||
/// <summary>
|
||||
/// 测试 RawFileObject 加载
|
||||
/// 测试 RawBundle 加载
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 覆盖 API: LoadAssetAsync(RawFileObject) / LoadAssetSync(RawFileObject)
|
||||
/// 测试内容:
|
||||
/// 1. 异步通过 RawFileObject 加载,验证 GetBytes() 和 GetText() 均返回有效数据(raw_file_c)
|
||||
/// 2. 同步通过 RawFileObject 加载,验证 GetBytes() 和 GetText() 均返回有效数据(raw_file_d)
|
||||
/// 3. 异步加载加密 RawBundle,验证 Memory 解密路径(raw_file_x)
|
||||
/// 4. 同步加载加密 RawBundle,验证 Memory 解密路径(raw_file_y)
|
||||
/// </remarks>
|
||||
public class TestLoadRawFileObject
|
||||
public class TestLoadRawBundle
|
||||
{
|
||||
public IEnumerator RuntimeTester()
|
||||
{
|
||||
@@ -55,5 +57,44 @@ public class TestLoadRawFileObject
|
||||
Assert.IsNotEmpty(fileText);
|
||||
assetHandle.Release();
|
||||
}
|
||||
|
||||
// 测试异步加载加密 RawBundle:通过 RawFileObject 获取二进制数据和文本数据
|
||||
{
|
||||
var assetHandle = package.LoadAssetAsync<RawFileObject>("raw_file_x");
|
||||
yield return assetHandle;
|
||||
Assert.AreEqual(EOperationStatus.Succeeded, assetHandle.Status);
|
||||
|
||||
var rawFileObject = assetHandle.GetAssetObject<RawFileObject>();
|
||||
Assert.IsNotNull(rawFileObject);
|
||||
|
||||
byte[] fileBytes = rawFileObject.GetBytes();
|
||||
Assert.IsNotNull(fileBytes);
|
||||
Assert.Greater(fileBytes.Length, 0);
|
||||
|
||||
string fileText = rawFileObject.GetText();
|
||||
Assert.IsNotNull(fileText);
|
||||
Assert.IsNotEmpty(fileText);
|
||||
Assert.AreEqual("this is raw file x !", fileText);
|
||||
assetHandle.Release();
|
||||
}
|
||||
|
||||
// 测试同步加载加密 RawBundle:通过 RawFileObject 获取二进制数据和文本数据
|
||||
{
|
||||
var assetHandle = package.LoadAssetSync<RawFileObject>("raw_file_y");
|
||||
Assert.AreEqual(EOperationStatus.Succeeded, assetHandle.Status);
|
||||
|
||||
var rawFileObject = assetHandle.GetAssetObject<RawFileObject>();
|
||||
Assert.IsNotNull(rawFileObject);
|
||||
|
||||
byte[] fileBytes = rawFileObject.GetBytes();
|
||||
Assert.IsNotNull(fileBytes);
|
||||
Assert.Greater(fileBytes.Length, 0);
|
||||
|
||||
string fileText = rawFileObject.GetText();
|
||||
Assert.IsNotNull(fileText);
|
||||
Assert.IsNotEmpty(fileText);
|
||||
Assert.AreEqual("this is raw file y !", fileText);
|
||||
assetHandle.Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c281ef07d441fc9458a3fa7be72b24c5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -14,7 +14,7 @@ using YooAsset;
|
||||
/// 覆盖 API: LoadAssetAsync (SpriteAtlas)
|
||||
/// 测试内容:
|
||||
/// 1. 异步加载 SpriteAtlas 资源,验证加载状态和资源对象非空
|
||||
/// 2. 从图集中获取三个精灵(bullet、pause、rocket),验证均非空
|
||||
/// 2. 从图集中获取三个精灵(sprite_a、sprite_b、sprite_c),验证均非空
|
||||
/// </remarks>
|
||||
public class TestLoadSpriteAtlas
|
||||
{
|
||||
@@ -30,13 +30,13 @@ public class TestLoadSpriteAtlas
|
||||
var spriteAtlas = assetHandle.AssetObject as SpriteAtlas;
|
||||
Assert.IsNotNull(spriteAtlas);
|
||||
|
||||
var sprite1 = spriteAtlas.GetSprite("bullet");
|
||||
var sprite1 = spriteAtlas.GetSprite("sprite_a");
|
||||
Assert.IsNotNull(sprite1);
|
||||
|
||||
var sprite2 = spriteAtlas.GetSprite("pause");
|
||||
var sprite2 = spriteAtlas.GetSprite("sprite_b");
|
||||
Assert.IsNotNull(sprite2);
|
||||
|
||||
var sprite3 = spriteAtlas.GetSprite("rocket");
|
||||
var sprite3 = spriteAtlas.GetSprite("sprite_c");
|
||||
Assert.IsNotNull(sprite3);
|
||||
assetHandle.Release();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
using YooAsset;
|
||||
|
||||
/// <summary>
|
||||
/// ArchiveBundle 解密器
|
||||
/// </summary>
|
||||
public class TestArchiveBundleDecryptor : IBundleMemoryDecryptor
|
||||
{
|
||||
byte[] IBundleMemoryDecryptor.GetDecryptedData(BundleDecryptArgs args)
|
||||
{
|
||||
byte[] data = args.FileData;
|
||||
if (data == null)
|
||||
data = FileUtility.ReadAllBytes(args.FilePath);
|
||||
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
data[i] ^= TestArchiveBundleEncryptor.KEY;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2ae99256961d47c09ef5a633f5d48c68
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.IO;
|
||||
using YooAsset;
|
||||
|
||||
/// <summary>
|
||||
/// ArchiveBundle 加密器
|
||||
/// </summary>
|
||||
public class TestArchiveBundleEncryptor : IBundleEncryptor
|
||||
{
|
||||
public const byte KEY = 0x5A;
|
||||
|
||||
public BundleEncryptResult Encrypt(BundleEncryptArgs fileInfo)
|
||||
{
|
||||
string bundleName = fileInfo.BundleName.ToLowerInvariant();
|
||||
if (bundleName.Contains("_testres6_encryptfiles_") == false)
|
||||
return new BundleEncryptResult(false, null);
|
||||
|
||||
byte[] fileData = File.ReadAllBytes(fileInfo.FilePath);
|
||||
for (int i = 0; i < fileData.Length; i++)
|
||||
{
|
||||
fileData[i] ^= KEY;
|
||||
}
|
||||
return new BundleEncryptResult(true, fileData);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using YooAsset;
|
||||
|
||||
/// <summary>
|
||||
/// AssetBundle 解密器
|
||||
/// </summary>
|
||||
public class TestAssetBundleDecryptor : IBundleMemoryDecryptor
|
||||
{
|
||||
byte[] IBundleMemoryDecryptor.GetDecryptedData(BundleDecryptArgs args)
|
||||
{
|
||||
byte[] data = args.FileData;
|
||||
if (data == null)
|
||||
data = FileUtility.ReadAllBytes(args.FilePath);
|
||||
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
data[i] ^= TestAssetBundleEncryptor.KEY;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 502b8de579fc3e04ab0c61064b344b50
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,26 @@
|
||||
using System.IO;
|
||||
using YooAsset;
|
||||
|
||||
/// <summary>
|
||||
/// AssetBundle 加密器
|
||||
/// </summary>
|
||||
public class TestAssetBundleEncryptor : IBundleEncryptor
|
||||
{
|
||||
public const byte KEY = 0x5A;
|
||||
|
||||
public BundleEncryptResult Encrypt(BundleEncryptArgs fileInfo)
|
||||
{
|
||||
string bundleName = fileInfo.BundleName.ToLowerInvariant();
|
||||
if (bundleName.Contains("_testres_encryptfiles_") == false &&
|
||||
bundleName.Contains("_testres3_importfiles_") == false &&
|
||||
bundleName.Contains("_testres3_unpackfiles_") == false)
|
||||
return new BundleEncryptResult(false, null);
|
||||
|
||||
byte[] fileData = File.ReadAllBytes(fileInfo.FilePath);
|
||||
for (int i = 0; i < fileData.Length; i++)
|
||||
{
|
||||
fileData[i] ^= KEY;
|
||||
}
|
||||
return new BundleEncryptResult(true, fileData);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 09c441a23eaa4be486ad910c9dcfa401
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,123 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using YooAsset;
|
||||
|
||||
/// <summary>
|
||||
/// XOR 解密文件流,读取时自动对每个字节执行异或解密
|
||||
/// </summary>
|
||||
public class TestBundleStream : FileStream
|
||||
{
|
||||
public const byte KEY = 64;
|
||||
|
||||
public TestBundleStream(string path, FileMode mode, FileAccess access, FileShare share) : base(path, mode, access, share)
|
||||
{
|
||||
}
|
||||
public TestBundleStream(string path, FileMode mode) : base(path, mode)
|
||||
{
|
||||
}
|
||||
public override int Read(byte[] array, int offset, int count)
|
||||
{
|
||||
var index = base.Read(array, offset, count);
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
array[i] ^= KEY;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 流模式 XOR 加密器,对 TestRes3 目录的 Bundle 进行逐字节异或加密
|
||||
/// </summary>
|
||||
public class TestFileStreamEncryption : IBundleEncryptor
|
||||
{
|
||||
public BundleEncryptResult Encrypt(BundleEncryptArgs fileInfo)
|
||||
{
|
||||
// 说明:对TestRes3资源目录进行加密
|
||||
if (fileInfo.BundleName.Contains("_testres3_"))
|
||||
{
|
||||
var fileData = File.ReadAllBytes(fileInfo.FilePath);
|
||||
for (int i = 0; i < fileData.Length; i++)
|
||||
{
|
||||
fileData[i] ^= TestBundleStream.KEY;
|
||||
}
|
||||
|
||||
return new BundleEncryptResult(true, fileData);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new BundleEncryptResult(false, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 偏移模式加密器,在 Bundle 文件头部插入固定长度的空白偏移
|
||||
/// </summary>
|
||||
public class TestFileOffsetEncryption : IBundleEncryptor
|
||||
{
|
||||
public BundleEncryptResult Encrypt(BundleEncryptArgs fileInfo)
|
||||
{
|
||||
// 说明:对TestRes3资源目录进行加密
|
||||
if (fileInfo.BundleName.Contains("_testres3_"))
|
||||
{
|
||||
int offset = 32;
|
||||
byte[] fileData = File.ReadAllBytes(fileInfo.FilePath);
|
||||
var encryptedData = new byte[fileData.Length + offset];
|
||||
Buffer.BlockCopy(fileData, 0, encryptedData, offset, fileData.Length);
|
||||
|
||||
return new BundleEncryptResult(true, encryptedData);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new BundleEncryptResult(false, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 偏移模式解密器,返回固定的文件偏移量以跳过加密头
|
||||
/// </summary>
|
||||
public class TestFileOffsetDecryption : IBundleOffsetDecryptor
|
||||
{
|
||||
private const long FILE_OFFSET = 32;
|
||||
|
||||
long IBundleOffsetDecryptor.GetFileOffset(BundleDecryptArgs args)
|
||||
{
|
||||
return FILE_OFFSET;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 内存模式 XOR 解密器,将整个 Bundle 读入内存后逐字节异或解密
|
||||
/// </summary>
|
||||
public class TestFileMemoryDecryption : IBundleMemoryDecryptor
|
||||
{
|
||||
byte[] IBundleMemoryDecryptor.GetDecryptedData(BundleDecryptArgs args)
|
||||
{
|
||||
byte[] data = args.FileData;
|
||||
|
||||
// 注意:如果数据为空,自行加载文件数据。
|
||||
if (data == null)
|
||||
data = FileUtility.ReadAllBytes(args.FilePath);
|
||||
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
data[i] ^= TestBundleStream.KEY;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 流模式解密器,返回 TestBundleStream 实现读取时自动解密
|
||||
/// </summary>
|
||||
public class TestFileStreamDecryption : IBundleStreamDecryptor
|
||||
{
|
||||
Stream IBundleStreamDecryptor.CreateDecryptionStream(BundleDecryptArgs args)
|
||||
{
|
||||
var fileStream = new TestBundleStream(args.FilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
return fileStream;
|
||||
}
|
||||
|
||||
int IBundleStreamDecryptor.GetBufferSize(BundleDecryptArgs args)
|
||||
{
|
||||
return 1024;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using YooAsset;
|
||||
|
||||
/// <summary>
|
||||
/// 资源清单解密器
|
||||
/// </summary>
|
||||
public class TestManifestDecryptor : IManifestDecryptor
|
||||
{
|
||||
byte[] IManifestDecryptor.Decrypt(byte[] fileData)
|
||||
{
|
||||
return TestXorCrypto.Crypto(fileData, TestManifestEncryptor.KEY);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6c2d2ff26d5d4d4d9ac08ba6a420d3f1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,27 +1,17 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Collections;
|
||||
using YooAsset;
|
||||
|
||||
/// <summary>
|
||||
/// 测试用清单加密器,使用 XOR 方式加密清单数据
|
||||
/// 资源清单加密器
|
||||
/// </summary>
|
||||
public class TestManifestEncryptor : IManifestEncryptor
|
||||
{
|
||||
public const string KEY = "YOO";
|
||||
|
||||
byte[] IManifestEncryptor.Encrypt(byte[] fileData)
|
||||
{
|
||||
return TestXorCrypto.Crypto(fileData, "YOO");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试用清单解密器,使用 XOR 方式解密清单数据
|
||||
/// </summary>
|
||||
public class TestManifestDecryptor : IManifestDecryptor
|
||||
{
|
||||
byte[] IManifestDecryptor.Decrypt(byte[] fileData)
|
||||
{
|
||||
return TestXorCrypto.Crypto(fileData, "YOO");
|
||||
return TestXorCrypto.Crypto(fileData, KEY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +52,7 @@ public class TestXorCrypto
|
||||
/// <returns>处理后的字节数组</returns>
|
||||
public static byte[] Crypto(byte[] data, string key)
|
||||
{
|
||||
byte[] keyBytes = System.Text.Encoding.UTF8.GetBytes(key);
|
||||
byte[] keyBytes = Encoding.UTF8.GetBytes(key);
|
||||
return Crypto(data, keyBytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using YooAsset;
|
||||
|
||||
/// <summary>
|
||||
/// RawBundle 解密器
|
||||
/// </summary>
|
||||
public class TestRawBundleDecryptor : IBundleMemoryDecryptor
|
||||
{
|
||||
byte[] IBundleMemoryDecryptor.GetDecryptedData(BundleDecryptArgs args)
|
||||
{
|
||||
byte[] data = args.FileData;
|
||||
if (data == null)
|
||||
data = FileUtility.ReadAllBytes(args.FilePath);
|
||||
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
data[i] ^= TestRawBundleEncryptor.KEY;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7bf91e81ab6e85b4eb4f478fcd1e7261
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.IO;
|
||||
using YooAsset;
|
||||
|
||||
/// <summary>
|
||||
/// RawBundle 加密器
|
||||
/// </summary>
|
||||
public class TestRawBundleEncryptor : IBundleEncryptor
|
||||
{
|
||||
public const byte KEY = 0x6B;
|
||||
|
||||
public BundleEncryptResult Encrypt(BundleEncryptArgs fileInfo)
|
||||
{
|
||||
string bundleName = fileInfo.BundleName.ToLowerInvariant();
|
||||
if (bundleName.Contains("_testres5_encryptfiles_") == false)
|
||||
return new BundleEncryptResult(false, null);
|
||||
|
||||
byte[] fileData = File.ReadAllBytes(fileInfo.FilePath);
|
||||
for (int i = 0; i < fileData.Length; i++)
|
||||
{
|
||||
fileData[i] ^= KEY;
|
||||
}
|
||||
return new BundleEncryptResult(true, fileData);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d84195bebf934e44b8d73d46ba0ce838
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -170,26 +170,30 @@ public class T0_InitYooAssets : IPrebuildSetup, IPostBuildCleanup
|
||||
{
|
||||
var collector1 = new YooAsset.Editor.BundleCollector();
|
||||
collector1.CollectPath = "";
|
||||
collector1.CollectorGUID = "e082d492b9da65e499cee3495be3645d"; //TestRes3/encrypt目录
|
||||
collector1.CollectorGUID = "e082d492b9da65e499cee3495be3645d"; //TestRes/EncryptFiles目录
|
||||
collector1.CollectorType = YooAsset.Editor.ECollectorType.MainAssetCollector;
|
||||
collector1.PackRuleName = nameof(YooAsset.Editor.PackSeparately);
|
||||
YooAsset.Editor.BundleCollectorSettingData.CreateCollector(encryptGroup, collector1);
|
||||
}
|
||||
|
||||
// 拷贝测试文件
|
||||
var copyGroup = YooAsset.Editor.BundleCollectorSettingData.CreateGroup(testPackage, "CopyGroup");
|
||||
{
|
||||
var collector1 = new YooAsset.Editor.BundleCollector();
|
||||
collector1.CollectPath = "";
|
||||
collector1.CollectorGUID = "35f454fb80a715047bcf0ce30c7c4f18"; //TestRes3/ImportFiles目录
|
||||
collector1.CollectorType = YooAsset.Editor.ECollectorType.MainAssetCollector;
|
||||
collector1.AssetTags = "import";
|
||||
collector1.PackRuleName = nameof(YooAsset.Editor.PackSeparately);
|
||||
YooAsset.Editor.BundleCollectorSettingData.CreateCollector(copyGroup, collector1);
|
||||
|
||||
var collector2 = new YooAsset.Editor.BundleCollector();
|
||||
collector2.CollectPath = "";
|
||||
collector2.CollectorGUID = "35f454fb80a715047bcf0ce30c7c4f18"; //TestRes3/import目录
|
||||
collector2.CollectorGUID = "401af1ca0abf3ae4594631e5f71bfe27"; //TestRes3/UnpackFiles目录
|
||||
collector2.CollectorType = YooAsset.Editor.ECollectorType.MainAssetCollector;
|
||||
collector2.AssetTags = "import";
|
||||
collector2.AssetTags = "unpack";
|
||||
collector2.PackRuleName = nameof(YooAsset.Editor.PackSeparately);
|
||||
YooAsset.Editor.BundleCollectorSettingData.CreateCollector(encryptGroup, collector2);
|
||||
|
||||
var collector3 = new YooAsset.Editor.BundleCollector();
|
||||
collector3.CollectPath = "";
|
||||
collector3.CollectorGUID = "401af1ca0abf3ae4594631e5f71bfe27"; //TestRes3/unpack目录
|
||||
collector3.CollectorType = YooAsset.Editor.ECollectorType.MainAssetCollector;
|
||||
collector3.AssetTags = "unpack";
|
||||
collector3.PackRuleName = nameof(YooAsset.Editor.PackSeparately);
|
||||
YooAsset.Editor.BundleCollectorSettingData.CreateCollector(encryptGroup, collector3);
|
||||
YooAsset.Editor.BundleCollectorSettingData.CreateCollector(copyGroup, collector2);
|
||||
}
|
||||
|
||||
// 卸载测试文件
|
||||
@@ -230,10 +234,17 @@ public class T0_InitYooAssets : IPrebuildSetup, IPostBuildCleanup
|
||||
{
|
||||
var collector1 = new YooAsset.Editor.BundleCollector();
|
||||
collector1.CollectPath = "";
|
||||
collector1.CollectorGUID = "fddaaf9430e24344196cc82ac3d006b4"; //TestRes/RawFiles目录
|
||||
collector1.CollectorGUID = "fddaaf9430e24344196cc82ac3d006b4"; //TestRes5/RawFiles目录
|
||||
collector1.CollectorType = YooAsset.Editor.ECollectorType.MainAssetCollector;
|
||||
collector1.PackRuleName = nameof(YooAsset.Editor.PackRawFile);
|
||||
YooAsset.Editor.BundleCollectorSettingData.CreateCollector(rawFileGroup, collector1);
|
||||
|
||||
var collector2 = new YooAsset.Editor.BundleCollector();
|
||||
collector2.CollectPath = "";
|
||||
collector2.CollectorGUID = "9378c52809165094cb532c1678355a3c"; //TestRes5/EncryptFiles目录
|
||||
collector2.CollectorType = YooAsset.Editor.ECollectorType.MainAssetCollector;
|
||||
collector2.PackRuleName = nameof(YooAsset.Editor.PackRawFile);
|
||||
YooAsset.Editor.BundleCollectorSettingData.CreateCollector(rawFileGroup, collector2);
|
||||
}
|
||||
}
|
||||
private static void CreateArchiveBundlePackageCollector()
|
||||
@@ -247,10 +258,17 @@ public class T0_InitYooAssets : IPrebuildSetup, IPostBuildCleanup
|
||||
{
|
||||
var collector1 = new YooAsset.Editor.BundleCollector();
|
||||
collector1.CollectPath = "";
|
||||
collector1.CollectorGUID = "c0444018376a7cd4ead6a671035617d6"; //TestRes/ArchiveFiles目录
|
||||
collector1.CollectorGUID = "c0444018376a7cd4ead6a671035617d6"; //TestRes6/ArchiveFiles目录
|
||||
collector1.CollectorType = YooAsset.Editor.ECollectorType.MainAssetCollector;
|
||||
collector1.PackRuleName = nameof(YooAsset.Editor.PackCollector);
|
||||
YooAsset.Editor.BundleCollectorSettingData.CreateCollector(archiveFileGroup, collector1);
|
||||
|
||||
var collector2 = new YooAsset.Editor.BundleCollector();
|
||||
collector2.CollectPath = "";
|
||||
collector2.CollectorGUID = "5bf4f68676550434291dbdee4da52f65"; //TestRes6/EncryptFiles目录
|
||||
collector2.CollectorType = YooAsset.Editor.ECollectorType.MainAssetCollector;
|
||||
collector2.PackRuleName = nameof(YooAsset.Editor.PackCollector);
|
||||
YooAsset.Editor.BundleCollectorSettingData.CreateCollector(archiveFileGroup, collector2);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -23,7 +23,7 @@ public class T1_TestEditorFileSystem : IPrebuildSetup, IPostBuildCleanup
|
||||
void IPrebuildSetup.Setup()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
// 构建资源包
|
||||
// 构建 AssetBundlePackage
|
||||
{
|
||||
var simulateParams = new PackageBuildParameters(TestConsts.AssetBundlePackageName);
|
||||
simulateParams.BuildPipelineName = "EditorSimulateBuildPipeline";
|
||||
@@ -35,7 +35,7 @@ public class T1_TestEditorFileSystem : IPrebuildSetup, IPostBuildCleanup
|
||||
UnityEditor.EditorPrefs.SetString(ASSET_BUNDLE_PACKAGE_ROOT_KEY, simulateResult.PackageRootDirectory);
|
||||
}
|
||||
|
||||
// 构建原生资源包
|
||||
// 构建 RawBundlePackage
|
||||
{
|
||||
var simulateParams = new PackageBuildParameters(TestConsts.RawBundlePackageName);
|
||||
simulateParams.BuildPipelineName = "EditorSimulateBuildPipeline";
|
||||
@@ -47,7 +47,7 @@ public class T1_TestEditorFileSystem : IPrebuildSetup, IPostBuildCleanup
|
||||
UnityEditor.EditorPrefs.SetString(RAW_BUNDLE_PACKAGE_ROOT_KEY, simulateResult.PackageRootDirectory);
|
||||
}
|
||||
|
||||
// 构建归档资源包
|
||||
// 构建 ArchiveBundlePackage
|
||||
{
|
||||
var simulateParams = new PackageBuildParameters(TestConsts.ArchiveBundlePackageName);
|
||||
simulateParams.BuildPipelineName = "EditorSimulateBuildPipeline";
|
||||
@@ -68,7 +68,7 @@ public class T1_TestEditorFileSystem : IPrebuildSetup, IPostBuildCleanup
|
||||
[UnityTest]
|
||||
public IEnumerator A_InitializePackage()
|
||||
{
|
||||
// 初始化资源包 ASSET_BUNDLE
|
||||
// 初始化 AssetBundlePackage
|
||||
{
|
||||
string packageRoot = string.Empty;
|
||||
#if UNITY_EDITOR
|
||||
@@ -104,7 +104,7 @@ public class T1_TestEditorFileSystem : IPrebuildSetup, IPostBuildCleanup
|
||||
Assert.AreEqual(EOperationStatus.Succeeded, loadPackageManifestOp.Status);
|
||||
}
|
||||
|
||||
// 初始化资源包 RAW_BUNDLE
|
||||
// 初始化 RawBundlePackage
|
||||
{
|
||||
string packageRoot = string.Empty;
|
||||
#if UNITY_EDITOR
|
||||
@@ -140,7 +140,7 @@ public class T1_TestEditorFileSystem : IPrebuildSetup, IPostBuildCleanup
|
||||
Assert.AreEqual(EOperationStatus.Succeeded, loadPackageManifestOp.Status);
|
||||
}
|
||||
|
||||
// 初始化资源包 ARCHIVE_BUNDLE
|
||||
// 初始化 ArchiveBundlePackage
|
||||
{
|
||||
string packageRoot = string.Empty;
|
||||
#if UNITY_EDITOR
|
||||
@@ -248,9 +248,9 @@ public class T1_TestEditorFileSystem : IPrebuildSetup, IPostBuildCleanup
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator B11_TestLoadRawFileObject()
|
||||
public IEnumerator B11_TestLoadRawBundle()
|
||||
{
|
||||
var tester = new TestLoadRawFileObject();
|
||||
var tester = new TestLoadRawBundle();
|
||||
yield return tester.RuntimeTester();
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ public class T2_TestBuiltinFileSystem : IPrebuildSetup, IPostBuildCleanup
|
||||
void IPrebuildSetup.Setup()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
// 构建AssetBundlePackage
|
||||
// 构建 AssetBundlePackage
|
||||
{
|
||||
var buildParams = new PackageBuildParameters(TestConsts.AssetBundlePackageName);
|
||||
buildParams.BuildPipelineName = "ScriptableBuildPipeline";
|
||||
@@ -34,7 +34,7 @@ public class T2_TestBuiltinFileSystem : IPrebuildSetup, IPostBuildCleanup
|
||||
UnityEditor.EditorPrefs.SetString(ASSET_BUNDLE_PACKAGE_ROOT_KEY, simulateResult.PackageRootDirectory);
|
||||
}
|
||||
|
||||
// 构建RawBundlePackage
|
||||
// 构建 RawBundlePackage
|
||||
{
|
||||
var buildParams = new PackageBuildParameters(TestConsts.RawBundlePackageName);
|
||||
buildParams.BuildPipelineName = "RawFileBuildPipeline";
|
||||
@@ -45,7 +45,7 @@ public class T2_TestBuiltinFileSystem : IPrebuildSetup, IPostBuildCleanup
|
||||
UnityEditor.EditorPrefs.SetString(RAW_BUNDLE_PACKAGE_ROOT_KEY, simulateResult.PackageRootDirectory);
|
||||
}
|
||||
|
||||
// 构建ArchiveBundlePackage
|
||||
// 构建 ArchiveBundlePackage
|
||||
{
|
||||
var buildParams = new PackageBuildParameters(TestConsts.ArchiveBundlePackageName);
|
||||
buildParams.BuildPipelineName = "ArchiveFileBuildPipeline";
|
||||
@@ -65,7 +65,7 @@ public class T2_TestBuiltinFileSystem : IPrebuildSetup, IPostBuildCleanup
|
||||
[UnityTest]
|
||||
public IEnumerator A_InitializePackage()
|
||||
{
|
||||
// 初始化资源包 ASSET_BUNDLE
|
||||
// 初始化 AssetBundlePackage
|
||||
{
|
||||
string packageRoot = string.Empty;
|
||||
#if UNITY_EDITOR
|
||||
@@ -81,7 +81,7 @@ public class T2_TestBuiltinFileSystem : IPrebuildSetup, IPostBuildCleanup
|
||||
var manifestServices = new TestManifestDecryptor();
|
||||
initParams.BuiltinFileSystemParameters = FileSystemParameters.CreateDefaultBuiltinFileSystemParameters(packageRoot);
|
||||
initParams.BuiltinFileSystemParameters.AddParameter(EFileSystemParameter.ManifestDecryptor, manifestServices);
|
||||
initParams.BuiltinFileSystemParameters.AddParameter(EFileSystemParameter.AssetbundleDecryptor, new TestFileStreamDecryption());
|
||||
initParams.BuiltinFileSystemParameters.AddParameter(EFileSystemParameter.AssetBundleDecryptor, new TestAssetBundleDecryptor());
|
||||
var initializeOp = package.InitializePackageAsync(initParams);
|
||||
yield return initializeOp;
|
||||
if (initializeOp.Status != EOperationStatus.Succeeded)
|
||||
@@ -104,7 +104,7 @@ public class T2_TestBuiltinFileSystem : IPrebuildSetup, IPostBuildCleanup
|
||||
Assert.AreEqual(EOperationStatus.Succeeded, loadPackageManifestOp.Status);
|
||||
}
|
||||
|
||||
// 初始化资源包 RAW_BUNDLE
|
||||
// 初始化 RawBundlePackage
|
||||
{
|
||||
string packageRoot = string.Empty;
|
||||
#if UNITY_EDITOR
|
||||
@@ -118,6 +118,7 @@ public class T2_TestBuiltinFileSystem : IPrebuildSetup, IPostBuildCleanup
|
||||
// 初始化资源包
|
||||
var initParams = new OfflinePlayModeOptions();
|
||||
initParams.BuiltinFileSystemParameters = FileSystemParameters.CreateDefaultBuiltinFileSystemParameters(packageRoot);
|
||||
initParams.BuiltinFileSystemParameters.AddParameter(EFileSystemParameter.RawBundleDecryptor, new TestRawBundleDecryptor());
|
||||
var initializeOp = package.InitializePackageAsync(initParams);
|
||||
yield return initializeOp;
|
||||
if (initializeOp.Status != EOperationStatus.Succeeded)
|
||||
@@ -140,7 +141,7 @@ public class T2_TestBuiltinFileSystem : IPrebuildSetup, IPostBuildCleanup
|
||||
Assert.AreEqual(EOperationStatus.Succeeded, loadPackageManifestOp.Status);
|
||||
}
|
||||
|
||||
// 初始化资源包 ARCHIVE_BUNDLE
|
||||
// 初始化 ArchiveBundlePackage
|
||||
{
|
||||
string packageRoot = string.Empty;
|
||||
#if UNITY_EDITOR
|
||||
@@ -154,6 +155,7 @@ public class T2_TestBuiltinFileSystem : IPrebuildSetup, IPostBuildCleanup
|
||||
// 初始化资源包
|
||||
var initParams = new OfflinePlayModeOptions();
|
||||
initParams.BuiltinFileSystemParameters = FileSystemParameters.CreateDefaultBuiltinFileSystemParameters(packageRoot);
|
||||
initParams.BuiltinFileSystemParameters.AddParameter(EFileSystemParameter.ArchiveBundleDecryptor, new TestArchiveBundleDecryptor());
|
||||
var initializeOp = package.InitializePackageAsync(initParams);
|
||||
yield return initializeOp;
|
||||
if (initializeOp.Status != EOperationStatus.Succeeded)
|
||||
@@ -248,9 +250,9 @@ public class T2_TestBuiltinFileSystem : IPrebuildSetup, IPostBuildCleanup
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator B11_TestLoadRawFileObject()
|
||||
public IEnumerator B11_TestLoadRawBundle()
|
||||
{
|
||||
var tester = new TestLoadRawFileObject();
|
||||
var tester = new TestLoadRawBundle();
|
||||
yield return tester.RuntimeTester();
|
||||
}
|
||||
|
||||
@@ -290,9 +292,9 @@ public class T2_TestBuiltinFileSystem : IPrebuildSetup, IPostBuildCleanup
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator C01_TestBundleEncryption()
|
||||
public IEnumerator C01_TestAssetBundleDecryption()
|
||||
{
|
||||
var tester = new TestBundleEncryption();
|
||||
var tester = new TestAssetBundleDecryption();
|
||||
yield return tester.RuntimeTester();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,30 +1,32 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using NUnit.Framework;
|
||||
using YooAsset;
|
||||
|
||||
/// <summary>
|
||||
/// 测试加载加密文件
|
||||
/// 测试加载加密的 AssetBundle 资源
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 覆盖 API: LoadAssetAsync / LoadAssetSync / InstantiateSync
|
||||
/// 测试内容:
|
||||
/// 1. 异步加载加密的预制体(prefab_encryptA),验证加载成功并实例化
|
||||
/// 2. 同步加载加密的预制体(prefab_encryptB),验证加载成功并实例化
|
||||
/// 1. 使用 Memory 解密器加载加密预制体(prefab_encrypt_x / prefab_encrypt_y)
|
||||
/// </remarks>
|
||||
public class TestBundleEncryption
|
||||
public class TestAssetBundleDecryption
|
||||
{
|
||||
public IEnumerator RuntimeTester()
|
||||
{
|
||||
ResourcePackage package = YooAssets.GetPackage(TestConsts.AssetBundlePackageName);
|
||||
Assert.IsNotNull(package);
|
||||
|
||||
yield return TestEncryptedPrefabPair(package, "prefab_encrypt_x", "prefab_encrypt_y");
|
||||
}
|
||||
private IEnumerator TestEncryptedPrefabPair(ResourcePackage package, string asyncLocation, string syncLocation)
|
||||
{
|
||||
Assert.IsNotNull(package);
|
||||
|
||||
// 异步加载加密的预制体
|
||||
// 说明:测试内置文件解压
|
||||
{
|
||||
var assetHandle = package.LoadAssetAsync<GameObject>("prefab_encryptA");
|
||||
var assetHandle = package.LoadAssetAsync<GameObject>(asyncLocation);
|
||||
yield return assetHandle;
|
||||
Assert.AreEqual(EOperationStatus.Succeeded, assetHandle.Status);
|
||||
|
||||
@@ -36,9 +38,8 @@ public class TestBundleEncryption
|
||||
}
|
||||
|
||||
// 同步加载加密的预制体
|
||||
// 说明:测试内置文件解压
|
||||
{
|
||||
var assetHandle = package.LoadAssetSync<GameObject>("prefab_encryptB");
|
||||
var assetHandle = package.LoadAssetSync<GameObject>(syncLocation);
|
||||
Assert.AreEqual(EOperationStatus.Succeeded, assetHandle.Status);
|
||||
|
||||
var options = new InstantiateOptions(true, Vector3.zero, Quaternion.identity);
|
||||
@@ -48,4 +49,4 @@ public class TestBundleEncryption
|
||||
assetHandle.Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,7 +34,11 @@ public class T3_TestCacheFileSystem : IPrebuildSetup, IPostBuildCleanup
|
||||
if (Directory.Exists(cacheRoot))
|
||||
Directory.Delete(cacheRoot, true);
|
||||
|
||||
// 拷贝打包资源到本地服务器
|
||||
// 清空旧的本地服务器测试目录
|
||||
if (Directory.Exists(TestConsts.TestServerDirectory))
|
||||
Directory.Delete(TestConsts.TestServerDirectory, true);
|
||||
|
||||
// 拷贝 AssetBundlePackage 到本地服务器
|
||||
{
|
||||
string packageRoot = string.Empty;
|
||||
#if UNITY_EDITOR
|
||||
@@ -46,7 +50,31 @@ public class T3_TestCacheFileSystem : IPrebuildSetup, IPostBuildCleanup
|
||||
CopyDirectory(packageRoot, TestConsts.TestServerDirectory);
|
||||
}
|
||||
|
||||
// 初始化资源包 ASSET_BUNDLE
|
||||
// 拷贝 RawBundlePackage 到本地服务器
|
||||
{
|
||||
string packageRoot = string.Empty;
|
||||
#if UNITY_EDITOR
|
||||
packageRoot = UnityEditor.EditorPrefs.GetString(T2_TestBuiltinFileSystem.RAW_BUNDLE_PACKAGE_ROOT_KEY);
|
||||
#endif
|
||||
if (Directory.Exists(packageRoot) == false)
|
||||
throw new Exception($"Not found package root : {packageRoot}");
|
||||
|
||||
CopyDirectory(packageRoot, TestConsts.TestServerDirectory);
|
||||
}
|
||||
|
||||
// 拷贝 ArchiveBundlePackage 到本地服务器
|
||||
{
|
||||
string packageRoot = string.Empty;
|
||||
#if UNITY_EDITOR
|
||||
packageRoot = UnityEditor.EditorPrefs.GetString(T2_TestBuiltinFileSystem.ARCHIVE_BUNDLE_PACKAGE_ROOT_KEY);
|
||||
#endif
|
||||
if (Directory.Exists(packageRoot) == false)
|
||||
throw new Exception($"Not found package root : {packageRoot}");
|
||||
|
||||
CopyDirectory(packageRoot, TestConsts.TestServerDirectory);
|
||||
}
|
||||
|
||||
// 初始化 AssetBundlePackage
|
||||
{
|
||||
var package = YooAssets.CreatePackage(TestConsts.AssetBundlePackageName);
|
||||
|
||||
@@ -58,7 +86,71 @@ public class T3_TestCacheFileSystem : IPrebuildSetup, IPostBuildCleanup
|
||||
initParams.BuiltinFileSystemParameters = null;
|
||||
initParams.CacheFileSystemParameters = FileSystemParameters.CreateDefaultSandboxFileSystemParameters(remoteService);
|
||||
initParams.CacheFileSystemParameters.AddParameter(EFileSystemParameter.ManifestDecryptor, manifestServices);
|
||||
initParams.CacheFileSystemParameters.AddParameter(EFileSystemParameter.AssetbundleDecryptor, new TestFileStreamDecryption());
|
||||
initParams.CacheFileSystemParameters.AddParameter(EFileSystemParameter.AssetBundleDecryptor, new TestAssetBundleDecryptor());
|
||||
var initializeOp = package.InitializePackageAsync(initParams);
|
||||
yield return initializeOp;
|
||||
if (initializeOp.Status != EOperationStatus.Succeeded)
|
||||
Debug.LogError(initializeOp.Error);
|
||||
Assert.AreEqual(EOperationStatus.Succeeded, initializeOp.Status);
|
||||
|
||||
// 请求资源版本
|
||||
var requestVersionOp = package.RequestPackageVersionAsync();
|
||||
yield return requestVersionOp;
|
||||
if (requestVersionOp.Status != EOperationStatus.Succeeded)
|
||||
Debug.LogError(requestVersionOp.Error);
|
||||
Assert.AreEqual(EOperationStatus.Succeeded, requestVersionOp.Status);
|
||||
|
||||
// 更新资源清单
|
||||
var loadPackageManifestOptions = new LoadPackageManifestOptions(requestVersionOp.PackageVersion, 60);
|
||||
var loadPackageManifestOp = package.LoadPackageManifestAsync(loadPackageManifestOptions);
|
||||
yield return loadPackageManifestOp;
|
||||
if (loadPackageManifestOp.Status != EOperationStatus.Succeeded)
|
||||
Debug.LogError(loadPackageManifestOp.Error);
|
||||
Assert.AreEqual(EOperationStatus.Succeeded, loadPackageManifestOp.Status);
|
||||
}
|
||||
|
||||
// 初始化 RawBundlePackage
|
||||
{
|
||||
var package = YooAssets.CreatePackage(TestConsts.RawBundlePackageName);
|
||||
|
||||
// 初始化资源包
|
||||
var initParams = new HostPlayModeOptions();
|
||||
var remoteService = new TestRemoteService(TestConsts.TestServerURL);
|
||||
initParams.BuiltinFileSystemParameters = null;
|
||||
initParams.CacheFileSystemParameters = FileSystemParameters.CreateDefaultSandboxFileSystemParameters(remoteService);
|
||||
initParams.CacheFileSystemParameters.AddParameter(EFileSystemParameter.RawBundleDecryptor, new TestRawBundleDecryptor());
|
||||
var initializeOp = package.InitializePackageAsync(initParams);
|
||||
yield return initializeOp;
|
||||
if (initializeOp.Status != EOperationStatus.Succeeded)
|
||||
Debug.LogError(initializeOp.Error);
|
||||
Assert.AreEqual(EOperationStatus.Succeeded, initializeOp.Status);
|
||||
|
||||
// 请求资源版本
|
||||
var requestVersionOp = package.RequestPackageVersionAsync();
|
||||
yield return requestVersionOp;
|
||||
if (requestVersionOp.Status != EOperationStatus.Succeeded)
|
||||
Debug.LogError(requestVersionOp.Error);
|
||||
Assert.AreEqual(EOperationStatus.Succeeded, requestVersionOp.Status);
|
||||
|
||||
// 更新资源清单
|
||||
var loadPackageManifestOptions = new LoadPackageManifestOptions(requestVersionOp.PackageVersion, 60);
|
||||
var loadPackageManifestOp = package.LoadPackageManifestAsync(loadPackageManifestOptions);
|
||||
yield return loadPackageManifestOp;
|
||||
if (loadPackageManifestOp.Status != EOperationStatus.Succeeded)
|
||||
Debug.LogError(loadPackageManifestOp.Error);
|
||||
Assert.AreEqual(EOperationStatus.Succeeded, loadPackageManifestOp.Status);
|
||||
}
|
||||
|
||||
// 初始化 ArchiveBundlePackage
|
||||
{
|
||||
var package = YooAssets.CreatePackage(TestConsts.ArchiveBundlePackageName);
|
||||
|
||||
// 初始化资源包
|
||||
var initParams = new HostPlayModeOptions();
|
||||
var remoteService = new TestRemoteService(TestConsts.TestServerURL);
|
||||
initParams.BuiltinFileSystemParameters = null;
|
||||
initParams.CacheFileSystemParameters = FileSystemParameters.CreateDefaultSandboxFileSystemParameters(remoteService);
|
||||
initParams.CacheFileSystemParameters.AddParameter(EFileSystemParameter.ArchiveBundleDecryptor, new TestArchiveBundleDecryptor());
|
||||
var initializeOp = package.InitializePackageAsync(initParams);
|
||||
yield return initializeOp;
|
||||
if (initializeOp.Status != EOperationStatus.Succeeded)
|
||||
@@ -120,14 +212,182 @@ public class T3_TestCacheFileSystem : IPrebuildSetup, IPostBuildCleanup
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator C04_TestClearCache()
|
||||
public IEnumerator D01_TestAsyncTask()
|
||||
{
|
||||
var tester = new TestAsyncTask();
|
||||
yield return tester.RuntimeTester();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator D02_TestAsyncCompleted()
|
||||
{
|
||||
var tester = new TestAsyncCompleted();
|
||||
yield return tester.RuntimeTester();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator D03_TestLoadAsset()
|
||||
{
|
||||
var tester = new TestLoadAsset();
|
||||
yield return tester.RuntimeTester();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator D04_TestLoadSubAssets()
|
||||
{
|
||||
var tester = new TestLoadSubAssets();
|
||||
yield return tester.RuntimeTester();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator D05_TestLoadAllAssets()
|
||||
{
|
||||
var tester = new TestLoadAllAssets();
|
||||
yield return tester.RuntimeTester();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator D06_TestLoadGameObject()
|
||||
{
|
||||
var tester = new TestLoadGameObject();
|
||||
yield return tester.RuntimeTester();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator D07_TestLoadSpriteAtlas()
|
||||
{
|
||||
var tester = new TestLoadSpriteAtlas();
|
||||
yield return tester.RuntimeTester();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator D08_TestLoadScriptableObject()
|
||||
{
|
||||
var tester = new TestLoadScriptableObject();
|
||||
yield return tester.RuntimeTester();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator D09_TestLoadScene()
|
||||
{
|
||||
var tester = new TestLoadScene();
|
||||
yield return tester.RuntimeTester();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator D10_TestLoadBundleFile()
|
||||
{
|
||||
var tester = new TestLoadBundleFile();
|
||||
yield return tester.RuntimeTester();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator D11_TestLoadRawBundle()
|
||||
{
|
||||
var tester = new TestLoadRawBundle();
|
||||
yield return tester.RuntimeTester();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator D12_TestLoadArchiveBundle()
|
||||
{
|
||||
var tester = new TestLoadArchiveBundle();
|
||||
yield return tester.RuntimeTester();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator D13_TestEnsureBundleFile_RawBundle()
|
||||
{
|
||||
var tester = new TestEnsureBundleFile();
|
||||
yield return tester.RuntimeTester_RawBundle();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator D14_TestEnsureBundleFile_AssetBundle()
|
||||
{
|
||||
var tester = new TestEnsureBundleFile();
|
||||
yield return tester.RuntimeTester_AssetBundle();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator D15_TestEnsureBundleFile_ArchiveBundle()
|
||||
{
|
||||
var tester = new TestEnsureBundleFile();
|
||||
yield return tester.RuntimeTester_ArchiveBundle();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator D16_TestUniTask()
|
||||
{
|
||||
var tester = new TestUniTask();
|
||||
yield return tester.RuntimeTester();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator E01_TestGetPackageInfo()
|
||||
{
|
||||
var tester = new TestGetPackageInfo();
|
||||
yield return tester.RuntimeTester();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator E02_TestGetAssetInfo()
|
||||
{
|
||||
var tester = new TestGetAssetInfo();
|
||||
yield return tester.RuntimeTester();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator E03_TestIsLocationValid()
|
||||
{
|
||||
var tester = new TestIsLocationValid();
|
||||
yield return tester.RuntimeTester();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator E04_TestLoadInvalidAsset()
|
||||
{
|
||||
var tester = new TestLoadInvalidAsset();
|
||||
yield return tester.RuntimeTester();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator E05_TestDuplicateLoad()
|
||||
{
|
||||
var tester = new TestDuplicateLoad();
|
||||
yield return tester.RuntimeTester();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator E06_TestHandleRelease()
|
||||
{
|
||||
var tester = new TestHandleRelease();
|
||||
yield return tester.RuntimeTester();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator E07_TestBundleFileRelease()
|
||||
{
|
||||
var tester = new TestBundleFileRelease();
|
||||
yield return tester.RuntimeTester();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator E08_TestUnloadAllAssets()
|
||||
{
|
||||
var tester = new TestUnloadAllAssets();
|
||||
yield return tester.RuntimeTester();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator F01_TestClearCache()
|
||||
{
|
||||
var tester = new TestClearCache();
|
||||
yield return tester.RuntimeTester();
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator C05_TestClearManifest()
|
||||
public IEnumerator F02_TestClearManifest()
|
||||
{
|
||||
var tester = new TestClearManifest();
|
||||
yield return tester.RuntimeTester();
|
||||
@@ -137,7 +397,7 @@ public class T3_TestCacheFileSystem : IPrebuildSetup, IPostBuildCleanup
|
||||
public IEnumerator Z_DestroyPackage()
|
||||
{
|
||||
var tester = new TestDestroyPackage();
|
||||
yield return tester.RuntimeTester(false);
|
||||
yield return tester.RuntimeTester(true, true);
|
||||
}
|
||||
|
||||
private static void CopyDirectory(string sourceDir, string targetDir)
|
||||
|
||||
@@ -12,8 +12,8 @@ using YooAsset;
|
||||
/// 覆盖 API: GetDownloadSize / LoadAssetAsync / LoadAssetSync / UnloadUnusedAssetsAsync
|
||||
/// 测试内容:
|
||||
/// 1. 验证目标远端资源的下载大小非零(尚未缓存)
|
||||
/// 2. 异步加载远端资源(prefab_encryptA),验证首次加载触发下载并最终成功
|
||||
/// 3. 同步加载远端资源(prefab_encryptB),首次应失败并触发后台下载
|
||||
/// 2. 异步加载远端资源(prefab_encrypt_x),验证首次加载触发下载并最终成功
|
||||
/// 3. 同步加载远端资源(prefab_encrypt_y),首次应失败并触发后台下载
|
||||
/// 4. 释放失败的 Handle 并清理资源,等待下载完成后再次同步加载,验证成功
|
||||
/// </remarks>
|
||||
public class TestBundlePlaying
|
||||
@@ -23,18 +23,18 @@ public class TestBundlePlaying
|
||||
ResourcePackage package = YooAssets.GetPackage(TestConsts.AssetBundlePackageName);
|
||||
Assert.IsNotNull(package);
|
||||
|
||||
if (package.GetDownloadSize("prefab_encryptA") == 0)
|
||||
if (package.GetDownloadSize("prefab_encrypt_x") == 0)
|
||||
{
|
||||
Assert.Fail("Load bundle is already existed !");
|
||||
}
|
||||
if (package.GetDownloadSize("prefab_encryptB") == 0)
|
||||
if (package.GetDownloadSize("prefab_encrypt_y") == 0)
|
||||
{
|
||||
Assert.Fail("Load bundle is already existed !");
|
||||
}
|
||||
|
||||
// 测试异步加载远端资源
|
||||
{
|
||||
var assetsHandle = package.LoadAssetAsync<GameObject>("prefab_encryptA");
|
||||
var assetsHandle = package.LoadAssetAsync<GameObject>("prefab_encrypt_x");
|
||||
yield return assetsHandle;
|
||||
Assert.AreEqual(EOperationStatus.Succeeded, assetsHandle.Status);
|
||||
assetsHandle.Release();
|
||||
@@ -45,7 +45,7 @@ public class TestBundlePlaying
|
||||
{
|
||||
// 验证失败结果
|
||||
UnityEngine.TestTools.LogAssert.ignoreFailingMessages = true;
|
||||
var assetsHandle = package.LoadAssetSync<GameObject>("prefab_encryptB");
|
||||
var assetsHandle = package.LoadAssetSync<GameObject>("prefab_encrypt_y");
|
||||
UnityEngine.TestTools.LogAssert.ignoreFailingMessages = false;
|
||||
Assert.AreEqual(EOperationStatus.Failed, assetsHandle.Status);
|
||||
|
||||
@@ -57,7 +57,7 @@ public class TestBundlePlaying
|
||||
// 验证成功结果
|
||||
yield return new WaitForSeconds(1f);
|
||||
UnityEngine.TestTools.LogAssert.ignoreFailingMessages = true;
|
||||
assetsHandle = package.LoadAssetSync<GameObject>("prefab_encryptB");
|
||||
assetsHandle = package.LoadAssetSync<GameObject>("prefab_encrypt_y");
|
||||
UnityEngine.TestTools.LogAssert.ignoreFailingMessages = false;
|
||||
Assert.AreEqual(EOperationStatus.Succeeded, assetsHandle.Status);
|
||||
assetsHandle.Release();
|
||||
|
||||
@@ -30,12 +30,12 @@ public class TestClearCache
|
||||
|
||||
// ---- 1. ClearBundleFilesByLocations ----
|
||||
{
|
||||
var options = new ClearCacheOptions(ClearCacheMethods.ClearBundleFilesByLocations, "prefab_encryptA");
|
||||
var options = new ClearCacheOptions(ClearCacheMethods.ClearBundleFilesByLocations, "prefab_encrypt_x");
|
||||
var clearOp = package.ClearCacheAsync(options);
|
||||
yield return clearOp;
|
||||
Assert.AreEqual(EOperationStatus.Succeeded, clearOp.Status);
|
||||
|
||||
Assert.Greater(package.GetDownloadSize("prefab_encryptA"), 0);
|
||||
Assert.Greater(package.GetDownloadSize("prefab_encrypt_x"), 0);
|
||||
}
|
||||
|
||||
// ---- 2. ClearBundleFilesByTags ----
|
||||
@@ -53,7 +53,7 @@ public class TestClearCache
|
||||
yield return clearOp;
|
||||
Assert.AreEqual(EOperationStatus.Succeeded, clearOp.Status);
|
||||
|
||||
Assert.Greater(package.GetDownloadSize("prefab_encryptA"), 0);
|
||||
Assert.Greater(package.GetDownloadSize("prefab_encrypt_x"), 0);
|
||||
}
|
||||
|
||||
// ---- 4. ClearAllBundleFiles ----
|
||||
|
||||
@@ -12,17 +12,24 @@ using YooAsset;
|
||||
/// 测试内容:
|
||||
/// 1. 创建资源下载器,验证需要下载的资源数量非零
|
||||
/// 2. 启动下载并等待完成,验证下载状态为成功
|
||||
/// 3. 覆盖 AssetBundle、RawBundle 和 ArchiveBundle 三个包裹
|
||||
/// </remarks>
|
||||
public class TestResourceDownloader
|
||||
{
|
||||
public IEnumerator RuntimeTester()
|
||||
{
|
||||
ResourcePackage package = YooAssets.GetPackage(TestConsts.AssetBundlePackageName);
|
||||
yield return DownloadPackage(TestConsts.AssetBundlePackageName);
|
||||
yield return DownloadPackage(TestConsts.RawBundlePackageName);
|
||||
yield return DownloadPackage(TestConsts.ArchiveBundlePackageName);
|
||||
}
|
||||
private IEnumerator DownloadPackage(string packageName)
|
||||
{
|
||||
ResourcePackage package = YooAssets.GetPackage(packageName);
|
||||
Assert.IsNotNull(package);
|
||||
|
||||
var options = new ResourceDownloaderOptions(10, 1);
|
||||
var downloader = package.CreateResourceDownloader(options);
|
||||
Assert.AreNotEqual(0, downloader.TotalDownloadCount);
|
||||
Assert.AreNotEqual(0, downloader.TotalDownloadCount, $"{packageName} no files need to download.");
|
||||
|
||||
downloader.StartDownload();
|
||||
yield return downloader;
|
||||
|
||||
@@ -29,13 +29,13 @@ public class TestResourceImporter
|
||||
string fileRoot = $"{packageDir.Parent.FullName}/OutputCache";
|
||||
|
||||
var fileInfoA = new ImportBundleInfo(
|
||||
filePath: $"{fileRoot}/assets_samples_test_sample_testres3_import_prefab_importa.bundle.encrypt",
|
||||
bundleName: "assets_samples_test_sample_testres3_import_prefab_importa.bundle",
|
||||
filePath: $"{fileRoot}/assets_samples_test_sample_testres3_importfiles_prefab_import_a.bundle.encrypt",
|
||||
bundleName: "assets_samples_test_sample_testres3_importfiles_prefab_import_a.bundle",
|
||||
bundleGuid: null);
|
||||
|
||||
var fileInfoB = new ImportBundleInfo(
|
||||
filePath: $"{fileRoot}/assets_samples_test_sample_testres3_import_prefab_importb.bundle.encrypt",
|
||||
bundleName: "assets_samples_test_sample_testres3_import_prefab_importb.bundle",
|
||||
filePath: $"{fileRoot}/assets_samples_test_sample_testres3_importfiles_prefab_import_b.bundle.encrypt",
|
||||
bundleName: "assets_samples_test_sample_testres3_importfiles_prefab_import_b.bundle",
|
||||
bundleGuid: null);
|
||||
|
||||
ImportBundleInfo[] importInfos = { fileInfoA, fileInfoB };
|
||||
|
||||
@@ -10,7 +10,7 @@ GameObject:
|
||||
m_Component:
|
||||
- component: {fileID: 1740794871874781600}
|
||||
m_Layer: 0
|
||||
m_Name: prefab_encryptA
|
||||
m_Name: prefab_encrypt_x
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
@@ -10,7 +10,7 @@ GameObject:
|
||||
m_Component:
|
||||
- component: {fileID: 1740794871874781600}
|
||||
m_Layer: 0
|
||||
m_Name: prefab_encryptB
|
||||
m_Name: prefab_encrypt_y
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
@@ -46,9 +46,9 @@ SpriteAtlas:
|
||||
- {fileID: 21300000, guid: fcab35236e33438448805a9211b0cc19, type: 3}
|
||||
- {fileID: 21300000, guid: 3b8db7241fc8ff54e9dea6fc64cfd7e5, type: 3}
|
||||
m_PackedSpriteNamesToIndex:
|
||||
- pause
|
||||
- bullet
|
||||
- rocket
|
||||
- sprite_b
|
||||
- sprite_a
|
||||
- sprite_c
|
||||
m_RenderDataMap: {}
|
||||
m_Tag: atlas_icon
|
||||
m_IsVariant: 0
|
||||
|
||||
|
Before Width: | Height: | Size: 111 KiB After Width: | Height: | Size: 111 KiB |
|
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 104 KiB |
|
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 106 KiB |
@@ -10,7 +10,7 @@ GameObject:
|
||||
m_Component:
|
||||
- component: {fileID: 7029742931587134142}
|
||||
m_Layer: 0
|
||||
m_Name: prefab_unpackA
|
||||
m_Name: prefab_import_a
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
@@ -10,7 +10,7 @@ GameObject:
|
||||
m_Component:
|
||||
- component: {fileID: 7029742931587134142}
|
||||
m_Layer: 0
|
||||
m_Name: prefab_unpackB
|
||||
m_Name: prefab_import_b
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
@@ -10,7 +10,7 @@ GameObject:
|
||||
m_Component:
|
||||
- component: {fileID: 7029742931587134142}
|
||||
m_Layer: 0
|
||||
m_Name: prefab_importA
|
||||
m_Name: prefab_unpack_a
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
@@ -10,7 +10,7 @@ GameObject:
|
||||
m_Component:
|
||||
- component: {fileID: 7029742931587134142}
|
||||
m_Layer: 0
|
||||
m_Name: prefab_importB
|
||||
m_Name: prefab_unpack_b
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
8
Assets/YooAsset/Samples~/Test Sample/TestRes5.meta
Normal file
8
Assets/YooAsset/Samples~/Test Sample/TestRes5.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: caefa9a20bd10f54395f8ea2900d1977
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9378c52809165094cb532c1678355a3c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1 @@
|
||||
this is raw file x !
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e3bf9fcab5b44514bb6aaf7a0e700ce3
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1 @@
|
||||
this is raw file y !
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 913cf046bcd71c641a1cf6f1fd900491
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2b4e5ebf72945ef4d87639537fc14dbb
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/YooAsset/Samples~/Test Sample/TestRes6.meta
Normal file
8
Assets/YooAsset/Samples~/Test Sample/TestRes6.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a8b52fc9f8f300d4788b43e8122c89f6
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user