yoo2.2,9
This commit is contained in:
Alex-Rachel
2025-01-25 13:46:17 +08:00
parent 634a392a1f
commit 6166fd24c6
584 changed files with 15684 additions and 11714 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,121 @@
using UnityEngine;
namespace YooAsset
{
internal class AssetBundleLoadAllAssetsOperation : FSLoadAllAssetsOperation
{
protected enum ESteps
{
None,
CheckBundle,
LoadAsset,
CheckResult,
Done,
}
private readonly PackageBundle _packageBundle;
private readonly AssetBundle _assetBundle;
private readonly AssetInfo _assetInfo;
private AssetBundleRequest _request;
private ESteps _steps = ESteps.None;
public AssetBundleLoadAllAssetsOperation(PackageBundle packageBundle, AssetBundle assetBundle, AssetInfo assetInfo)
{
_packageBundle = packageBundle;
_assetBundle = assetBundle;
_assetInfo = assetInfo;
}
internal override void InternalOnStart()
{
_steps = ESteps.CheckBundle;
}
internal override void InternalOnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.CheckBundle)
{
if (_assetBundle == null)
{
_steps = ESteps.Done;
Error = $"The bundle {_packageBundle.BundleName} has been destroyed due to unity engine bugs !";
Status = EOperationStatus.Failed;
return;
}
_steps = ESteps.LoadAsset;
}
if (_steps == ESteps.LoadAsset)
{
if (IsWaitForAsyncComplete)
{
if (_assetInfo.AssetType == null)
Result = _assetBundle.LoadAllAssets();
else
Result = _assetBundle.LoadAllAssets(_assetInfo.AssetType);
}
else
{
if (_assetInfo.AssetType == null)
_request = _assetBundle.LoadAllAssetsAsync();
else
_request = _assetBundle.LoadAllAssetsAsync(_assetInfo.AssetType);
}
_steps = ESteps.CheckResult;
}
if (_steps == ESteps.CheckResult)
{
if (_request != null)
{
if (IsWaitForAsyncComplete)
{
// 强制挂起主线程(注意:该操作会很耗时)
YooLogger.Warning("Suspend the main thread to load unity asset.");
Result = _request.allAssets;
}
else
{
Progress = _request.progress;
if (_request.isDone == false)
return;
Result = _request.allAssets;
}
}
if (Result == null)
{
string error;
if (_assetInfo.AssetType == null)
error = $"Failed to load all assets : {_assetInfo.AssetPath} AssetType : null AssetBundle : {_packageBundle.BundleName}";
else
error = $"Failed to load all assets : {_assetInfo.AssetPath} AssetType : {_assetInfo.AssetType} AssetBundle : {_packageBundle.BundleName}";
YooLogger.Error(error);
_steps = ESteps.Done;
Error = error;
Status = EOperationStatus.Failed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
}
}
internal override void InternalWaitForAsyncComplete()
{
while (true)
{
if (ExecuteWhileDone())
{
_steps = ESteps.Done;
break;
}
}
}
}
}

View File

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

View File

@@ -0,0 +1,121 @@
using UnityEngine;
namespace YooAsset
{
internal class AssetBundleLoadAssetOperation : FSLoadAssetOperation
{
protected enum ESteps
{
None,
CheckBundle,
LoadAsset,
CheckResult,
Done,
}
private readonly PackageBundle _packageBundle;
private readonly AssetBundle _assetBundle;
private readonly AssetInfo _assetInfo;
private AssetBundleRequest _request;
private ESteps _steps = ESteps.None;
public AssetBundleLoadAssetOperation(PackageBundle packageBundle, AssetBundle assetBundle, AssetInfo assetInfo)
{
_packageBundle = packageBundle;
_assetBundle = assetBundle;
_assetInfo = assetInfo;
}
internal override void InternalOnStart()
{
_steps = ESteps.CheckBundle;
}
internal override void InternalOnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.CheckBundle)
{
if (_assetBundle == null)
{
_steps = ESteps.Done;
Error = $"The bundle {_packageBundle.BundleName} has been destroyed due to unity engine bugs !";
Status = EOperationStatus.Failed;
return;
}
_steps = ESteps.LoadAsset;
}
if (_steps == ESteps.LoadAsset)
{
if (IsWaitForAsyncComplete)
{
if (_assetInfo.AssetType == null)
Result = _assetBundle.LoadAsset(_assetInfo.AssetPath);
else
Result = _assetBundle.LoadAsset(_assetInfo.AssetPath, _assetInfo.AssetType);
}
else
{
if (_assetInfo.AssetType == null)
_request = _assetBundle.LoadAssetAsync(_assetInfo.AssetPath);
else
_request = _assetBundle.LoadAssetAsync(_assetInfo.AssetPath, _assetInfo.AssetType);
}
_steps = ESteps.CheckResult;
}
if (_steps == ESteps.CheckResult)
{
if (_request != null)
{
if (IsWaitForAsyncComplete)
{
// 强制挂起主线程(注意:该操作会很耗时)
YooLogger.Warning("Suspend the main thread to load unity asset.");
Result = _request.asset;
}
else
{
Progress = _request.progress;
if (_request.isDone == false)
return;
Result = _request.asset;
}
}
if (Result == null)
{
string error;
if (_assetInfo.AssetType == null)
error = $"Failed to load asset : {_assetInfo.AssetPath} AssetType : null AssetBundle : {_packageBundle.BundleName}";
else
error = $"Failed to load asset : {_assetInfo.AssetPath} AssetType : {_assetInfo.AssetType} AssetBundle : {_packageBundle.BundleName}";
YooLogger.Error(error);
_steps = ESteps.Done;
Error = error;
Status = EOperationStatus.Failed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
}
}
internal override void InternalWaitForAsyncComplete()
{
while (true)
{
if (ExecuteWhileDone())
{
_steps = ESteps.Done;
break;
}
}
}
}
}

View File

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

View File

@@ -0,0 +1,117 @@
using UnityEngine;
using UnityEngine.SceneManagement;
namespace YooAsset
{
internal class AssetBundleLoadSceneOperation : FSLoadSceneOperation
{
protected enum ESteps
{
None,
LoadScene,
CheckResult,
Done,
}
private readonly AssetInfo _assetInfo;
private readonly LoadSceneParameters _loadParams;
private bool _suspendLoad;
private AsyncOperation _asyncOperation;
private ESteps _steps = ESteps.None;
public AssetBundleLoadSceneOperation(AssetInfo assetInfo, LoadSceneParameters loadParams, bool suspendLoad)
{
_assetInfo = assetInfo;
_loadParams = loadParams;
_suspendLoad = suspendLoad;
}
internal override void InternalOnStart()
{
_steps = ESteps.LoadScene;
}
internal override void InternalOnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.LoadScene)
{
if (IsWaitForAsyncComplete)
{
// 注意:场景同步加载方法不会立即加载场景,而是在下一帧加载。
Result = SceneManager.LoadScene(_assetInfo.AssetPath, _loadParams);
_steps = ESteps.CheckResult;
}
else
{
// 注意如果场景不存在异步加载方法返回NULL
// 注意:即使是异步加载也要在当帧获取到场景对象
_asyncOperation = SceneManager.LoadSceneAsync(_assetInfo.AssetPath, _loadParams);
if (_asyncOperation != null)
{
_asyncOperation.allowSceneActivation = !_suspendLoad;
_asyncOperation.priority = 100;
Result = SceneManager.GetSceneAt(SceneManager.sceneCount - 1);
_steps = ESteps.CheckResult;
}
else
{
string error = $"Failed to load scene : {_assetInfo.AssetPath}";
YooLogger.Error(error);
_steps = ESteps.Done;
Error = error;
Status = EOperationStatus.Failed;
}
}
}
if (_steps == ESteps.CheckResult)
{
if (_asyncOperation != null)
{
if (IsWaitForAsyncComplete)
{
//注意:场景加载无法强制异步转同步
YooLogger.Error("The scene is loading asyn !");
}
else
{
// 注意:在业务层中途可以取消挂起
if (_asyncOperation.allowSceneActivation == false)
{
if (_suspendLoad == false)
_asyncOperation.allowSceneActivation = true;
}
Progress = _asyncOperation.progress;
if (_asyncOperation.isDone == false)
return;
}
}
if (Result.IsValid())
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
else
{
string error = $"The loaded scene is invalid : {_assetInfo.AssetPath}";
YooLogger.Error(error);
_steps = ESteps.Done;
Error = error;
Status = EOperationStatus.Failed;
}
}
}
internal override void InternalWaitForAsyncComplete()
{
//TODO 场景加载不支持异步转同步,为了支持同步加载方法需要实现该方法!
InternalOnUpdate();
}
public override void UnSuspendLoad()
{
_suspendLoad = false;
}
}
}

View File

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

View File

@@ -0,0 +1,121 @@
using UnityEngine;
namespace YooAsset
{
internal class AssetBundleLoadSubAssetsOperation : FSLoadSubAssetsOperation
{
protected enum ESteps
{
None,
CheckBundle,
LoadAsset,
CheckResult,
Done,
}
private readonly PackageBundle _packageBundle;
private readonly AssetBundle _assetBundle;
private readonly AssetInfo _assetInfo;
private AssetBundleRequest _request;
private ESteps _steps = ESteps.None;
public AssetBundleLoadSubAssetsOperation(PackageBundle packageBundle, AssetBundle assetBundle, AssetInfo assetInfo)
{
_packageBundle = packageBundle;
_assetBundle = assetBundle;
_assetInfo = assetInfo;
}
internal override void InternalOnStart()
{
_steps = ESteps.CheckBundle;
}
internal override void InternalOnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.CheckBundle)
{
if (_assetBundle == null)
{
_steps = ESteps.Done;
Error = $"The bundle {_packageBundle.BundleName} has been destroyed due to unity engine bugs !";
Status = EOperationStatus.Failed;
return;
}
_steps = ESteps.LoadAsset;
}
if (_steps == ESteps.LoadAsset)
{
if (IsWaitForAsyncComplete)
{
if (_assetInfo.AssetType == null)
Result = _assetBundle.LoadAssetWithSubAssets(_assetInfo.AssetPath);
else
Result = _assetBundle.LoadAssetWithSubAssets(_assetInfo.AssetPath, _assetInfo.AssetType);
}
else
{
if (_assetInfo.AssetType == null)
_request = _assetBundle.LoadAssetWithSubAssetsAsync(_assetInfo.AssetPath);
else
_request = _assetBundle.LoadAssetWithSubAssetsAsync(_assetInfo.AssetPath, _assetInfo.AssetType);
}
_steps = ESteps.CheckResult;
}
if (_steps == ESteps.CheckResult)
{
if (_request != null)
{
if (IsWaitForAsyncComplete)
{
// 强制挂起主线程(注意:该操作会很耗时)
YooLogger.Warning("Suspend the main thread to load unity asset.");
Result = _request.allAssets;
}
else
{
Progress = _request.progress;
if (_request.isDone == false)
return;
Result = _request.allAssets;
}
}
if (Result == null)
{
string error;
if (_assetInfo.AssetType == null)
error = $"Failed to load sub assets : {_assetInfo.AssetPath} AssetType : null AssetBundle : {_packageBundle.BundleName}";
else
error = $"Failed to load sub assets : {_assetInfo.AssetPath} AssetType : {_assetInfo.AssetType} AssetBundle : {_packageBundle.BundleName}";
YooLogger.Error(error);
_steps = ESteps.Done;
Error = error;
Status = EOperationStatus.Failed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
}
}
internal override void InternalWaitForAsyncComplete()
{
while (true)
{
if (ExecuteWhileDone())
{
_steps = ESteps.Done;
break;
}
}
}
}
}

View File

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

View File

@@ -0,0 +1,48 @@
using UnityEngine.SceneManagement;
namespace YooAsset
{
internal abstract class BundleResult
{
/// <summary>
/// 卸载资源包文件
/// </summary>
public abstract void UnloadBundleFile();
/// <summary>
/// 获取资源包文件的路径
/// </summary>
public abstract string GetBundleFilePath();
/// <summary>
/// 读取资源包文件的二进制数据
/// </summary>
public abstract byte[] ReadBundleFileData();
/// <summary>
/// 读取资源包文件的文本数据
/// </summary>
public abstract string ReadBundleFileText();
/// <summary>
/// 加载资源包内的资源对象
/// </summary>
public abstract FSLoadAssetOperation LoadAssetAsync(AssetInfo assetInfo);
/// <summary>
/// 加载资源包内的所有资源对象
/// </summary>
public abstract FSLoadAllAssetsOperation LoadAllAssetsAsync(AssetInfo assetInfo);
/// <summary>
/// 加载资源包内的资源对象及所有子资源对象
/// </summary>
public abstract FSLoadSubAssetsOperation LoadSubAssetsAsync(AssetInfo assetInfo);
/// <summary>
/// 加载资源包内的场景对象
/// </summary>
public abstract FSLoadSceneOperation LoadSceneOperation(AssetInfo assetInfo, LoadSceneParameters loadParams, bool suspendLoad);
}
}

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,15 @@

namespace YooAsset
{
internal class RawBundleLoadAllAssetsOperation : FSLoadAllAssetsOperation
{
internal override void InternalOnStart()
{
Error = $"{nameof(RawBundleLoadAllAssetsOperation)} not support load all assets !";
Status = EOperationStatus.Failed;
}
internal override void InternalOnUpdate()
{
}
}
}

View File

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

View File

@@ -0,0 +1,15 @@

namespace YooAsset
{
internal class RawBundleLoadAssetOperation : FSLoadAssetOperation
{
internal override void InternalOnStart()
{
Error = $"{nameof(RawBundleLoadAssetOperation)} not support load asset !";
Status = EOperationStatus.Failed;
}
internal override void InternalOnUpdate()
{
}
}
}

View File

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

View File

@@ -0,0 +1,18 @@

namespace YooAsset
{
internal class RawBundleLoadSceneOperation : FSLoadSceneOperation
{
internal override void InternalOnStart()
{
Error = $"{nameof(RawBundleLoadSceneOperation)} not support load scene !";
Status = EOperationStatus.Failed;
}
internal override void InternalOnUpdate()
{
}
public override void UnSuspendLoad()
{
}
}
}

View File

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

View File

@@ -0,0 +1,15 @@

namespace YooAsset
{
internal class RawBundleLoadSubAssetsOperation : FSLoadSubAssetsOperation
{
internal override void InternalOnStart()
{
Error = $"{nameof(RawBundleLoadSubAssetsOperation)} not support load sub assets !";
Status = EOperationStatus.Failed;
}
internal override void InternalOnUpdate()
{
}
}
}

View File

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

View File

@@ -0,0 +1,57 @@
using UnityEngine.SceneManagement;
namespace YooAsset
{
internal class RawBundleResult : BundleResult
{
private readonly IFileSystem _fileSystem;
private readonly PackageBundle _packageBundle;
public RawBundleResult(IFileSystem fileSystem, PackageBundle packageBundle)
{
_fileSystem = fileSystem;
_packageBundle = packageBundle;
}
public override void UnloadBundleFile()
{
}
public override string GetBundleFilePath()
{
return _fileSystem.GetBundleFilePath(_packageBundle);
}
public override byte[] ReadBundleFileData()
{
return _fileSystem.ReadBundleFileData(_packageBundle);
}
public override string ReadBundleFileText()
{
return _fileSystem.ReadBundleFileText(_packageBundle);
}
public override FSLoadAssetOperation LoadAssetAsync(AssetInfo assetInfo)
{
var operation = new RawBundleLoadAssetOperation();
OperationSystem.StartOperation(_fileSystem.PackageName, operation);
return operation;
}
public override FSLoadAllAssetsOperation LoadAllAssetsAsync(AssetInfo assetInfo)
{
var operation = new RawBundleLoadAllAssetsOperation();
OperationSystem.StartOperation(_fileSystem.PackageName, operation);
return operation;
}
public override FSLoadSubAssetsOperation LoadSubAssetsAsync(AssetInfo assetInfo)
{
var operation = new RawBundleLoadSubAssetsOperation();
OperationSystem.StartOperation(_fileSystem.PackageName, operation);
return operation;
}
public override FSLoadSceneOperation LoadSceneOperation(AssetInfo assetInfo, LoadSceneParameters loadParams, bool suspendLoad)
{
var operation = new RawBundleLoadSceneOperation();
OperationSystem.StartOperation(_fileSystem.PackageName, operation);
return operation;
}
}
}

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,122 @@
using System.Collections.Generic;
namespace YooAsset
{
internal class VirtualBundleLoadAllAssetsOperation : FSLoadAllAssetsOperation
{
protected enum ESteps
{
None,
CheckBundle,
LoadAsset,
CheckResult,
Done,
}
private readonly PackageBundle _packageBundle;
private readonly AssetInfo _assetInfo;
private ESteps _steps = ESteps.None;
public VirtualBundleLoadAllAssetsOperation(PackageBundle packageBundle, AssetInfo assetInfo)
{
_packageBundle = packageBundle;
_assetInfo = assetInfo;
}
internal override void InternalOnStart()
{
#if UNITY_EDITOR
_steps = ESteps.CheckBundle;
#else
_steps = ESteps.Done;
Error = $"{nameof(VirtualBundleLoadAllAssetsOperation)} only support unity editor platform !";
Status = EOperationStatus.Failed;
#endif
}
internal override void InternalOnUpdate()
{
#if UNITY_EDITOR
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.CheckBundle)
{
// 检测资源文件是否存在
string guid = UnityEditor.AssetDatabase.AssetPathToGUID(_assetInfo.AssetPath);
if (string.IsNullOrEmpty(guid))
{
string error = $"Not found asset : {_assetInfo.AssetPath}";
YooLogger.Error(error);
_steps = ESteps.Done;
Error = error;
Status = EOperationStatus.Failed;
return;
}
_steps = ESteps.LoadAsset;
}
if (_steps == ESteps.LoadAsset)
{
if (_assetInfo.AssetType == null)
{
List<UnityEngine.Object> result = new List<UnityEngine.Object>();
foreach (var packageAsset in _packageBundle.IncludeMainAssets)
{
string assetPath = packageAsset.AssetPath;
UnityEngine.Object mainAsset = UnityEditor.AssetDatabase.LoadMainAssetAtPath(assetPath);
if (mainAsset != null)
result.Add(mainAsset);
}
Result = result.ToArray();
}
else
{
List<UnityEngine.Object> result = new List<UnityEngine.Object>();
foreach (var packageAsset in _packageBundle.IncludeMainAssets)
{
string assetPath = packageAsset.AssetPath;
UnityEngine.Object mainAsset = UnityEditor.AssetDatabase.LoadAssetAtPath(assetPath, _assetInfo.AssetType);
if (mainAsset != null)
result.Add(mainAsset);
}
Result = result.ToArray();
}
_steps = ESteps.CheckResult;
}
if (_steps == ESteps.CheckResult)
{
if (Result == null)
{
string error;
if (_assetInfo.AssetType == null)
error = $"Failed to load all assets : {_assetInfo.AssetPath} AssetType : null";
else
error = $"Failed to load all assets : {_assetInfo.AssetPath} AssetType : {_assetInfo.AssetType}";
YooLogger.Error(error);
_steps = ESteps.Done;
Error = error;
Status = EOperationStatus.Failed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
}
#endif
}
internal override void InternalWaitForAsyncComplete()
{
while (true)
{
if (ExecuteWhileDone())
{
_steps = ESteps.Done;
break;
}
}
}
}
}

View File

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

View File

@@ -0,0 +1,101 @@

namespace YooAsset
{
internal class VirtualBundleLoadAssetOperation : FSLoadAssetOperation
{
protected enum ESteps
{
None,
CheckBundle,
LoadAsset,
CheckResult,
Done,
}
private readonly PackageBundle _packageBundle;
private readonly AssetInfo _assetInfo;
private ESteps _steps = ESteps.None;
public VirtualBundleLoadAssetOperation(PackageBundle packageBundle, AssetInfo assetInfo)
{
_packageBundle = packageBundle;
_assetInfo = assetInfo;
}
internal override void InternalOnStart()
{
#if UNITY_EDITOR
_steps = ESteps.CheckBundle;
#else
_steps = ESteps.Done;
Error = $"{nameof(VirtualBundleLoadAssetOperation)} only support unity editor platform !";
Status = EOperationStatus.Failed;
#endif
}
internal override void InternalOnUpdate()
{
#if UNITY_EDITOR
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.CheckBundle)
{
// 检测资源文件是否存在
string guid = UnityEditor.AssetDatabase.AssetPathToGUID(_assetInfo.AssetPath);
if (string.IsNullOrEmpty(guid))
{
string error = $"Not found asset : {_assetInfo.AssetPath}";
YooLogger.Error(error);
_steps = ESteps.Done;
Error = error;
Status = EOperationStatus.Failed;
return;
}
_steps = ESteps.LoadAsset;
}
if (_steps == ESteps.LoadAsset)
{
if (_assetInfo.AssetType == null)
Result = UnityEditor.AssetDatabase.LoadMainAssetAtPath(_assetInfo.AssetPath);
else
Result = UnityEditor.AssetDatabase.LoadAssetAtPath(_assetInfo.AssetPath, _assetInfo.AssetType);
_steps = ESteps.CheckResult;
}
if (_steps == ESteps.CheckResult)
{
if (Result == null)
{
string error;
if (_assetInfo.AssetType == null)
error = $"Failed to load asset object : {_assetInfo.AssetPath} AssetType : null";
else
error = $"Failed to load asset object : {_assetInfo.AssetPath} AssetType : {_assetInfo.AssetType}";
YooLogger.Error(error);
_steps = ESteps.Done;
Error = error;
Status = EOperationStatus.Failed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
}
#endif
}
internal override void InternalWaitForAsyncComplete()
{
while (true)
{
if (ExecuteWhileDone())
{
_steps = ESteps.Done;
break;
}
}
}
}
}

View File

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

View File

@@ -0,0 +1,123 @@
using UnityEngine;
using UnityEngine.SceneManagement;
namespace YooAsset
{
internal class VirtualBundleLoadSceneOperation : FSLoadSceneOperation
{
protected enum ESteps
{
None,
LoadScene,
CheckResult,
Done,
}
private readonly AssetInfo _assetInfo;
private readonly LoadSceneParameters _loadParams;
private bool _suspendLoad;
private AsyncOperation _asyncOperation;
private ESteps _steps = ESteps.None;
public VirtualBundleLoadSceneOperation(AssetInfo assetInfo, LoadSceneParameters loadParams, bool suspendLoad)
{
_assetInfo = assetInfo;
_loadParams = loadParams;
_suspendLoad = suspendLoad;
}
internal override void InternalOnStart()
{
#if UNITY_EDITOR
_steps = ESteps.LoadScene;
#else
_steps = ESteps.Done;
Error = $"{nameof(VirtualBundleLoadSceneOperation)} only support unity editor platform !";
Status = EOperationStatus.Failed;
#endif
}
internal override void InternalOnUpdate()
{
#if UNITY_EDITOR
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.LoadScene)
{
if (IsWaitForAsyncComplete)
{
Result = UnityEditor.SceneManagement.EditorSceneManager.LoadSceneInPlayMode(_assetInfo.AssetPath, _loadParams);
_steps = ESteps.CheckResult;
}
else
{
_asyncOperation = UnityEditor.SceneManagement.EditorSceneManager.LoadSceneAsyncInPlayMode(_assetInfo.AssetPath, _loadParams);
if (_asyncOperation != null)
{
_asyncOperation.allowSceneActivation = !_suspendLoad;
_asyncOperation.priority = 100;
Result = SceneManager.GetSceneAt(SceneManager.sceneCount - 1);
_steps = ESteps.CheckResult;
}
else
{
string error = $"Failed to load scene : {_assetInfo.AssetPath}";
YooLogger.Error(error);
_steps = ESteps.Done;
Error = error;
Status = EOperationStatus.Failed;
return;
}
}
}
if (_steps == ESteps.CheckResult)
{
if (_asyncOperation != null)
{
if (IsWaitForAsyncComplete)
{
// 注意:场景加载无法强制异步转同步
YooLogger.Error("The scene is loading asyn !");
}
else
{
// 注意:在业务层中途可以取消挂起
if (_asyncOperation.allowSceneActivation == false)
{
if (_suspendLoad == false)
_asyncOperation.allowSceneActivation = true;
}
Progress = _asyncOperation.progress;
if (_asyncOperation.isDone == false)
return;
}
}
if (Result.IsValid())
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
else
{
string error = $"The loaded scene is invalid : {_assetInfo.AssetPath}";
YooLogger.Error(error);
_steps = ESteps.Done;
Error = error;
Status = EOperationStatus.Failed;
}
}
#endif
}
internal override void InternalWaitForAsyncComplete()
{
//TODO 场景加载不支持异步转同步,为了支持同步加载方法需要实现该方法!
InternalOnUpdate();
}
public override void UnSuspendLoad()
{
_suspendLoad = false;
}
}
}

View File

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

View File

@@ -0,0 +1,113 @@
using System.Collections.Generic;
namespace YooAsset
{
internal class VirtualBundleLoadSubAssetsOperation : FSLoadSubAssetsOperation
{
protected enum ESteps
{
None,
CheckBundle,
LoadAsset,
CheckResult,
Done,
}
private readonly PackageBundle _packageBundle;
private readonly AssetInfo _assetInfo;
private ESteps _steps = ESteps.None;
public VirtualBundleLoadSubAssetsOperation(PackageBundle packageBundle, AssetInfo assetInfo)
{
_packageBundle = packageBundle;
_assetInfo = assetInfo;
}
internal override void InternalOnStart()
{
#if UNITY_EDITOR
_steps = ESteps.CheckBundle;
#else
_steps = ESteps.Done;
Error = $"{nameof(VirtualBundleLoadSubAssetsOperation)} only support unity editor platform !";
Status = EOperationStatus.Failed;
#endif
}
internal override void InternalOnUpdate()
{
#if UNITY_EDITOR
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.CheckBundle)
{
// 检测资源文件是否存在
string guid = UnityEditor.AssetDatabase.AssetPathToGUID(_assetInfo.AssetPath);
if (string.IsNullOrEmpty(guid))
{
string error = $"Not found asset : {_assetInfo.AssetPath}";
YooLogger.Error(error);
_steps = ESteps.Done;
Error = error;
Status = EOperationStatus.Failed;
return;
}
_steps = ESteps.LoadAsset;
}
if (_steps == ESteps.LoadAsset)
{
if (_assetInfo.AssetType == null)
{
Result = UnityEditor.AssetDatabase.LoadAllAssetRepresentationsAtPath(_assetInfo.AssetPath);
}
else
{
UnityEngine.Object[] findAssets = UnityEditor.AssetDatabase.LoadAllAssetRepresentationsAtPath(_assetInfo.AssetPath);
List<UnityEngine.Object> result = new List<UnityEngine.Object>(findAssets.Length);
foreach (var findAsset in findAssets)
{
if (_assetInfo.AssetType.IsAssignableFrom(findAsset.GetType()))
result.Add(findAsset);
}
Result = result.ToArray();
}
_steps = ESteps.CheckResult;
}
if (_steps == ESteps.CheckResult)
{
if (Result == null)
{
string error;
if (_assetInfo.AssetType == null)
error = $"Failed to load sub assets : {_assetInfo.AssetPath} AssetType : null";
else
error = $"Failed to load sub assets : {_assetInfo.AssetPath} AssetType : {_assetInfo.AssetType}";
YooLogger.Error(error);
_steps = ESteps.Done;
Error = error;
Status = EOperationStatus.Failed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
}
#endif
}
internal override void InternalWaitForAsyncComplete()
{
while (true)
{
if (ExecuteWhileDone())
{
_steps = ESteps.Done;
break;
}
}
}
}
}

View File

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

View File

@@ -0,0 +1,57 @@
using UnityEngine.SceneManagement;
namespace YooAsset
{
internal class VirtualBundleResult : BundleResult
{
private readonly IFileSystem _fileSystem;
private readonly PackageBundle _packageBundle;
public VirtualBundleResult(IFileSystem fileSystem, PackageBundle bundle)
{
_fileSystem = fileSystem;
_packageBundle = bundle;
}
public override void UnloadBundleFile()
{
}
public override string GetBundleFilePath()
{
return _fileSystem.GetBundleFilePath(_packageBundle);
}
public override byte[] ReadBundleFileData()
{
return _fileSystem.ReadBundleFileData(_packageBundle);
}
public override string ReadBundleFileText()
{
return _fileSystem.ReadBundleFileText(_packageBundle);
}
public override FSLoadAssetOperation LoadAssetAsync(AssetInfo assetInfo)
{
var operation = new VirtualBundleLoadAssetOperation(_packageBundle, assetInfo);
OperationSystem.StartOperation(_fileSystem.PackageName, operation);
return operation;
}
public override FSLoadAllAssetsOperation LoadAllAssetsAsync(AssetInfo assetInfo)
{
var operation = new VirtualBundleLoadAllAssetsOperation(_packageBundle, assetInfo);
OperationSystem.StartOperation(_fileSystem.PackageName, operation);
return operation;
}
public override FSLoadSubAssetsOperation LoadSubAssetsAsync(AssetInfo assetInfo)
{
var operation = new VirtualBundleLoadSubAssetsOperation(_packageBundle, assetInfo);
OperationSystem.StartOperation(_fileSystem.PackageName, operation);
return operation;
}
public override FSLoadSceneOperation LoadSceneOperation(AssetInfo assetInfo, LoadSceneParameters loadParams, bool suspendLoad)
{
var operation = new VirtualBundleLoadSceneOperation(assetInfo, loadParams, suspendLoad);
OperationSystem.StartOperation(_fileSystem.PackageName, operation);
return operation;
}
}
}

View File

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

View File

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

View File

@@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace YooAsset
{
/// <summary>
/// 内置资源清单目录
/// </summary>
internal class DefaultBuildinFileCatalog : ScriptableObject
{
[Serializable]
public class FileWrapper
{
public string BundleGUID;
public string FileName;
public FileWrapper(string bundleGUID, string fileName)
{
BundleGUID = bundleGUID;
FileName = fileName;
}
}
/// <summary>
/// 包裹名称
/// </summary>
public string PackageName;
/// <summary>
/// 包裹版本
/// </summary>
public string PackageVersion;
/// <summary>
/// 文件列表
/// </summary>
public List<FileWrapper> Wrappers = new List<FileWrapper>();
}
}

View File

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

View File

@@ -0,0 +1,374 @@
using System;
using System.IO;
using System.Collections.Generic;
using UnityEngine;
namespace YooAsset
{
/// <summary>
/// 内置文件系统
/// </summary>
internal class DefaultBuildinFileSystem : IFileSystem
{
public class FileWrapper
{
public string FileName { private set; get; }
public FileWrapper(string fileName)
{
FileName = fileName;
}
}
protected readonly Dictionary<string, FileWrapper> _wrappers = new Dictionary<string, FileWrapper>(10000);
protected readonly Dictionary<string, string> _buildinFilePaths = new Dictionary<string, string>(10000);
protected IFileSystem _unpackFileSystem;
protected string _packageRoot;
/// <summary>
/// 包裹名称
/// </summary>
public string PackageName { private set; get; }
/// <summary>
/// 文件根目录
/// </summary>
public string FileRoot
{
get
{
return _packageRoot;
}
}
/// <summary>
/// 文件数量
/// </summary>
public int FileCount
{
get
{
return _wrappers.Count;
}
}
#region
/// <summary>
/// 自定义参数:初始化的时候缓存文件校验级别
/// </summary>
public EFileVerifyLevel FileVerifyLevel { private set; get; } = EFileVerifyLevel.Middle;
/// <summary>
/// 自定义参数:数据文件追加文件格式
/// </summary>
public bool AppendFileExtension { private set; get; } = false;
/// <summary>
/// 自定义参数禁用Catalog目录查询文件
/// </summary>
public bool DisableCatalogFile { private set; get; } = false;
/// <summary>
/// 自定义参数:解密方法类
/// </summary>
public IDecryptionServices DecryptionServices { private set; get; }
#endregion
public DefaultBuildinFileSystem()
{
}
public virtual FSInitializeFileSystemOperation InitializeFileSystemAsync()
{
var operation = new DBFSInitializeOperation(this);
OperationSystem.StartOperation(PackageName, operation);
return operation;
}
public virtual FSLoadPackageManifestOperation LoadPackageManifestAsync(string packageVersion, int timeout)
{
var operation = new DBFSLoadPackageManifestOperation(this, packageVersion);
OperationSystem.StartOperation(PackageName, operation);
return operation;
}
public virtual FSRequestPackageVersionOperation RequestPackageVersionAsync(bool appendTimeTicks, int timeout)
{
var operation = new DBFSRequestPackageVersionOperation(this);
OperationSystem.StartOperation(PackageName, operation);
return operation;
}
public virtual FSClearCacheFilesOperation ClearCacheFilesAsync(PackageManifest manifest, string clearMode, object clearParam)
{
return _unpackFileSystem.ClearCacheFilesAsync(manifest, clearMode, clearParam);
}
public virtual FSDownloadFileOperation DownloadFileAsync(PackageBundle bundle, DownloadParam param)
{
param.ImportFilePath = GetBuildinFileLoadPath(bundle);
return _unpackFileSystem.DownloadFileAsync(bundle, param);
}
public virtual FSLoadBundleOperation LoadBundleFile(PackageBundle bundle)
{
if (NeedUnpack(bundle))
{
return _unpackFileSystem.LoadBundleFile(bundle);
}
if (bundle.BundleType == (int)EBuildBundleType.AssetBundle)
{
var operation = new DBFSLoadAssetBundleOperation(this, bundle);
OperationSystem.StartOperation(PackageName, operation);
return operation;
}
else if (bundle.BundleType == (int)EBuildBundleType.RawBundle)
{
var operation = new DBFSLoadRawBundleOperation(this, bundle);
OperationSystem.StartOperation(PackageName, operation);
return operation;
}
else
{
string error = $"{nameof(DefaultBuildinFileSystem)} not support load bundle type : {bundle.BundleType}";
var operation = new FSLoadBundleCompleteOperation(error);
OperationSystem.StartOperation(PackageName, operation);
return operation;
}
}
public virtual void SetParameter(string name, object value)
{
if (name == FileSystemParametersDefine.FILE_VERIFY_LEVEL)
{
FileVerifyLevel = (EFileVerifyLevel)value;
}
else if (name == FileSystemParametersDefine.APPEND_FILE_EXTENSION)
{
AppendFileExtension = (bool)value;
}
else if (name == FileSystemParametersDefine.DISABLE_CATALOG_FILE)
{
DisableCatalogFile = (bool)value;
}
else if (name == FileSystemParametersDefine.DECRYPTION_SERVICES)
{
DecryptionServices = (IDecryptionServices)value;
}
else
{
YooLogger.Warning($"Invalid parameter : {name}");
}
}
public virtual void OnCreate(string packageName, string packageRoot)
{
PackageName = packageName;
if (string.IsNullOrEmpty(packageRoot))
_packageRoot = GetDefaultBuildinPackageRoot(packageName);
else
_packageRoot = packageRoot;
// 创建解压文件系统
var remoteServices = new DefaultUnpackRemoteServices(_packageRoot);
_unpackFileSystem = new DefaultUnpackFileSystem();
_unpackFileSystem.SetParameter(FileSystemParametersDefine.REMOTE_SERVICES, remoteServices);
_unpackFileSystem.SetParameter(FileSystemParametersDefine.FILE_VERIFY_LEVEL, FileVerifyLevel);
_unpackFileSystem.SetParameter(FileSystemParametersDefine.APPEND_FILE_EXTENSION, AppendFileExtension);
_unpackFileSystem.SetParameter(FileSystemParametersDefine.DECRYPTION_SERVICES, DecryptionServices);
_unpackFileSystem.OnCreate(packageName, null);
}
public virtual void OnUpdate()
{
_unpackFileSystem.OnUpdate();
}
public virtual bool Belong(PackageBundle bundle)
{
if (DisableCatalogFile)
return true;
return _wrappers.ContainsKey(bundle.BundleGUID);
}
public virtual bool Exists(PackageBundle bundle)
{
if (DisableCatalogFile)
return true;
return _wrappers.ContainsKey(bundle.BundleGUID);
}
public virtual bool NeedDownload(PackageBundle bundle)
{
return false;
}
public virtual bool NeedUnpack(PackageBundle bundle)
{
if (Belong(bundle) == false)
return false;
#if UNITY_ANDROID
return bundle.BundleType == (int)EBuildBundleType.RawBundle || bundle.Encrypted;
#else
return false;
#endif
}
public virtual bool NeedImport(PackageBundle bundle)
{
return false;
}
public virtual string GetBundleFilePath(PackageBundle bundle)
{
if (NeedUnpack(bundle))
return _unpackFileSystem.GetBundleFilePath(bundle);
return GetBuildinFileLoadPath(bundle);
}
public virtual byte[] ReadBundleFileData(PackageBundle bundle)
{
if (NeedUnpack(bundle))
return _unpackFileSystem.ReadBundleFileData(bundle);
if (Exists(bundle) == false)
return null;
if (bundle.Encrypted)
{
if (DecryptionServices == null)
{
YooLogger.Error($"The {nameof(IDecryptionServices)} is null !");
return null;
}
string filePath = GetBuildinFileLoadPath(bundle);
var fileInfo = new DecryptFileInfo()
{
BundleName = bundle.BundleName,
FileLoadCRC = bundle.UnityCRC,
FileLoadPath = filePath,
};
return DecryptionServices.ReadFileData(fileInfo);
}
else
{
string filePath = GetBuildinFileLoadPath(bundle);
return FileUtility.ReadAllBytes(filePath);
}
}
public virtual string ReadBundleFileText(PackageBundle bundle)
{
if (NeedUnpack(bundle))
return _unpackFileSystem.ReadBundleFileText(bundle);
if (Exists(bundle) == false)
return null;
if (bundle.Encrypted)
{
if (DecryptionServices == null)
{
YooLogger.Error($"The {nameof(IDecryptionServices)} is null !");
return null;
}
string filePath = GetBuildinFileLoadPath(bundle);
var fileInfo = new DecryptFileInfo()
{
BundleName = bundle.BundleName,
FileLoadCRC = bundle.UnityCRC,
FileLoadPath = filePath,
};
return DecryptionServices.ReadFileText(fileInfo);
}
else
{
string filePath = GetBuildinFileLoadPath(bundle);
return FileUtility.ReadAllText(filePath);
}
}
#region
protected string GetDefaultBuildinPackageRoot(string packageName)
{
string rootDirectory = YooAssetSettingsData.GetYooMobileBuildinRoot();
return PathUtility.Combine(rootDirectory, packageName);
}
public string GetBuildinFileLoadPath(PackageBundle bundle)
{
if (_buildinFilePaths.TryGetValue(bundle.BundleGUID, out string filePath) == false)
{
filePath = PathUtility.Combine(_packageRoot, bundle.FileName);
_buildinFilePaths.Add(bundle.BundleGUID, filePath);
}
return filePath;
}
public string GetBuildinPackageVersionFilePath()
{
string fileName = YooAssetSettingsData.GetPackageVersionFileName(PackageName);
return PathUtility.Combine(_packageRoot, fileName);
}
public string GetBuildinPackageHashFilePath(string packageVersion)
{
string fileName = YooAssetSettingsData.GetPackageHashFileName(PackageName, packageVersion);
return PathUtility.Combine(_packageRoot, fileName);
}
public string GetBuildinPackageManifestFilePath(string packageVersion)
{
string fileName = YooAssetSettingsData.GetManifestBinaryFileName(PackageName, packageVersion);
return PathUtility.Combine(_packageRoot, fileName);
}
public string GetCatalogFileLoadPath()
{
string fileName = Path.GetFileNameWithoutExtension(DefaultBuildinFileSystemDefine.BuildinCatalogFileName);
return YooAssetSettingsData.GetYooResourcesLoadPath(PackageName, fileName);
}
/// <summary>
/// 记录文件信息
/// </summary>
public bool RecordCatalogFile(string bundleGUID, FileWrapper wrapper)
{
if (_wrappers.ContainsKey(bundleGUID))
{
YooLogger.Error($"{nameof(DefaultBuildinFileSystem)} has element : {bundleGUID}");
return false;
}
_wrappers.Add(bundleGUID, wrapper);
return true;
}
/// <summary>
/// 初始化解压文件系统
/// </summary>
public FSInitializeFileSystemOperation InitializeUpackFileSystem()
{
return _unpackFileSystem.InitializeFileSystemAsync();
}
/// <summary>
/// 加载加密的资源文件
/// </summary>
public DecryptResult LoadEncryptedAssetBundle(PackageBundle bundle)
{
string filePath = GetBuildinFileLoadPath(bundle);
var fileInfo = new DecryptFileInfo()
{
BundleName = bundle.BundleName,
FileLoadCRC = bundle.UnityCRC,
FileLoadPath = filePath,
};
return DecryptionServices.LoadAssetBundle(fileInfo);
}
/// <summary>
/// 加载加密的资源文件
/// </summary>
public DecryptResult LoadEncryptedAssetBundleAsync(PackageBundle bundle)
{
string filePath = GetBuildinFileLoadPath(bundle);
var fileInfo = new DecryptFileInfo()
{
BundleName = bundle.BundleName,
FileLoadCRC = bundle.UnityCRC,
FileLoadPath = filePath,
};
return DecryptionServices.LoadAssetBundleAsync(fileInfo);
}
#endregion
}
}

View File

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

View File

@@ -0,0 +1,135 @@
#if UNITY_EDITOR
using System.Collections.Generic;
using System.IO;
using UnityEngine;
namespace YooAsset
{
public class DefaultBuildinFileSystemBuild : UnityEditor.Build.IPreprocessBuildWithReport
{
public int callbackOrder { get { return 0; } }
/// <summary>
/// 在构建应用程序前自动生成内置资源目录文件。
/// 原理搜索StreamingAssets目录下的所有资源文件然后将这些文件信息写入文件并存储在Resources目录下。
/// </summary>
public void OnPreprocessBuild(UnityEditor.Build.Reporting.BuildReport report)
{
YooLogger.Log("Begin to create catalog file !");
string savePath = YooAssetSettingsData.GetYooResourcesFullPath();
DirectoryInfo saveDirectory = new DirectoryInfo(savePath);
if (saveDirectory.Exists)
saveDirectory.Delete(true);
string rootPath = YooAssetSettingsData.GetYooEditorBuildinRoot();
DirectoryInfo rootDirectory = new DirectoryInfo(rootPath);
if (rootDirectory.Exists == false)
{
UnityEngine.Debug.LogWarning($"Can not found StreamingAssets root directory : {rootPath}");
return;
}
// 搜索所有Package目录
DirectoryInfo[] subDirectories = rootDirectory.GetDirectories();
foreach (var subDirectory in subDirectories)
{
CreateBuildinCatalogFile(subDirectory.Name, subDirectory.FullName);
}
}
/// <summary>
/// 生成包裹的内置资源目录文件
/// </summary>
public static void CreateBuildinCatalogFile(string packageName, string pacakgeDirectory)
{
// 获取资源清单版本
string packageVersion;
{
string versionFileName = YooAssetSettingsData.GetPackageVersionFileName(packageName);
string versionFilePath = $"{pacakgeDirectory}/{versionFileName}";
if (File.Exists(versionFilePath) == false)
{
throw new System.Exception($"Can not found package version file : {versionFilePath}");
}
packageVersion = FileUtility.ReadAllText(versionFilePath);
}
// 加载资源清单文件
PackageManifest packageManifest;
{
string manifestFileName = YooAssetSettingsData.GetManifestBinaryFileName(packageName, packageVersion);
string manifestFilePath = $"{pacakgeDirectory}/{manifestFileName}";
if (File.Exists(manifestFilePath) == false)
{
throw new System.Exception($"Can not found package manifest file : {manifestFilePath}");
}
var binaryData = FileUtility.ReadAllBytes(manifestFilePath);
packageManifest = ManifestTools.DeserializeFromBinary(binaryData);
}
// 获取文件名映射关系
Dictionary<string, string> fileMapping = new Dictionary<string, string>();
{
foreach (var packageBundle in packageManifest.BundleList)
{
fileMapping.Add(packageBundle.FileName, packageBundle.BundleGUID);
}
}
// 创建内置清单实例
var buildinFileCatalog = ScriptableObject.CreateInstance<DefaultBuildinFileCatalog>();
buildinFileCatalog.PackageName = packageName;
buildinFileCatalog.PackageVersion = packageVersion;
// 记录所有内置资源文件
DirectoryInfo rootDirectory = new DirectoryInfo(pacakgeDirectory);
FileInfo[] fileInfos = rootDirectory.GetFiles();
foreach (var fileInfo in fileInfos)
{
if (fileInfo.Extension == ".meta")
continue;
if (fileInfo.Name == "link.xml" || fileInfo.Name == "buildlogtep.json")
continue;
if (fileInfo.Name == $"{packageName}.version")
continue;
if (fileInfo.Name == $"{packageName}_{packageVersion}.bytes")
continue;
if (fileInfo.Name == $"{packageName}_{packageVersion}.hash")
continue;
if (fileInfo.Name == $"{packageName}_{packageVersion}.json")
continue;
if (fileInfo.Name == $"{packageName}_{packageVersion}.report")
continue;
string fileName = fileInfo.Name;
if (fileMapping.TryGetValue(fileName, out string bundleGUID))
{
var wrapper = new DefaultBuildinFileCatalog.FileWrapper(bundleGUID, fileName);
buildinFileCatalog.Wrappers.Add(wrapper);
}
else
{
Debug.LogWarning($"Failed mapping file : {fileName}");
}
}
string fullPath = YooAssetSettingsData.GetYooResourcesFullPath();
string saveFilePath = $"{fullPath}/{packageName}/{DefaultBuildinFileSystemDefine.BuildinCatalogFileName}";
FileUtility.CreateFileDirectory(saveFilePath);
UnityEditor.AssetDatabase.CreateAsset(buildinFileCatalog, saveFilePath);
UnityEditor.EditorUtility.SetDirty(buildinFileCatalog);
#if UNITY_2019
UnityEditor.AssetDatabase.SaveAssets();
#else
UnityEditor.AssetDatabase.SaveAssetIfDirty(buildinFileCatalog);
#endif
Debug.Log($"Succeed to save buildin file catalog : {saveFilePath}");
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,11 @@

namespace YooAsset
{
internal class DefaultBuildinFileSystemDefine
{
/// <summary>
/// 内置清单文件名称
/// </summary>
public const string BuildinCatalogFileName = "BuildinCatalog.asset";
}
}

View File

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

View File

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

View File

@@ -0,0 +1,101 @@
using System;
using System.IO;
namespace YooAsset
{
internal class DBFSInitializeOperation : FSInitializeFileSystemOperation
{
private enum ESteps
{
None,
InitUnpackFileSystem,
LoadCatalogFile,
Done,
}
private readonly DefaultBuildinFileSystem _fileSystem;
private FSInitializeFileSystemOperation _initUnpackFIleSystemOp;
private LoadBuildinCatalogFileOperation _loadCatalogFileOp;
private ESteps _steps = ESteps.None;
internal DBFSInitializeOperation(DefaultBuildinFileSystem fileSystem)
{
_fileSystem = fileSystem;
}
internal override void InternalOnStart()
{
#if UNITY_WEBGL
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"{nameof(DefaultBuildinFileSystem)} is not support WEBGL platform !";
#else
_steps = ESteps.InitUnpackFileSystem;
#endif
}
internal override void InternalOnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.InitUnpackFileSystem)
{
if (_initUnpackFIleSystemOp == null)
_initUnpackFIleSystemOp = _fileSystem.InitializeUpackFileSystem();
Progress = _initUnpackFIleSystemOp.Progress;
if (_initUnpackFIleSystemOp.IsDone == false)
return;
if (_initUnpackFIleSystemOp.Status == EOperationStatus.Succeed)
{
if (_fileSystem.DisableCatalogFile)
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.LoadCatalogFile;
}
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _initUnpackFIleSystemOp.Error;
}
}
if (_steps == ESteps.LoadCatalogFile)
{
if (_loadCatalogFileOp == null)
{
#if UNITY_EDITOR
// 兼容性初始化
// 说明:内置文件系统在编辑器下运行时需要动态生成
string packageRoot = _fileSystem.FileRoot;
DefaultBuildinFileSystemBuild.CreateBuildinCatalogFile(_fileSystem.PackageName, packageRoot);
#endif
_loadCatalogFileOp = new LoadBuildinCatalogFileOperation(_fileSystem);
OperationSystem.StartOperation(_fileSystem.PackageName, _loadCatalogFileOp);
}
if (_loadCatalogFileOp.IsDone == false)
return;
if (_loadCatalogFileOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _loadCatalogFileOp.Error;
}
}
}
}
}

View File

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

View File

@@ -0,0 +1,213 @@
using System.IO;
using UnityEngine;
namespace YooAsset
{
/// <summary>
/// 加载AssetBundle文件
/// </summary>
internal class DBFSLoadAssetBundleOperation : FSLoadBundleOperation
{
private enum ESteps
{
None,
LoadAssetBundle,
CheckResult,
Done,
}
private readonly DefaultBuildinFileSystem _fileSystem;
private readonly PackageBundle _bundle;
private AssetBundleCreateRequest _createRequest;
private AssetBundle _assetBundle;
private Stream _managedStream;
private ESteps _steps = ESteps.None;
internal DBFSLoadAssetBundleOperation(DefaultBuildinFileSystem fileSystem, PackageBundle bundle)
{
_fileSystem = fileSystem;
_bundle = bundle;
}
internal override void InternalOnStart()
{
DownloadProgress = 1f;
DownloadedBytes = _bundle.FileSize;
_steps = ESteps.LoadAssetBundle;
}
internal override void InternalOnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.LoadAssetBundle)
{
if (_bundle.Encrypted)
{
if (_fileSystem.DecryptionServices == null)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"The {nameof(IDecryptionServices)} is null !";
YooLogger.Error(Error);
return;
}
}
if (IsWaitForAsyncComplete)
{
if (_bundle.Encrypted)
{
var decryptResult = _fileSystem.LoadEncryptedAssetBundle(_bundle);
_assetBundle = decryptResult.Result;
_managedStream = decryptResult.ManagedStream;
}
else
{
string filePath = _fileSystem.GetBuildinFileLoadPath(_bundle);
_assetBundle = AssetBundle.LoadFromFile(filePath);
}
}
else
{
if (_bundle.Encrypted)
{
var decryptResult = _fileSystem.LoadEncryptedAssetBundleAsync(_bundle);
_createRequest = decryptResult.CreateRequest;
_managedStream = decryptResult.ManagedStream;
}
else
{
string filePath = _fileSystem.GetBuildinFileLoadPath(_bundle);
_createRequest = AssetBundle.LoadFromFileAsync(filePath);
}
}
_steps = ESteps.CheckResult;
}
if (_steps == ESteps.CheckResult)
{
if (_createRequest != null)
{
if (IsWaitForAsyncComplete)
{
// 强制挂起主线程(注意:该操作会很耗时)
YooLogger.Warning("Suspend the main thread to load unity bundle.");
_assetBundle = _createRequest.assetBundle;
}
else
{
if (_createRequest.isDone == false)
return;
_assetBundle = _createRequest.assetBundle;
}
}
if (_assetBundle != null)
{
_steps = ESteps.Done;
Result = new AssetBundleResult(_fileSystem, _bundle, _assetBundle, _managedStream);
Status = EOperationStatus.Succeed;
return;
}
if (_bundle.Encrypted)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Failed to load encrypted buildin asset bundle file : {_bundle.BundleName}";
YooLogger.Error(Error);
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Failed to load buildin asset bundle file : {_bundle.BundleName}";
YooLogger.Error(Error);
}
}
}
internal override void InternalWaitForAsyncComplete()
{
while (true)
{
if (ExecuteWhileDone())
{
_steps = ESteps.Done;
break;
}
}
}
public override void AbortDownloadOperation()
{
}
}
/// <summary>
/// 加载原生文件
/// </summary>
internal class DBFSLoadRawBundleOperation : FSLoadBundleOperation
{
private enum ESteps
{
None,
LoadBuildinRawBundle,
Done,
}
private readonly DefaultBuildinFileSystem _fileSystem;
private readonly PackageBundle _bundle;
private ESteps _steps = ESteps.None;
internal DBFSLoadRawBundleOperation(DefaultBuildinFileSystem fileSystem, PackageBundle bundle)
{
_fileSystem = fileSystem;
_bundle = bundle;
}
internal override void InternalOnStart()
{
DownloadProgress = 1f;
DownloadedBytes = _bundle.FileSize;
_steps = ESteps.LoadBuildinRawBundle;
}
internal override void InternalOnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.LoadBuildinRawBundle)
{
string filePath = _fileSystem.GetBuildinFileLoadPath(_bundle);
if (File.Exists(filePath))
{
_steps = ESteps.Done;
Result = new RawBundleResult(_fileSystem, _bundle);
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Can not found buildin raw bundle file : {filePath}";
YooLogger.Error(Error);
}
}
}
internal override void InternalWaitForAsyncComplete()
{
while (true)
{
if (ExecuteWhileDone())
{
_steps = ESteps.Done;
break;
}
}
}
public override void AbortDownloadOperation()
{
}
}
}

View File

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

View File

@@ -0,0 +1,85 @@

namespace YooAsset
{
internal class DBFSLoadPackageManifestOperation : FSLoadPackageManifestOperation
{
private enum ESteps
{
None,
RequestBuildinPackageHash,
LoadBuildinPackageManifest,
Done,
}
private readonly DefaultBuildinFileSystem _fileSystem;
private readonly string _packageVersion;
private RequestBuildinPackageHashOperation _requestBuildinPackageHashOp;
private LoadBuildinPackageManifestOperation _loadBuildinPackageManifestOp;
private ESteps _steps = ESteps.None;
public DBFSLoadPackageManifestOperation(DefaultBuildinFileSystem fileSystem, string packageVersion)
{
_fileSystem = fileSystem;
_packageVersion = packageVersion;
}
internal override void InternalOnStart()
{
_steps = ESteps.RequestBuildinPackageHash;
}
internal override void InternalOnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.RequestBuildinPackageHash)
{
if (_requestBuildinPackageHashOp == null)
{
_requestBuildinPackageHashOp = new RequestBuildinPackageHashOperation(_fileSystem, _packageVersion);
OperationSystem.StartOperation(_fileSystem.PackageName, _requestBuildinPackageHashOp);
}
if (_requestBuildinPackageHashOp.IsDone == false)
return;
if (_requestBuildinPackageHashOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.LoadBuildinPackageManifest;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _requestBuildinPackageHashOp.Error;
}
}
if (_steps == ESteps.LoadBuildinPackageManifest)
{
if (_loadBuildinPackageManifestOp == null)
{
string packageHash = _requestBuildinPackageHashOp.PackageHash;
_loadBuildinPackageManifestOp = new LoadBuildinPackageManifestOperation(_fileSystem, _packageVersion, packageHash);
OperationSystem.StartOperation(_fileSystem.PackageName, _loadBuildinPackageManifestOp);
}
if (_loadBuildinPackageManifestOp.IsDone == false)
return;
if (_loadBuildinPackageManifestOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.Done;
Manifest = _loadBuildinPackageManifestOp.Manifest;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _loadBuildinPackageManifestOp.Error;
}
}
}
}
}

View File

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

View File

@@ -0,0 +1,57 @@

namespace YooAsset
{
internal class DBFSRequestPackageVersionOperation : FSRequestPackageVersionOperation
{
private enum ESteps
{
None,
RequestPackageVersion,
Done,
}
private readonly DefaultBuildinFileSystem _fileSystem;
private RequestBuildinPackageVersionOperation _requestBuildinPackageVersionOp;
private ESteps _steps = ESteps.None;
internal DBFSRequestPackageVersionOperation(DefaultBuildinFileSystem fileSystem)
{
_fileSystem = fileSystem;
}
internal override void InternalOnStart()
{
_steps = ESteps.RequestPackageVersion;
}
internal override void InternalOnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.RequestPackageVersion)
{
if (_requestBuildinPackageVersionOp == null)
{
_requestBuildinPackageVersionOp = new RequestBuildinPackageVersionOperation(_fileSystem);
OperationSystem.StartOperation(_fileSystem.PackageName, _requestBuildinPackageVersionOp);
}
if (_requestBuildinPackageVersionOp.IsDone == false)
return;
if (_requestBuildinPackageVersionOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.Done;
PackageVersion = _requestBuildinPackageVersionOp.PackageVersion;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _requestBuildinPackageVersionOp.Error;
}
}
}
}
}

View File

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

View File

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

View File

@@ -0,0 +1,63 @@
using UnityEngine;
namespace YooAsset
{
internal sealed class LoadBuildinCatalogFileOperation : AsyncOperationBase
{
private enum ESteps
{
None,
LoadCatalog,
Done,
}
private readonly DefaultBuildinFileSystem _fileSystem;
private ESteps _steps = ESteps.None;
internal LoadBuildinCatalogFileOperation(DefaultBuildinFileSystem fileSystem)
{
_fileSystem = fileSystem;
}
internal override void InternalOnStart()
{
_steps = ESteps.LoadCatalog;
}
internal override void InternalOnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.LoadCatalog)
{
string catalogFilePath = _fileSystem.GetCatalogFileLoadPath();
var catalog = Resources.Load<DefaultBuildinFileCatalog>(catalogFilePath);
if (catalog == null)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Failed to load catalog file : {catalogFilePath}";
return;
}
if (catalog.PackageName != _fileSystem.PackageName)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Catalog file package name {catalog.PackageName} cannot match the file system package name {_fileSystem.PackageName}";
return;
}
foreach (var wrapper in catalog.Wrappers)
{
var fileWrapper = new DefaultBuildinFileSystem.FileWrapper(wrapper.FileName);
_fileSystem.RecordCatalogFile(wrapper.BundleGUID, fileWrapper);
}
YooLogger.Log($"Package '{_fileSystem.PackageName}' buildin catalog files count : {catalog.Wrappers.Count}");
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
}
}
}

View File

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

View File

@@ -0,0 +1,110 @@

namespace YooAsset
{
internal class LoadBuildinPackageManifestOperation : AsyncOperationBase
{
private enum ESteps
{
None,
RequestFileData,
VerifyFileData,
LoadManifest,
Done,
}
private readonly DefaultBuildinFileSystem _fileSystem;
private readonly string _packageVersion;
private readonly string _packageHash;
private UnityWebDataRequestOperation _webDataRequestOp;
private DeserializeManifestOperation _deserializer;
private ESteps _steps = ESteps.None;
/// <summary>
/// 包裹清单
/// </summary>
public PackageManifest Manifest { private set; get; }
internal LoadBuildinPackageManifestOperation(DefaultBuildinFileSystem fileSystem, string packageVersion, string packageHash)
{
_fileSystem = fileSystem;
_packageVersion = packageVersion;
_packageHash = packageHash;
}
internal override void InternalOnStart()
{
_steps = ESteps.RequestFileData;
}
internal override void InternalOnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.RequestFileData)
{
if (_webDataRequestOp == null)
{
string filePath = _fileSystem.GetBuildinPackageManifestFilePath(_packageVersion);
string url = DownloadSystemHelper.ConvertToWWWPath(filePath);
_webDataRequestOp = new UnityWebDataRequestOperation(url);
OperationSystem.StartOperation(_fileSystem.PackageName, _webDataRequestOp);
}
if (_webDataRequestOp.IsDone == false)
return;
if (_webDataRequestOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.VerifyFileData;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _webDataRequestOp.Error;
}
}
if (_steps == ESteps.VerifyFileData)
{
string fileHash = HashUtility.BytesCRC32(_webDataRequestOp.Result);
if (fileHash == _packageHash)
{
_steps = ESteps.LoadManifest;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = "Failed to verify buildin package manifest file !";
}
}
if (_steps == ESteps.LoadManifest)
{
if (_deserializer == null)
{
_deserializer = new DeserializeManifestOperation(_webDataRequestOp.Result);
OperationSystem.StartOperation(_fileSystem.PackageName, _deserializer);
}
Progress = _deserializer.Progress;
if (_deserializer.IsDone == false)
return;
if (_deserializer.Status == EOperationStatus.Succeed)
{
_steps = ESteps.Done;
Manifest = _deserializer.Manifest;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _deserializer.Error;
}
}
}
}
}

View File

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

View File

@@ -0,0 +1,75 @@

namespace YooAsset
{
internal class RequestBuildinPackageHashOperation : AsyncOperationBase
{
private enum ESteps
{
None,
RequestPackageHash,
Done,
}
private readonly DefaultBuildinFileSystem _fileSystem;
private readonly string _packageVersion;
private UnityWebTextRequestOperation _webTextRequestOp;
private ESteps _steps = ESteps.None;
/// <summary>
/// 包裹哈希值
/// </summary>
public string PackageHash { private set; get; }
internal RequestBuildinPackageHashOperation(DefaultBuildinFileSystem fileSystem, string packageVersion)
{
_fileSystem = fileSystem;
_packageVersion = packageVersion;
}
internal override void InternalOnStart()
{
_steps = ESteps.RequestPackageHash;
}
internal override void InternalOnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.RequestPackageHash)
{
if (_webTextRequestOp == null)
{
string filePath = _fileSystem.GetBuildinPackageHashFilePath(_packageVersion);
string url = DownloadSystemHelper.ConvertToWWWPath(filePath);
_webTextRequestOp = new UnityWebTextRequestOperation(url);
OperationSystem.StartOperation(_fileSystem.PackageName, _webTextRequestOp);
}
if (_webTextRequestOp.IsDone == false)
return;
if (_webTextRequestOp.Status == EOperationStatus.Succeed)
{
PackageHash = _webTextRequestOp.Result;
if (string.IsNullOrEmpty(PackageHash))
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Buildin package hash file content is empty !";
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _webTextRequestOp.Error;
}
}
}
}
}

View File

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

View File

@@ -0,0 +1,73 @@

namespace YooAsset
{
internal class RequestBuildinPackageVersionOperation : AsyncOperationBase
{
private enum ESteps
{
None,
RequestPackageVersion,
Done,
}
private readonly DefaultBuildinFileSystem _fileSystem;
private UnityWebTextRequestOperation _webTextRequestOp;
private ESteps _steps = ESteps.None;
/// <summary>
/// 包裹版本
/// </summary>
public string PackageVersion { private set; get; }
internal RequestBuildinPackageVersionOperation(DefaultBuildinFileSystem fileSystem)
{
_fileSystem = fileSystem;
}
internal override void InternalOnStart()
{
_steps = ESteps.RequestPackageVersion;
}
internal override void InternalOnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.RequestPackageVersion)
{
if (_webTextRequestOp == null)
{
string filePath = _fileSystem.GetBuildinPackageVersionFilePath();
string url = DownloadSystemHelper.ConvertToWWWPath(filePath);
_webTextRequestOp = new UnityWebTextRequestOperation(url);
OperationSystem.StartOperation(_fileSystem.PackageName, _webTextRequestOp);
}
if (_webTextRequestOp.IsDone == false)
return;
if (_webTextRequestOp.Status == EOperationStatus.Succeed)
{
PackageVersion = _webTextRequestOp.Result;
if (string.IsNullOrEmpty(PackageVersion))
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Buildin package version file content is empty !";
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _webTextRequestOp.Error;
}
}
}
}
}

View File

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

View File

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

View File

@@ -0,0 +1,63 @@
using System.IO;
using UnityEngine;
namespace YooAsset
{
/// <summary>
/// 应用程序水印
/// </summary>
internal class ApplicationFootPrint
{
private readonly DefaultCacheFileSystem _fileSystem;
private string _footPrint;
public ApplicationFootPrint(DefaultCacheFileSystem fileSystem)
{
_fileSystem = fileSystem;
}
/// <summary>
/// 读取应用程序水印
/// </summary>
public void Load(string packageName)
{
string footPrintFilePath = _fileSystem.GetSandboxAppFootPrintFilePath();
if (File.Exists(footPrintFilePath))
{
_footPrint = FileUtility.ReadAllText(footPrintFilePath);
}
else
{
Coverage(packageName);
}
}
/// <summary>
/// 检测水印是否发生变化
/// </summary>
public bool IsDirty()
{
#if UNITY_EDITOR
return _footPrint != Application.version;
#else
return _footPrint != Application.buildGUID;
#endif
}
/// <summary>
/// 覆盖掉水印
/// </summary>
public void Coverage(string packageName)
{
#if UNITY_EDITOR
_footPrint = Application.version;
#else
_footPrint = Application.buildGUID;
#endif
string footPrintFilePath = _fileSystem.GetSandboxAppFootPrintFilePath();
FileUtility.WriteAllText(footPrintFilePath, _footPrint);
YooLogger.Log($"Save application foot print : {_footPrint}");
}
}
}

View File

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

View File

@@ -0,0 +1,131 @@
using System;
using System.Collections.Generic;
namespace YooAsset
{
internal class DefaultCacheDownloadCenter
{
private readonly DefaultCacheFileSystem _fileSystem;
protected readonly Dictionary<string, DefaultDownloadFileOperation> _downloaders = new Dictionary<string, DefaultDownloadFileOperation>(1000);
protected readonly List<string> _removeDownloadList = new List<string>(1000);
public DefaultCacheDownloadCenter(DefaultCacheFileSystem fileSystem)
{
_fileSystem = fileSystem;
}
/// <summary>
/// 更新下载中心
/// </summary>
public void Update()
{
// 获取可移除的下载器集合
_removeDownloadList.Clear();
foreach (var valuePair in _downloaders)
{
var downloader = valuePair.Value;
// 注意:主动终止引用计数为零的下载任务
if (downloader.RefCount <= 0)
{
_removeDownloadList.Add(valuePair.Key);
downloader.SetAbort();
continue;
}
if (downloader.IsDone)
{
_removeDownloadList.Add(valuePair.Key);
continue;
}
}
// 移除下载器
foreach (var key in _removeDownloadList)
{
_downloaders.Remove(key);
}
// 最大并发数检测
int processCount = GetProcessingOperationCount();
if (processCount != _downloaders.Count)
{
if (processCount < _fileSystem.DownloadMaxConcurrency)
{
int startCount = _fileSystem.DownloadMaxConcurrency - processCount;
if (startCount > _fileSystem.DownloadMaxRequestPerFrame)
startCount = _fileSystem.DownloadMaxRequestPerFrame;
foreach (var operationPair in _downloaders)
{
var operation = operationPair.Value;
if (operation.Status == EOperationStatus.None)
{
OperationSystem.StartOperation(_fileSystem.PackageName, operation);
startCount--;
if (startCount <= 0)
break;
}
}
}
}
}
/// <summary>
/// 创建下载任务
/// </summary>
public FSDownloadFileOperation DownloadFileAsync(PackageBundle bundle, DownloadParam param)
{
// 查询旧的下载器
if (_downloaders.TryGetValue(bundle.BundleGUID, out var oldDownloader))
{
oldDownloader.Reference();
return oldDownloader;
}
// 设置请求URL
if (string.IsNullOrEmpty(param.ImportFilePath))
{
param.MainURL = _fileSystem.RemoteServices.GetRemoteMainURL(bundle.FileName);
param.FallbackURL = _fileSystem.RemoteServices.GetRemoteFallbackURL(bundle.FileName);
}
else
{
// 注意:把本地文件路径指定为远端下载地址
param.MainURL = DownloadSystemHelper.ConvertToWWWPath(param.ImportFilePath);
param.FallbackURL = param.MainURL;
}
// 创建新的下载器
DefaultDownloadFileOperation newDownloader;
if (bundle.FileSize >= _fileSystem.ResumeDownloadMinimumSize)
{
newDownloader = new DownloadResumeFileOperation(_fileSystem, bundle, param);
newDownloader.Reference();
_downloaders.Add(bundle.BundleGUID, newDownloader);
}
else
{
newDownloader = new DownloadNormalFileOperation(_fileSystem, bundle, param);
newDownloader.Reference();
_downloaders.Add(bundle.BundleGUID, newDownloader);
}
return newDownloader;
}
/// <summary>
/// 获取正在进行中的下载器总数
/// </summary>
private int GetProcessingOperationCount()
{
int count = 0;
foreach (var operationPair in _downloaders)
{
var operation = operationPair.Value;
if (operation.Status != EOperationStatus.None)
count++;
}
return count;
}
}
}

View File

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

View File

@@ -0,0 +1,557 @@
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
namespace YooAsset
{
/// <summary>
/// 缓存文件系统
/// 说明正在进行的下载器会在ResourcePackage销毁的时候执行Abort操作
/// </summary>
internal class DefaultCacheFileSystem : IFileSystem
{
protected readonly Dictionary<string, RecordFileElement> _wrappers = new Dictionary<string, RecordFileElement>(10000);
protected readonly Dictionary<string, string> _bundleDataFilePaths = new Dictionary<string, string>(10000);
protected readonly Dictionary<string, string> _bundleInfoFilePaths = new Dictionary<string, string>(10000);
protected readonly Dictionary<string, string> _tempFilePaths = new Dictionary<string, string>(10000);
protected DefaultCacheDownloadCenter _downloadCenter;
protected string _packageRoot;
protected string _tempFilesRoot;
protected string _cacheBundleFilesRoot;
protected string _cacheManifestFilesRoot;
/// <summary>
/// 包裹名称
/// </summary>
public string PackageName { private set; get; }
/// <summary>
/// 文件根目录
/// </summary>
public string FileRoot
{
get
{
return _packageRoot;
}
}
/// <summary>
/// 文件数量
/// </summary>
public int FileCount
{
get
{
return _wrappers.Count;
}
}
#region
/// <summary>
/// 自定义参数:远程服务接口
/// </summary>
public IRemoteServices RemoteServices { private set; get; } = null;
/// <summary>
/// 自定义参数:初始化的时候缓存文件校验级别
/// </summary>
public EFileVerifyLevel FileVerifyLevel { private set; get; } = EFileVerifyLevel.Middle;
/// <summary>
/// 自定义参数:数据文件追加文件格式
/// </summary>
public bool AppendFileExtension { private set; get; } = false;
/// <summary>
/// 自定义参数:最大并发连接数
/// </summary>
public int DownloadMaxConcurrency { private set; get; } = int.MaxValue;
/// <summary>
/// 自定义参数:每帧发起的最大请求数
/// </summary>
public int DownloadMaxRequestPerFrame { private set; get; } = int.MaxValue;
/// <summary>
/// 自定义参数:启用断点续传的最小尺寸
/// </summary>
public long ResumeDownloadMinimumSize { private set; get; } = long.MaxValue;
/// <summary>
/// 自定义参数:断点续传下载器关注的错误码
/// </summary>
public List<long> ResumeDownloadResponseCodes { private set; get; } = null;
/// <summary>
/// 自定义参数:解密方法类
/// </summary>
public IDecryptionServices DecryptionServices { private set; get; }
#endregion
public DefaultCacheFileSystem()
{
}
public virtual FSInitializeFileSystemOperation InitializeFileSystemAsync()
{
var operation = new DCFSInitializeOperation(this);
OperationSystem.StartOperation(PackageName, operation);
return operation;
}
public virtual FSLoadPackageManifestOperation LoadPackageManifestAsync(string packageVersion, int timeout)
{
var operation = new DCFSLoadPackageManifestOperation(this, packageVersion, timeout);
OperationSystem.StartOperation(PackageName, operation);
return operation;
}
public virtual FSRequestPackageVersionOperation RequestPackageVersionAsync(bool appendTimeTicks, int timeout)
{
var operation = new DCFSRequestPackageVersionOperation(this, appendTimeTicks, timeout);
OperationSystem.StartOperation(PackageName, operation);
return operation;
}
public virtual FSClearCacheFilesOperation ClearCacheFilesAsync(PackageManifest manifest, string clearMode, object clearParam)
{
if (clearMode == EFileClearMode.ClearAllBundleFiles.ToString())
{
var operation = new ClearAllCacheBundleFilesOperation(this);
OperationSystem.StartOperation(PackageName, operation);
return operation;
}
else if (clearMode == EFileClearMode.ClearUnusedBundleFiles.ToString())
{
var operation = new ClearUnusedCacheBundleFilesOperation(this, manifest);
OperationSystem.StartOperation(PackageName, operation);
return operation;
}
else if (clearMode == EFileClearMode.ClearBundleFilesByTags.ToString())
{
var operation = new ClearCacheBundleFilesByTagsOperaiton(this, manifest, clearParam);
OperationSystem.StartOperation(PackageName, operation);
return operation;
}
else if (clearMode == EFileClearMode.ClearAllManifestFiles.ToString())
{
var operation = new ClearAllCacheManifestFilesOperation(this);
OperationSystem.StartOperation(PackageName, operation);
return operation;
}
else if (clearMode == EFileClearMode.ClearUnusedManifestFiles.ToString())
{
var operation = new ClearUnusedCacheManifestFilesOperation(this, manifest);
OperationSystem.StartOperation(PackageName, operation);
return operation;
}
else
{
string error = $"Invalid clear mode : {clearMode}";
var operation = new FSClearCacheFilesCompleteOperation(error);
OperationSystem.StartOperation(PackageName, operation);
return operation;
}
}
public virtual FSDownloadFileOperation DownloadFileAsync(PackageBundle bundle, DownloadParam param)
{
return _downloadCenter.DownloadFileAsync(bundle, param);
}
public virtual FSLoadBundleOperation LoadBundleFile(PackageBundle bundle)
{
if (bundle.BundleType == (int)EBuildBundleType.AssetBundle)
{
var operation = new DCFSLoadAssetBundleOperation(this, bundle);
OperationSystem.StartOperation(PackageName, operation);
return operation;
}
else if (bundle.BundleType == (int)EBuildBundleType.RawBundle)
{
var operation = new DCFSLoadRawBundleOperation(this, bundle);
OperationSystem.StartOperation(PackageName, operation);
return operation;
}
else
{
string error = $"{nameof(DefaultCacheFileSystem)} not support load bundle type : {bundle.BundleType}";
var operation = new FSLoadBundleCompleteOperation(error);
OperationSystem.StartOperation(PackageName, operation);
return operation;
}
}
public virtual void SetParameter(string name, object value)
{
if (name == FileSystemParametersDefine.REMOTE_SERVICES)
{
RemoteServices = (IRemoteServices)value;
}
else if (name == FileSystemParametersDefine.FILE_VERIFY_LEVEL)
{
FileVerifyLevel = (EFileVerifyLevel)value;
}
else if (name == FileSystemParametersDefine.APPEND_FILE_EXTENSION)
{
AppendFileExtension = (bool)value;
}
else if (name == FileSystemParametersDefine.DOWNLOAD_MAX_CONCURRENCY)
{
DownloadMaxConcurrency = (int)value;
}
else if (name == FileSystemParametersDefine.DOWNLOAD_MAX_REQUEST_PER_FRAME)
{
DownloadMaxRequestPerFrame = (int)value;
}
else if (name == FileSystemParametersDefine.RESUME_DOWNLOAD_MINMUM_SIZE)
{
ResumeDownloadMinimumSize = (long)value;
}
else if (name == FileSystemParametersDefine.RESUME_DOWNLOAD_RESPONSE_CODES)
{
ResumeDownloadResponseCodes = (List<long>)value;
}
else if (name == FileSystemParametersDefine.DECRYPTION_SERVICES)
{
DecryptionServices = (IDecryptionServices)value;
}
else
{
YooLogger.Warning($"Invalid parameter : {name}");
}
}
public virtual void OnCreate(string packageName, string packageRoot)
{
PackageName = packageName;
if (string.IsNullOrEmpty(packageRoot))
_packageRoot = GetDefaultCachePackageRoot(packageName);
else
_packageRoot = packageRoot;
_cacheBundleFilesRoot = PathUtility.Combine(_packageRoot, DefaultCacheFileSystemDefine.BundleFilesFolderName);
_tempFilesRoot = PathUtility.Combine(_packageRoot, DefaultCacheFileSystemDefine.TempFilesFolderName);
_cacheManifestFilesRoot = PathUtility.Combine(_packageRoot, DefaultCacheFileSystemDefine.ManifestFilesFolderName);
_downloadCenter = new DefaultCacheDownloadCenter(this);
}
public virtual void OnUpdate()
{
_downloadCenter.Update();
}
public virtual bool Belong(PackageBundle bundle)
{
// 注意:缓存文件系统保底加载!
return true;
}
public virtual bool Exists(PackageBundle bundle)
{
return _wrappers.ContainsKey(bundle.BundleGUID);
}
public virtual bool NeedDownload(PackageBundle bundle)
{
if (Belong(bundle) == false)
return false;
return Exists(bundle) == false;
}
public virtual bool NeedUnpack(PackageBundle bundle)
{
return false;
}
public virtual bool NeedImport(PackageBundle bundle)
{
if (Belong(bundle) == false)
return false;
return Exists(bundle) == false;
}
public virtual string GetBundleFilePath(PackageBundle bundle)
{
return GetCacheBundleFileLoadPath(bundle);
}
public virtual byte[] ReadBundleFileData(PackageBundle bundle)
{
if (Exists(bundle) == false)
return null;
if (bundle.Encrypted)
{
if (DecryptionServices == null)
{
YooLogger.Error($"The {nameof(IDecryptionServices)} is null !");
return null;
}
string filePath = GetCacheBundleFileLoadPath(bundle);
var fileInfo = new DecryptFileInfo()
{
BundleName = bundle.BundleName,
FileLoadCRC = bundle.UnityCRC,
FileLoadPath = filePath,
};
return DecryptionServices.ReadFileData(fileInfo);
}
else
{
string filePath = GetCacheBundleFileLoadPath(bundle);
return FileUtility.ReadAllBytes(filePath);
}
}
public virtual string ReadBundleFileText(PackageBundle bundle)
{
if (Exists(bundle) == false)
return null;
if (bundle.Encrypted)
{
if (DecryptionServices == null)
{
YooLogger.Error($"The {nameof(IDecryptionServices)} is null !");
return null;
}
string filePath = GetCacheBundleFileLoadPath(bundle);
var fileInfo = new DecryptFileInfo()
{
BundleName = bundle.BundleName,
FileLoadCRC = bundle.UnityCRC,
FileLoadPath = filePath,
};
return DecryptionServices.ReadFileText(fileInfo);
}
else
{
string filePath = GetCacheBundleFileLoadPath(bundle);
return FileUtility.ReadAllText(filePath);
}
}
#region
public List<string> GetAllCachedBundleGUIDs()
{
return _wrappers.Keys.ToList();
}
public string GetTempFilePath(PackageBundle bundle)
{
if (_tempFilePaths.TryGetValue(bundle.BundleGUID, out string filePath) == false)
{
filePath = PathUtility.Combine(_tempFilesRoot, bundle.BundleGUID);
_tempFilePaths.Add(bundle.BundleGUID, filePath);
}
return filePath;
}
public string GetBundleDataFilePath(PackageBundle bundle)
{
if (_bundleDataFilePaths.TryGetValue(bundle.BundleGUID, out string filePath) == false)
{
string folderName = bundle.FileHash.Substring(0, 2);
filePath = PathUtility.Combine(_cacheBundleFilesRoot, folderName, bundle.BundleGUID, DefaultCacheFileSystemDefine.BundleDataFileName);
if (AppendFileExtension)
filePath += bundle.FileExtension;
_bundleDataFilePaths.Add(bundle.BundleGUID, filePath);
}
return filePath;
}
public string GetBundleInfoFilePath(PackageBundle bundle)
{
if (_bundleInfoFilePaths.TryGetValue(bundle.BundleGUID, out string filePath) == false)
{
string folderName = bundle.FileHash.Substring(0, 2);
filePath = PathUtility.Combine(_cacheBundleFilesRoot, folderName, bundle.BundleGUID, DefaultCacheFileSystemDefine.BundleInfoFileName);
_bundleInfoFilePaths.Add(bundle.BundleGUID, filePath);
}
return filePath;
}
public bool IsRecordBundleFile(string bundleGUID)
{
return _wrappers.ContainsKey(bundleGUID);
}
public bool RecordBundleFile(string bundleGUID, RecordFileElement element)
{
if (_wrappers.ContainsKey(bundleGUID))
{
YooLogger.Error($"{nameof(DefaultCacheFileSystem)} has record file element : {bundleGUID}");
return false;
}
_wrappers.Add(bundleGUID, element);
return true;
}
public EFileVerifyResult VerifyCacheFile(PackageBundle bundle)
{
if (_wrappers.TryGetValue(bundle.BundleGUID, out RecordFileElement wrapper) == false)
return EFileVerifyResult.CacheNotFound;
EFileVerifyResult result = FileVerifyHelper.FileVerify(wrapper.DataFilePath, wrapper.DataFileSize, wrapper.DataFileCRC, EFileVerifyLevel.High);
return result;
}
public bool WriteCacheBundleFile(PackageBundle bundle, string copyPath)
{
if (_wrappers.ContainsKey(bundle.BundleGUID))
{
throw new Exception("Should never get here !");
}
string infoFilePath = GetBundleInfoFilePath(bundle);
string dataFilePath = GetBundleDataFilePath(bundle);
try
{
if (File.Exists(infoFilePath))
File.Delete(infoFilePath);
if (File.Exists(dataFilePath))
File.Delete(dataFilePath);
FileUtility.CreateFileDirectory(dataFilePath);
// 拷贝数据文件
FileInfo fileInfo = new FileInfo(copyPath);
fileInfo.CopyTo(dataFilePath);
// 写入文件信息
WriteBundleInfoFile(infoFilePath, bundle.FileCRC, bundle.FileSize);
}
catch (Exception e)
{
YooLogger.Error($"Failed to write cache file ! {e.Message}");
return false;
}
var recordFileElement = new RecordFileElement(infoFilePath, dataFilePath, bundle.FileCRC, bundle.FileSize);
return RecordBundleFile(bundle.BundleGUID, recordFileElement);
}
public bool DeleteCacheBundleFile(string bundleGUID)
{
if (_wrappers.TryGetValue(bundleGUID, out RecordFileElement wrapper))
{
try
{
string dataFilePath = wrapper.DataFilePath;
FileInfo fileInfo = new FileInfo(dataFilePath);
if (fileInfo.Exists)
fileInfo.Directory.Delete(true);
_wrappers.Remove(bundleGUID);
return true;
}
catch (Exception e)
{
YooLogger.Error($"Failed to delete cache file ! {e.Message}");
return false;
}
}
else
{
return false;
}
}
private readonly BufferWriter _sharedBuffer = new BufferWriter(1024);
public void WriteBundleInfoFile(string filePath, string dataFileCRC, long dataFileSize)
{
using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.Read))
{
_sharedBuffer.Clear();
_sharedBuffer.WriteUTF8(dataFileCRC);
_sharedBuffer.WriteInt64(dataFileSize);
_sharedBuffer.WriteToStream(fs);
fs.Flush();
}
}
public void ReadBundleInfoFile(string filePath, out string dataFileCRC, out long dataFileSize)
{
byte[] binaryData = FileUtility.ReadAllBytes(filePath);
BufferReader buffer = new BufferReader(binaryData);
dataFileCRC = buffer.ReadUTF8();
dataFileSize = buffer.ReadInt64();
}
#endregion
#region
public string GetDefaultCachePackageRoot(string packageName)
{
string rootDirectory;
#if UNITY_EDITOR
rootDirectory = YooAssetSettingsData.GetYooEditorCacheRoot();
#elif UNITY_STANDALONE
rootDirectory = YooAssetSettingsData.GetYooStandaloneCacheRoot();
#else
rootDirectory = YooAssetSettingsData.GetYooMobileCacheRoot();
#endif
return PathUtility.Combine(rootDirectory, packageName);
}
public string GetCacheBundleFileLoadPath(PackageBundle bundle)
{
return GetBundleDataFilePath(bundle);
}
public string GetCachePackageHashFilePath(string packageVersion)
{
string fileName = YooAssetSettingsData.GetPackageHashFileName(PackageName, packageVersion);
return PathUtility.Combine(_cacheManifestFilesRoot, fileName);
}
public string GetCachePackageManifestFilePath(string packageVersion)
{
string fileName = YooAssetSettingsData.GetManifestBinaryFileName(PackageName, packageVersion);
return PathUtility.Combine(_cacheManifestFilesRoot, fileName);
}
public string GetSandboxAppFootPrintFilePath()
{
return PathUtility.Combine(_cacheManifestFilesRoot, DefaultCacheFileSystemDefine.AppFootPrintFileName);
}
public string GetCacheBundleFilesRoot()
{
return _cacheBundleFilesRoot;
}
public string GetCacheManifestFilesRoot()
{
return _cacheManifestFilesRoot;
}
/// <summary>
/// 删除所有清单文件
/// </summary>
public void DeleteAllManifestFiles()
{
if (Directory.Exists(_cacheManifestFilesRoot))
{
Directory.Delete(_cacheManifestFilesRoot, true);
}
}
/// <summary>
/// 加载加密资源文件
/// </summary>
public DecryptResult LoadEncryptedAssetBundle(PackageBundle bundle)
{
string filePath = GetCacheBundleFileLoadPath(bundle);
var fileInfo = new DecryptFileInfo()
{
BundleName = bundle.BundleName,
FileLoadCRC = bundle.UnityCRC,
FileLoadPath = filePath,
};
return DecryptionServices.LoadAssetBundle(fileInfo);
}
/// <summary>
/// 加载加密资源文件
/// </summary>
public DecryptResult LoadEncryptedAssetBundleAsync(PackageBundle bundle)
{
string filePath = GetCacheBundleFileLoadPath(bundle);
var fileInfo = new DecryptFileInfo()
{
BundleName = bundle.BundleName,
FileLoadCRC = bundle.UnityCRC,
FileLoadPath = filePath,
};
return DecryptionServices.LoadAssetBundleAsync(fileInfo);
}
#endregion
}
}

View File

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

View File

@@ -0,0 +1,36 @@

namespace YooAsset
{
internal class DefaultCacheFileSystemDefine
{
/// <summary>
/// 数据文件名称
/// </summary>
public const string BundleDataFileName = "__data";
/// <summary>
/// 信息文件名称
/// </summary>
public const string BundleInfoFileName = "__info";
/// <summary>
/// 资源文件的文件夹名称
/// </summary>
public const string BundleFilesFolderName = "BundleFiles";
/// <summary>
/// 临时文件的文件夹名称
/// </summary>
public const string TempFilesFolderName = "TempFiles";
/// <summary>
/// 清单文件的文件夹名称
/// </summary>
public const string ManifestFilesFolderName = "ManifestFiles";
/// <summary>
/// 记录应用程序版本的文件名称
/// </summary>
public const string AppFootPrintFileName = "ApplicationFootPrint.bytes";
}
}

View File

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

View File

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

View File

@@ -0,0 +1,19 @@

namespace YooAsset
{
internal class RecordFileElement
{
public string InfoFilePath { private set; get; }
public string DataFilePath { private set; get; }
public string DataFileCRC { private set; get; }
public long DataFileSize { private set; get; }
public RecordFileElement(string infoFilePath, string dataFilePath, string dataFileCRC, long dataFileSize)
{
InfoFilePath = infoFilePath;
DataFilePath = dataFilePath;
DataFileCRC = dataFileCRC;
DataFileSize = dataFileSize;
}
}
}

View File

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

View File

@@ -0,0 +1,22 @@

namespace YooAsset
{
internal class TempFileElement
{
public string TempFilePath { private set; get; }
public string TempFileCRC { private set; get; }
public long TempFileSize { private set; get; }
/// <summary>
/// 注意:原子操作对象
/// </summary>
public volatile int Result = 0;
public TempFileElement(string filePath, string fileCRC, long fileSize)
{
TempFilePath = filePath;
TempFileCRC = fileCRC;
TempFileSize = fileSize;
}
}
}

View File

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

View File

@@ -0,0 +1,42 @@
using System.IO;
namespace YooAsset
{
internal class VerifyFileElement
{
public string PackageName { private set; get; }
public string BundleGUID { private set; get; }
public string FileRootPath { private set; get; }
public string DataFilePath { private set; get; }
public string InfoFilePath { private set; get; }
public string DataFileCRC;
public long DataFileSize;
/// <summary>
/// 注意:原子操作对象
/// </summary>
public volatile int Result = 0;
public VerifyFileElement(string packageName, string bundleGUID, string fileRootPath, string dataFilePath, string infoFilePath)
{
PackageName = packageName;
BundleGUID = bundleGUID;
FileRootPath = fileRootPath;
DataFilePath = dataFilePath;
InfoFilePath = infoFilePath;
}
public void DeleteFiles()
{
try
{
Directory.Delete(FileRootPath, true);
}
catch (System.Exception e)
{
YooLogger.Warning($"Failed to delete cache bundle folder : {e}");
}
}
}
}

View File

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

View File

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

View File

@@ -0,0 +1,98 @@

namespace YooAsset
{
internal class DCFSInitializeOperation : FSInitializeFileSystemOperation
{
private enum ESteps
{
None,
CheckAppFootPrint,
SearchCacheFiles,
VerifyCacheFiles,
Done,
}
private readonly DefaultCacheFileSystem _fileSystem;
private SearchCacheFilesOperation _searchCacheFilesOp;
private VerifyCacheFilesOperation _verifyCacheFilesOp;
private ESteps _steps = ESteps.None;
internal DCFSInitializeOperation(DefaultCacheFileSystem fileSystem)
{
_fileSystem = fileSystem;
}
internal override void InternalOnStart()
{
#if UNITY_WEBGL
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"{nameof(DefaultCacheFileSystem)} is not support WEBGL platform !";
#else
_steps = ESteps.CheckAppFootPrint;
#endif
}
internal override void InternalOnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.CheckAppFootPrint)
{
var appFootPrint = new ApplicationFootPrint(_fileSystem);
appFootPrint.Load(_fileSystem.PackageName);
// 如果水印发生变化,则说明覆盖安装后首次打开游戏
if (appFootPrint.IsDirty())
{
_fileSystem.DeleteAllManifestFiles();
appFootPrint.Coverage(_fileSystem.PackageName);
YooLogger.Warning("Delete manifest files when application foot print dirty !");
}
_steps = ESteps.SearchCacheFiles;
}
if (_steps == ESteps.SearchCacheFiles)
{
if (_searchCacheFilesOp == null)
{
_searchCacheFilesOp = new SearchCacheFilesOperation(_fileSystem);
OperationSystem.StartOperation(_fileSystem.PackageName, _searchCacheFilesOp);
}
Progress = _searchCacheFilesOp.Progress;
if (_searchCacheFilesOp.IsDone == false)
return;
_steps = ESteps.VerifyCacheFiles;
}
if (_steps == ESteps.VerifyCacheFiles)
{
if (_verifyCacheFilesOp == null)
{
_verifyCacheFilesOp = new VerifyCacheFilesOperation(_fileSystem, _searchCacheFilesOp.Result);
OperationSystem.StartOperation(_fileSystem.PackageName, _verifyCacheFilesOp);
}
Progress = _verifyCacheFilesOp.Progress;
if (_verifyCacheFilesOp.IsDone == false)
return;
if (_verifyCacheFilesOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
YooLogger.Log($"Package '{_fileSystem.PackageName}' cached files count : {_fileSystem.FileCount}");
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _verifyCacheFilesOp.Error;
}
}
}
}
}

View File

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

View File

@@ -0,0 +1,347 @@
using System.IO;
using UnityEngine;
namespace YooAsset
{
internal class DCFSLoadAssetBundleOperation : FSLoadBundleOperation
{
protected enum ESteps
{
None,
CheckExist,
DownloadFile,
LoadAssetBundle,
CheckResult,
Done,
}
protected readonly DefaultCacheFileSystem _fileSystem;
protected readonly PackageBundle _bundle;
protected FSDownloadFileOperation _downloadFileOp;
protected AssetBundleCreateRequest _createRequest;
private AssetBundle _assetBundle;
private Stream _managedStream;
protected ESteps _steps = ESteps.None;
internal DCFSLoadAssetBundleOperation(DefaultCacheFileSystem fileSystem, PackageBundle bundle)
{
_fileSystem = fileSystem;
_bundle = bundle;
}
internal override void InternalOnStart()
{
_steps = ESteps.CheckExist;
}
internal override void InternalOnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.CheckExist)
{
if (_fileSystem.Exists(_bundle))
{
DownloadProgress = 1f;
DownloadedBytes = _bundle.FileSize;
_steps = ESteps.LoadAssetBundle;
}
else
{
_steps = ESteps.DownloadFile;
}
}
if (_steps == ESteps.DownloadFile)
{
if (_downloadFileOp == null)
{
DownloadParam downloadParam = new DownloadParam(int.MaxValue, 60);
_downloadFileOp = _fileSystem.DownloadFileAsync(_bundle, downloadParam);
}
if (IsWaitForAsyncComplete)
_downloadFileOp.WaitForAsyncComplete();
DownloadProgress = _downloadFileOp.DownloadProgress;
DownloadedBytes = _downloadFileOp.DownloadedBytes;
if (_downloadFileOp.IsDone == false)
return;
if (_downloadFileOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.LoadAssetBundle;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _downloadFileOp.Error;
}
}
if (_steps == ESteps.LoadAssetBundle)
{
if (_bundle.Encrypted)
{
if (_fileSystem.DecryptionServices == null)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"The {nameof(IDecryptionServices)} is null !";
YooLogger.Error(Error);
return;
}
}
if (IsWaitForAsyncComplete)
{
if (_bundle.Encrypted)
{
var decryptResult = _fileSystem.LoadEncryptedAssetBundle(_bundle);
_assetBundle = decryptResult.Result;
_managedStream = decryptResult.ManagedStream;
}
else
{
string filePath = _fileSystem.GetCacheBundleFileLoadPath(_bundle);
_assetBundle = AssetBundle.LoadFromFile(filePath);
}
}
else
{
if (_bundle.Encrypted)
{
var decryptResult = _fileSystem.LoadEncryptedAssetBundleAsync(_bundle);
_createRequest = decryptResult.CreateRequest;
_managedStream = decryptResult.ManagedStream;
}
else
{
string filePath = _fileSystem.GetCacheBundleFileLoadPath(_bundle);
_createRequest = AssetBundle.LoadFromFileAsync(filePath);
}
}
_steps = ESteps.CheckResult;
}
if (_steps == ESteps.CheckResult)
{
if (_createRequest != null)
{
if (IsWaitForAsyncComplete)
{
// 强制挂起主线程(注意:该操作会很耗时)
YooLogger.Warning("Suspend the main thread to load unity bundle.");
_assetBundle = _createRequest.assetBundle;
}
else
{
if (_createRequest.isDone == false)
return;
_assetBundle = _createRequest.assetBundle;
}
}
if (_assetBundle != null)
{
_steps = ESteps.Done;
Result = new AssetBundleResult(_fileSystem, _bundle, _assetBundle, _managedStream);
Status = EOperationStatus.Succeed;
return;
}
// 注意当缓存文件的校验等级为Low的时候并不能保证缓存文件的完整性。
// 说明在AssetBundle文件加载失败的情况下我们需要重新验证文件的完整性
EFileVerifyResult verifyResult = _fileSystem.VerifyCacheFile(_bundle);
if (verifyResult == EFileVerifyResult.Succeed)
{
if (_bundle.Encrypted)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Failed to load encrypted asset bundle file : {_bundle.BundleName}";
YooLogger.Error(Error);
return;
}
// 注意:在安卓移动平台,华为和三星真机上有极小概率加载资源包失败。
// 说明:大多数情况在首次安装下载资源到沙盒内,游戏过程中切换到后台再回到游戏内有很大概率触发!
string filePath = _fileSystem.GetCacheBundleFileLoadPath(_bundle);
byte[] fileData = FileUtility.ReadAllBytes(filePath);
if (fileData != null && fileData.Length > 0)
{
_assetBundle = AssetBundle.LoadFromMemory(fileData);
if (_assetBundle == null)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Failed to load asset bundle from memory : {_bundle.BundleName}";
YooLogger.Error(Error);
}
else
{
_steps = ESteps.Done;
Result = new AssetBundleResult(_fileSystem, _bundle, _assetBundle, null);
Status = EOperationStatus.Succeed;
}
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Failed to read asset bundle file bytes : {_bundle.BundleName}";
YooLogger.Error(Error);
}
}
else
{
_steps = ESteps.Done;
_fileSystem.DeleteCacheBundleFile(_bundle.BundleGUID);
Status = EOperationStatus.Failed;
Error = $"Find corrupted asset bundle file and delete : {_bundle.BundleName}";
YooLogger.Error(Error);
}
}
}
internal override void InternalWaitForAsyncComplete()
{
while (true)
{
if (ExecuteWhileDone())
{
if (_downloadFileOp != null && _downloadFileOp.Status == EOperationStatus.Failed)
YooLogger.Error($"Try load bundle {_bundle.BundleName} from remote !");
_steps = ESteps.Done;
break;
}
}
}
public override void AbortDownloadOperation()
{
if (_steps == ESteps.DownloadFile)
{
if (_downloadFileOp != null)
_downloadFileOp.SetAbort();
}
}
}
internal class DCFSLoadRawBundleOperation : FSLoadBundleOperation
{
protected enum ESteps
{
None,
CheckExist,
DownloadFile,
LoadCacheRawBundle,
Done,
}
protected readonly DefaultCacheFileSystem _fileSystem;
protected readonly PackageBundle _bundle;
protected FSDownloadFileOperation _downloadFileOp;
protected ESteps _steps = ESteps.None;
internal DCFSLoadRawBundleOperation(DefaultCacheFileSystem fileSystem, PackageBundle bundle)
{
_fileSystem = fileSystem;
_bundle = bundle;
}
internal override void InternalOnStart()
{
_steps = ESteps.CheckExist;
}
internal override void InternalOnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.CheckExist)
{
if (_fileSystem.Exists(_bundle))
{
DownloadProgress = 1f;
DownloadedBytes = _bundle.FileSize;
_steps = ESteps.LoadCacheRawBundle;
}
else
{
_steps = ESteps.DownloadFile;
}
}
if (_steps == ESteps.DownloadFile)
{
if (_downloadFileOp == null)
{
DownloadParam downloadParam = new DownloadParam(int.MaxValue, 60);
_downloadFileOp = _fileSystem.DownloadFileAsync(_bundle, downloadParam);
}
if (IsWaitForAsyncComplete)
_downloadFileOp.WaitForAsyncComplete();
DownloadProgress = _downloadFileOp.DownloadProgress;
DownloadedBytes = _downloadFileOp.DownloadedBytes;
if (_downloadFileOp.IsDone == false)
return;
if (_downloadFileOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.LoadCacheRawBundle;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _downloadFileOp.Error;
}
}
if (_steps == ESteps.LoadCacheRawBundle)
{
string filePath = _fileSystem.GetCacheBundleFileLoadPath(_bundle);
if (File.Exists(filePath))
{
_steps = ESteps.Done;
Result = new RawBundleResult(_fileSystem, _bundle);
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Can not found cache raw bundle file : {filePath}";
YooLogger.Error(Error);
}
}
}
internal override void InternalWaitForAsyncComplete()
{
while (true)
{
if (ExecuteWhileDone())
{
//TODO 拷贝本地文件失败也会触发该错误!
if (_downloadFileOp != null && _downloadFileOp.Status == EOperationStatus.Failed)
YooLogger.Error($"Try load bundle {_bundle.BundleName} from remote !");
_steps = ESteps.Done;
break;
}
}
}
public override void AbortDownloadOperation()
{
if (_steps == ESteps.DownloadFile)
{
if (_downloadFileOp != null)
_downloadFileOp.SetAbort();
}
}
}
}

View File

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

View File

@@ -0,0 +1,158 @@
using System.IO;
namespace YooAsset
{
internal class DCFSLoadPackageManifestOperation : FSLoadPackageManifestOperation
{
private enum ESteps
{
None,
DownloadPackageHash,
DownloadPackageManifest,
LoadCachePackageHash,
LoadCachePackageManifest,
Done,
}
private readonly DefaultCacheFileSystem _fileSystem;
private readonly string _packageVersion;
private readonly int _timeout;
private DownloadPackageHashOperation _downloadPackageHashOp;
private DownloadPackageManifestOperation _downloadPackageManifestOp;
private LoadCachePackageHashOperation _loadCachePackageHashOp;
private LoadCachePackageManifestOperation _loadCachePackageManifestOp;
private ESteps _steps = ESteps.None;
internal DCFSLoadPackageManifestOperation(DefaultCacheFileSystem fileSystem, string packageVersion, int timeout)
{
_fileSystem = fileSystem;
_packageVersion = packageVersion;
_timeout = timeout;
}
internal override void InternalOnStart()
{
_steps = ESteps.DownloadPackageHash;
}
internal override void InternalOnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.DownloadPackageHash)
{
if (_downloadPackageHashOp == null)
{
_downloadPackageHashOp = new DownloadPackageHashOperation(_fileSystem, _packageVersion, _timeout);
OperationSystem.StartOperation(_fileSystem.PackageName, _downloadPackageHashOp);
}
if (_downloadPackageHashOp.IsDone == false)
return;
if (_downloadPackageHashOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.DownloadPackageManifest;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _downloadPackageHashOp.Error;
}
}
if (_steps == ESteps.DownloadPackageManifest)
{
if (_downloadPackageManifestOp == null)
{
_downloadPackageManifestOp = new DownloadPackageManifestOperation(_fileSystem, _packageVersion, _timeout);
OperationSystem.StartOperation(_fileSystem.PackageName, _downloadPackageManifestOp);
}
if (_downloadPackageManifestOp.IsDone == false)
return;
if (_downloadPackageManifestOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.LoadCachePackageHash;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _downloadPackageManifestOp.Error;
}
}
if (_steps == ESteps.LoadCachePackageHash)
{
if (_loadCachePackageHashOp == null)
{
_loadCachePackageHashOp = new LoadCachePackageHashOperation(_fileSystem, _packageVersion);
OperationSystem.StartOperation(_fileSystem.PackageName, _loadCachePackageHashOp);
}
if (_loadCachePackageHashOp.IsDone == false)
return;
if (_loadCachePackageHashOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.LoadCachePackageManifest;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _loadCachePackageHashOp.Error;
ClearCacheFatalFile();
}
}
if (_steps == ESteps.LoadCachePackageManifest)
{
if (_loadCachePackageManifestOp == null)
{
string packageHash = _loadCachePackageHashOp.PackageHash;
_loadCachePackageManifestOp = new LoadCachePackageManifestOperation(_fileSystem, _packageVersion, packageHash);
OperationSystem.StartOperation(_fileSystem.PackageName, _loadCachePackageManifestOp);
}
Progress = _loadCachePackageManifestOp.Progress;
if (_loadCachePackageManifestOp.IsDone == false)
return;
if (_loadCachePackageManifestOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.Done;
Manifest = _loadCachePackageManifestOp.Manifest;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _loadCachePackageManifestOp.Error;
ClearCacheFatalFile();
}
}
}
private void ClearCacheFatalFile()
{
// 注意:如果加载沙盒内的清单报错,为了避免流程被卡住,主动把损坏的文件删除。
string manifestFilePath = _fileSystem.GetCachePackageManifestFilePath(_packageVersion);
if (File.Exists(manifestFilePath))
{
YooLogger.Warning($"Invalid cache manifest file have been removed : {manifestFilePath}");
File.Delete(manifestFilePath);
}
string hashFilePath = _fileSystem.GetCachePackageHashFilePath(_packageVersion);
if (File.Exists(hashFilePath))
{
File.Delete(hashFilePath);
}
}
}
}

View File

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

View File

@@ -0,0 +1,62 @@

namespace YooAsset
{
internal class DCFSRequestPackageVersionOperation : FSRequestPackageVersionOperation
{
private enum ESteps
{
None,
GetPackageVersion,
Done,
}
private readonly DefaultCacheFileSystem _fileSystem;
private readonly bool _appendTimeTicks;
private readonly int _timeout;
private RequestRemotePackageVersionOperation _requestRemotePackageVersionOp;
private ESteps _steps = ESteps.None;
internal DCFSRequestPackageVersionOperation(DefaultCacheFileSystem fileSystem, bool appendTimeTicks, int timeout)
{
_fileSystem = fileSystem;
_appendTimeTicks = appendTimeTicks;
_timeout = timeout;
}
internal override void InternalOnStart()
{
_steps = ESteps.GetPackageVersion;
}
internal override void InternalOnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.GetPackageVersion)
{
if (_requestRemotePackageVersionOp == null)
{
_requestRemotePackageVersionOp = new RequestRemotePackageVersionOperation(_fileSystem, _appendTimeTicks, _timeout);
OperationSystem.StartOperation(_fileSystem.PackageName, _requestRemotePackageVersionOp);
}
Progress = _requestRemotePackageVersionOp.Progress;
if (_requestRemotePackageVersionOp.IsDone == false)
return;
if (_requestRemotePackageVersionOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.Done;
PackageVersion = _requestRemotePackageVersionOp.PackageVersion;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _requestRemotePackageVersionOp.Error;
}
}
}
}
}

View File

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

View File

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

View File

@@ -0,0 +1,67 @@
using System.Collections;
using System.Collections.Generic;
namespace YooAsset
{
internal sealed class ClearAllCacheBundleFilesOperation : FSClearCacheFilesOperation
{
private enum ESteps
{
None,
GetAllCacheFiles,
ClearAllCacheFiles,
Done,
}
private readonly DefaultCacheFileSystem _fileSystem;
private List<string> _allBundleGUIDs;
private int _fileTotalCount = 0;
private ESteps _steps = ESteps.None;
internal ClearAllCacheBundleFilesOperation(DefaultCacheFileSystem fileSystem)
{
_fileSystem = fileSystem;
}
internal override void InternalOnStart()
{
_steps = ESteps.GetAllCacheFiles;
}
internal override void InternalOnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.GetAllCacheFiles)
{
_allBundleGUIDs = _fileSystem.GetAllCachedBundleGUIDs();
_fileTotalCount = _allBundleGUIDs.Count;
_steps = ESteps.ClearAllCacheFiles;
YooLogger.Log($"Found all cache files count : {_fileTotalCount}");
}
if (_steps == ESteps.ClearAllCacheFiles)
{
for (int i = _allBundleGUIDs.Count - 1; i >= 0; i--)
{
string bundleGUID = _allBundleGUIDs[i];
_fileSystem.DeleteCacheBundleFile(bundleGUID);
_allBundleGUIDs.RemoveAt(i);
if (OperationSystem.IsBusy)
break;
}
if (_fileTotalCount == 0)
Progress = 1.0f;
else
Progress = 1.0f - (_allBundleGUIDs.Count / _fileTotalCount);
if (_allBundleGUIDs.Count == 0)
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
}
}
}
}

View File

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

View File

@@ -0,0 +1,63 @@
using System;
using System.IO;
namespace YooAsset
{
internal sealed class ClearAllCacheManifestFilesOperation : FSClearCacheFilesOperation
{
private enum ESteps
{
None,
ClearAllCacheFiles,
Done,
}
private readonly DefaultCacheFileSystem _fileSystem;
private ESteps _steps = ESteps.None;
internal ClearAllCacheManifestFilesOperation(DefaultCacheFileSystem fileSystem)
{
_fileSystem = fileSystem;
}
internal override void InternalOnStart()
{
_steps = ESteps.ClearAllCacheFiles;
}
internal override void InternalOnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.ClearAllCacheFiles)
{
try
{
// 注意:如果正在下载资源清单,会有几率触发异常!
string directoryRoot = _fileSystem.GetCacheManifestFilesRoot();
DirectoryInfo directoryInfo = new DirectoryInfo(directoryRoot);
if (directoryInfo.Exists)
{
foreach (FileInfo fileInfo in directoryInfo.GetFiles())
{
string fileName = fileInfo.Name;
if (fileName == DefaultCacheFileSystemDefine.AppFootPrintFileName)
continue;
fileInfo.Delete();
}
}
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
catch (Exception ex)
{
_steps = ESteps.Done;
Error = ex.Message;
Status = EOperationStatus.Failed;
}
}
}
}
}

View File

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

View File

@@ -0,0 +1,120 @@
using System.Collections.Generic;
namespace YooAsset
{
internal class ClearCacheBundleFilesByTagsOperaiton : FSClearCacheFilesOperation
{
private enum ESteps
{
None,
CheckArgs,
GetTagsCacheFiles,
ClearTagsCacheFiles,
Done,
}
private readonly DefaultCacheFileSystem _fileSystem;
private readonly PackageManifest _manifest;
private readonly object _clearParam;
private string[] _tags;
private List<string> _clearBundleGUIDs;
private int _clearFileTotalCount = 0;
private ESteps _steps = ESteps.None;
internal ClearCacheBundleFilesByTagsOperaiton(DefaultCacheFileSystem fileSystem, PackageManifest manifest, object clearParam)
{
_fileSystem = fileSystem;
_manifest = manifest;
_clearParam = clearParam;
}
internal override void InternalOnStart()
{
_steps = ESteps.CheckArgs;
}
internal override void InternalOnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.CheckArgs)
{
if (_clearParam == null)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = "Clear param is null !";
return;
}
if (_clearParam is string)
{
_tags = new string[] { _clearParam as string };
}
else if (_clearParam is List<string>)
{
var tempList = _clearParam as List<string>;
_tags = tempList.ToArray();
}
else if (_clearParam is string[])
{
_tags = _clearParam as string[];
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Invalid clear param : {_clearParam.GetType().FullName}";
return;
}
_steps = ESteps.GetTagsCacheFiles;
}
if (_steps == ESteps.GetTagsCacheFiles)
{
_clearBundleGUIDs = GetTagsBundleGUIDs();
_clearFileTotalCount = _clearBundleGUIDs.Count;
_steps = ESteps.ClearTagsCacheFiles;
}
if (_steps == ESteps.ClearTagsCacheFiles)
{
for (int i = _clearBundleGUIDs.Count - 1; i >= 0; i--)
{
string bundleGUID = _clearBundleGUIDs[i];
_fileSystem.DeleteCacheBundleFile(bundleGUID);
_clearBundleGUIDs.RemoveAt(i);
if (OperationSystem.IsBusy)
break;
}
if (_clearFileTotalCount == 0)
Progress = 1.0f;
else
Progress = 1.0f - (_clearBundleGUIDs.Count / _clearFileTotalCount);
if (_clearBundleGUIDs.Count == 0)
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
}
}
private List<string> GetTagsBundleGUIDs()
{
var allBundleGUIDs = _fileSystem.GetAllCachedBundleGUIDs();
List<string> result = new List<string>(allBundleGUIDs.Count);
foreach (var bundleGUID in allBundleGUIDs)
{
if (_manifest.TryGetPackageBundleByBundleGUID(bundleGUID, out PackageBundle bundle))
{
if (bundle.HasTag(_tags))
{
result.Add(bundleGUID);
}
}
}
return result;
}
}
}

View File

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

View File

@@ -0,0 +1,83 @@
using System.Collections;
using System.Collections.Generic;
namespace YooAsset
{
internal sealed class ClearUnusedCacheBundleFilesOperation : FSClearCacheFilesOperation
{
private enum ESteps
{
None,
GetUnusedCacheFiles,
ClearUnusedCacheFiles,
Done,
}
private readonly DefaultCacheFileSystem _fileSystem;
private readonly PackageManifest _manifest;
private List<string> _unusedBundleGUIDs;
private int _unusedFileTotalCount = 0;
private ESteps _steps = ESteps.None;
internal ClearUnusedCacheBundleFilesOperation(DefaultCacheFileSystem fileSystem, PackageManifest manifest)
{
_fileSystem = fileSystem;
_manifest = manifest;
}
internal override void InternalOnStart()
{
_steps = ESteps.GetUnusedCacheFiles;
}
internal override void InternalOnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.GetUnusedCacheFiles)
{
_unusedBundleGUIDs = GetUnusedBundleGUIDs();
_unusedFileTotalCount = _unusedBundleGUIDs.Count;
_steps = ESteps.ClearUnusedCacheFiles;
YooLogger.Log($"Found unused cache files count : {_unusedFileTotalCount}");
}
if (_steps == ESteps.ClearUnusedCacheFiles)
{
for (int i = _unusedBundleGUIDs.Count - 1; i >= 0; i--)
{
string bundleGUID = _unusedBundleGUIDs[i];
_fileSystem.DeleteCacheBundleFile(bundleGUID);
_unusedBundleGUIDs.RemoveAt(i);
if (OperationSystem.IsBusy)
break;
}
if (_unusedFileTotalCount == 0)
Progress = 1.0f;
else
Progress = 1.0f - (_unusedBundleGUIDs.Count / _unusedFileTotalCount);
if (_unusedBundleGUIDs.Count == 0)
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
}
}
private List<string> GetUnusedBundleGUIDs()
{
var allBundleGUIDs = _fileSystem.GetAllCachedBundleGUIDs();
List<string> result = new List<string>(allBundleGUIDs.Count);
foreach (var bundleGUID in allBundleGUIDs)
{
if (_manifest.IsIncludeBundleFile(bundleGUID) == false)
{
result.Add(bundleGUID);
}
}
return result;
}
}
}

View File

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

Some files were not shown because too many files have changed in this diff Show More