Update runtime logic

pull/40/head
hevinci 2022-09-28 11:55:12 +08:00
parent c8d3f6efed
commit a4c8fb6e1b
10 changed files with 146 additions and 214 deletions

View File

@ -11,7 +11,7 @@ namespace YooAsset
/// </summary>
internal abstract class PatchCacheVerifier
{
public abstract bool InitVerifier(PatchManifest appPatchManifest, PatchManifest localPatchManifest, bool weaklyUpdate);
public abstract bool InitVerifier(HostPlayModeImpl impl, bool weaklyUpdate);
public abstract bool UpdateVerifier();
public abstract float GetVerifierProgress();
@ -42,22 +42,18 @@ namespace YooAsset
private int _verifyMaxNum;
private int _verifyTotalCount;
public override bool InitVerifier(PatchManifest appPatchManifest, PatchManifest localPatchManifest, bool weaklyUpdate)
public override bool InitVerifier(HostPlayModeImpl impl, bool weaklyUpdate)
{
// 遍历所有文件然后验证并缓存合法文件
foreach (var patchBundle in localPatchManifest.BundleList)
foreach (var patchBundle in impl.LocalPatchManifest.BundleList)
{
// 忽略缓存文件
if (CacheSystem.IsCached(patchBundle))
continue;
// 忽略APP资源
// 注意如果是APP资源并且哈希值相同则不需要下载
if (appPatchManifest.TryGetPatchBundle(patchBundle.BundleName, out PatchBundle appPatchBundle))
{
if (appPatchBundle.IsBuildin && appPatchBundle.Equals(patchBundle))
continue;
}
if (impl.IsBuildinPatchBundle(patchBundle))
continue;
// 注意:在弱联网模式下,我们需要验证指定资源版本的所有资源完整性
if (weaklyUpdate)
@ -167,22 +163,18 @@ namespace YooAsset
private int _verifyMaxNum;
private int _verifyTotalCount;
public override bool InitVerifier(PatchManifest appPatchManifest, PatchManifest localPatchManifest, bool weaklyUpdate)
public override bool InitVerifier(HostPlayModeImpl impl, bool weaklyUpdate)
{
// 遍历所有文件然后验证并缓存合法文件
foreach (var patchBundle in localPatchManifest.BundleList)
foreach (var patchBundle in impl.LocalPatchManifest.BundleList)
{
// 忽略缓存文件
if (CacheSystem.IsCached(patchBundle))
continue;
// 忽略APP资源
// 注意如果是APP资源并且哈希值相同则不需要下载
if (appPatchManifest.TryGetPatchBundle(patchBundle.BundleName, out PatchBundle appPatchBundle))
{
if (appPatchBundle.IsBuildin && appPatchBundle.Equals(patchBundle))
continue;
}
if (impl.IsBuildinPatchBundle(patchBundle))
continue;
// 注意:在弱联网模式下,我们需要验证指定资源版本的所有资源完整性
if (weaklyUpdate)

View File

@ -134,75 +134,15 @@ namespace YooAsset
/// </summary>
internal sealed class HostPlayModeInitializationOperation : InitializationOperation
{
private enum ESteps
internal HostPlayModeInitializationOperation()
{
None,
LoadManifest,
CopyManifest,
Done,
}
private readonly HostPlayModeImpl _impl;
private readonly string _buildinPackageName;
private AppManifestLoader _appManifestLoader;
private AppManifestCopyer _appManifestCopyer;
private ESteps _steps = ESteps.None;
internal HostPlayModeInitializationOperation(HostPlayModeImpl impl, string buildinPackageName)
{
_impl = impl;
_buildinPackageName = buildinPackageName;
_appManifestLoader = new AppManifestLoader(buildinPackageName);
}
internal override void Start()
{
_steps = ESteps.LoadManifest;
Status = EOperationStatus.Succeed;
}
internal override void Update()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.LoadManifest)
{
_appManifestLoader.Update();
Progress = _appManifestLoader.Progress();
if (_appManifestLoader.IsDone() == false)
return;
if (_appManifestLoader.Result == null)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _appManifestLoader.Error;
}
else
{
_impl.SetAppPatchManifest(_appManifestLoader.Result);
_impl.SetLocalPatchManifest(_appManifestLoader.Result);
_appManifestCopyer = new AppManifestCopyer(_buildinPackageName, _appManifestLoader.BuildinPackageCRC);
_steps = ESteps.CopyManifest;
}
}
if (_steps == ESteps.CopyManifest)
{
_appManifestCopyer.Update();
if (_appManifestCopyer.IsDone() == false)
return;
if (_appManifestCopyer.Result == false)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _appManifestCopyer.Error;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
}
}
}

View File

@ -154,7 +154,7 @@ namespace YooAsset
if (_steps == ESteps.InitVerifyingCache)
{
_patchCacheVerifier.InitVerifier(_impl.AppPatchManifest, _impl.LocalPatchManifest, false);
_patchCacheVerifier.InitVerifier(_impl, false);
_verifyTime = UnityEngine.Time.realtimeSinceStartup;
_steps = ESteps.UpdateVerifyingCache;
}
@ -286,7 +286,7 @@ namespace YooAsset
if (_steps == ESteps.InitVerifyingCache)
{
if (_patchCacheVerifier.InitVerifier(_impl.AppPatchManifest, _impl.LocalPatchManifest, true))
if (_patchCacheVerifier.InitVerifier(_impl, true))
{
_verifyTime = UnityEngine.Time.realtimeSinceStartup;
_steps = ESteps.UpdateVerifyingCache;

View File

@ -205,12 +205,8 @@ namespace YooAsset
continue;
// 忽略APP资源
// 注意如果是APP资源并且哈希值相同则不需要下载
if (_impl.AppPatchManifest.TryGetPatchBundle(patchBundle.BundleName, out PatchBundle appPatchBundle))
{
if (appPatchBundle.IsBuildin && appPatchBundle.Equals(patchBundle))
continue;
}
if (_impl.IsBuildinPatchBundle(patchBundle))
continue;
downloadList.Add(patchBundle);
}

View File

@ -38,21 +38,16 @@ namespace YooAsset
public int Flags;
/// <summary>
/// 是否为加密文件
/// </summary>
public bool IsEncrypted { private set; get; }
/// <summary>
/// 是否为内置文件
/// </summary>
public bool IsBuildin { private set; get; }
/// <summary>
/// 是否为原生文件
/// </summary>
public bool IsRawFile { private set; get; }
/// <summary>
/// 是否为加密文件
/// </summary>
public bool IsEncrypted { private set; get; }
/// <summary>
/// 文件名称
/// </summary>
@ -69,7 +64,7 @@ namespace YooAsset
if (string.IsNullOrEmpty(_cachedFilePath) == false)
return _cachedFilePath;
string cacheRoot = SandboxHelper.GetCacheFolderPath();
string cacheRoot = SandboxHelper.GetCacheFolderPath();
_cachedFilePath = $"{cacheRoot}/{FileName}";
return _cachedFilePath;
}
@ -104,16 +99,14 @@ namespace YooAsset
/// <summary>
/// 设置Flags
/// </summary>
public void SetFlagsValue(bool isEncrypted, bool isBuildin, bool isRawFile)
public void SetFlagsValue(bool isRawFile, bool isEncrypted)
{
IsEncrypted = isEncrypted;
IsBuildin = isBuildin;
IsRawFile = isRawFile;
IsEncrypted = isEncrypted;
BitMask32 mask = new BitMask32(0);
if (isEncrypted) mask.Open(0);
if (isBuildin) mask.Open(1);
if (isRawFile) mask.Open(2);
if (isRawFile) mask.Open(0);
if (isEncrypted) mask.Open(1);
Flags = mask;
}
@ -123,9 +116,8 @@ namespace YooAsset
public void ParseFlagsValue()
{
BitMask32 value = Flags;
IsEncrypted = value.Test(0);
IsBuildin = value.Test(1);
IsRawFile = value.Test(2);
IsRawFile = value.Test(0);
IsEncrypted = value.Test(1);
}
/// <summary>
@ -179,11 +171,11 @@ namespace YooAsset
}
/// <summary>
/// 是否为纯内置资源不带任何Tag的资源
/// 是否包含任意Tags
/// </summary>
public bool IsPureBuildin()
public bool HasAnyTags()
{
if (Tags == null || Tags.Length == 0)
if (Tags != null && Tags.Length > 0)
return true;
else
return false;
@ -196,7 +188,7 @@ namespace YooAsset
{
if (FileHash == otherBundle.FileHash)
return true;
return false;
}
}

View File

@ -32,11 +32,6 @@ namespace YooAsset
/// </summary>
public string PackageName;
/// <summary>
/// 内置资源的标签列表(首包资源)
/// </summary>
public string BuildinTags;
/// <summary>
/// 资源列表(主动收集的资源列表)
/// </summary>

View File

@ -8,24 +8,25 @@ namespace YooAsset
internal class HostPlayModeImpl : IBundleServices
{
// 补丁清单
internal PatchManifest AppPatchManifest { private set; get; }
internal PatchManifest LocalPatchManifest { private set; get; }
// 参数相关
private bool _locationToLower;
private string _defaultHostServer;
private string _fallbackHostServer;
private IQueryServices _queryServices;
/// <summary>
/// 异步初始化
/// </summary>
public InitializationOperation InitializeAsync(bool locationToLower, string buildinPackageName, string defaultHostServer, string fallbackHostServer)
public InitializationOperation InitializeAsync(bool locationToLower, string defaultHostServer, string fallbackHostServer, IQueryServices queryServices)
{
_locationToLower = locationToLower;
_defaultHostServer = defaultHostServer;
_fallbackHostServer = fallbackHostServer;
_queryServices = queryServices;
var operation = new HostPlayModeInitializationOperation(this, buildinPackageName);
var operation = new HostPlayModeInitializationOperation();
OperationSystem.StartOperation(operation);
return operation;
}
@ -118,12 +119,8 @@ namespace YooAsset
continue;
// 忽略APP资源
// 注意如果是APP资源并且哈希值相同则不需要下载
if (AppPatchManifest.TryGetPatchBundle(patchBundle.BundleName, out PatchBundle appPatchBundle))
{
if (appPatchBundle.IsBuildin && appPatchBundle.Equals(patchBundle))
continue;
}
if (IsBuildinPatchBundle(patchBundle))
continue;
downloadList.Add(patchBundle);
}
@ -150,17 +147,11 @@ namespace YooAsset
continue;
// 忽略APP资源
// 注意如果是APP资源并且哈希值相同则不需要下载
if (AppPatchManifest.TryGetPatchBundle(patchBundle.BundleName, out PatchBundle appPatchBundle))
{
if (appPatchBundle.IsBuildin && appPatchBundle.Equals(patchBundle))
continue;
}
if (IsBuildinPatchBundle(patchBundle))
continue;
// 如果是纯内置资源,则统一下载
// 注意:可能是新增的或者变化的内置资源
// 注意:可能是由热更资源转换的内置资源
if (patchBundle.IsPureBuildin())
// 如果未带任何标记,则统一下载
if (patchBundle.HasAnyTags() == false)
{
downloadList.Add(patchBundle);
}
@ -220,12 +211,8 @@ namespace YooAsset
continue;
// 忽略APP资源
// 注意如果是APP资源并且哈希值相同则不需要下载
if (AppPatchManifest.TryGetPatchBundle(patchBundle.BundleName, out PatchBundle appPatchBundle))
{
if (appPatchBundle.IsBuildin && appPatchBundle.Equals(patchBundle))
continue;
}
if (IsBuildinPatchBundle(patchBundle))
continue;
downloadList.Add(patchBundle);
}
@ -245,20 +232,19 @@ namespace YooAsset
private List<BundleInfo> GetUnpackListByTags(string[] tags)
{
List<PatchBundle> downloadList = new List<PatchBundle>(1000);
foreach (var patchBundle in AppPatchManifest.BundleList)
foreach (var patchBundle in LocalPatchManifest.BundleList)
{
// 如果不是内置资源
if (patchBundle.IsBuildin == false)
continue;
// 忽略缓存文件
if (CacheSystem.IsCached(patchBundle))
continue;
// 查询DLC资源
if (patchBundle.HasTag(tags))
if (IsBuildinPatchBundle(patchBundle))
{
downloadList.Add(patchBundle);
if (patchBundle.HasTag(tags))
{
downloadList.Add(patchBundle);
}
}
}
@ -277,17 +263,16 @@ namespace YooAsset
private List<BundleInfo> GetUnpackListByAll()
{
List<PatchBundle> downloadList = new List<PatchBundle>(1000);
foreach (var patchBundle in AppPatchManifest.BundleList)
foreach (var patchBundle in LocalPatchManifest.BundleList)
{
// 如果不是内置资源
if (patchBundle.IsBuildin == false)
continue;
// 忽略缓存文件
if (CacheSystem.IsCached(patchBundle))
continue;
downloadList.Add(patchBundle);
if (IsBuildinPatchBundle(patchBundle))
{
downloadList.Add(patchBundle);
}
}
return PatchHelper.ConvertToUnpackList(downloadList);
@ -322,16 +307,15 @@ namespace YooAsset
return bundleInfo;
}
// 设置资源清单
internal void SetAppPatchManifest(PatchManifest patchManifest)
{
AppPatchManifest = patchManifest;
}
internal void SetLocalPatchManifest(PatchManifest patchManifest)
{
LocalPatchManifest = patchManifest;
LocalPatchManifest.InitAssetPathMapping(_locationToLower);
}
internal bool IsBuildinPatchBundle(PatchBundle patchBundle)
{
return _queryServices.QueryStreamingAssets(patchBundle.FileName);
}
#region IBundleServices接口
private BundleInfo CreateBundleInfo(PatchBundle patchBundle)
@ -347,13 +331,10 @@ namespace YooAsset
}
// 查询APP资源
if (AppPatchManifest.TryGetPatchBundle(patchBundle.BundleName, out PatchBundle appPatchBundle))
if (IsBuildinPatchBundle(patchBundle))
{
if (appPatchBundle.IsBuildin && appPatchBundle.Equals(patchBundle))
{
BundleInfo bundleInfo = new BundleInfo(appPatchBundle, BundleInfo.ELoadMode.LoadFromStreaming);
return bundleInfo;
}
BundleInfo bundleInfo = new BundleInfo(patchBundle, BundleInfo.ELoadMode.LoadFromStreaming);
return bundleInfo;
}
// 从服务端下载

View File

@ -0,0 +1,11 @@

namespace YooAsset
{
public interface IQueryServices
{
/// <summary>
/// 查询内置资源
/// </summary>
bool QueryStreamingAssets(string fileName);
}
}

View File

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

View File

@ -40,11 +40,6 @@ namespace YooAsset
/// </summary>
public bool LocationToLower = false;
/// <summary>
/// 内置的资源包裹名称
/// </summary>
public string BuildinPackageName = string.Empty;
/// <summary>
/// 资源定位服务接口
/// </summary>
@ -83,6 +78,10 @@ namespace YooAsset
/// </summary>
public class OfflinePlayModeParameters : InitializeParameters
{
/// <summary>
/// 内置的资源包裹名称
/// </summary>
public string BuildinPackageName = string.Empty;
}
/// <summary>
@ -100,11 +99,6 @@ namespace YooAsset
/// </summary>
public string FallbackHostServer;
/// <summary>
/// 当缓存池被污染的时候清理缓存池
/// </summary>
public bool ClearCacheWhenDirty = false;
#if UNITY_WEBGL
/// <summary>
/// WEBGL模式不支持多线程下载
@ -121,6 +115,11 @@ namespace YooAsset
/// 下载文件校验等级
/// </summary>
public EVerifyLevel VerifyLevel = EVerifyLevel.High;
/// <summary>
/// 查询服务类
/// </summary>
public IQueryServices QueryServices = null;
}
@ -151,36 +150,45 @@ namespace YooAsset
if (parameters == null)
throw new Exception($"YooAsset create parameters is null.");
if (string.IsNullOrEmpty(parameters.BuildinPackageName))
throw new Exception($"{nameof(parameters.BuildinPackageName)} is empty.");
if (parameters.LocationServices == null)
throw new Exception($"{nameof(IBundleServices)} is null.");
#if !UNITY_EDITOR
if (parameters is EditorSimulateModeParameters)
throw new Exception($"Editor simulate mode only support unity editor.");
#endif
_locationServices = parameters.LocationServices;
// 创建驱动器
if (_isInitialize == false)
{
_isInitialize = true;
UnityEngine.GameObject driverGo = new UnityEngine.GameObject("[YooAsset]");
driverGo.AddComponent<YooAssetDriver>();
UnityEngine.Object.DontDestroyOnLoad(driverGo);
#if DEBUG
driverGo.AddComponent<RemoteDebuggerInRuntime>();
#endif
}
// 鉴定运行模式
if (parameters is EditorSimulateModeParameters)
_playMode = EPlayMode.EditorSimulateMode;
else if (parameters is OfflinePlayModeParameters)
_playMode = EPlayMode.OfflinePlayMode;
else if (parameters is HostPlayModeParameters)
_playMode = EPlayMode.HostPlayMode;
else
throw new NotImplementedException();
if (parameters.LocationServices == null)
throw new Exception($"{nameof(IBundleServices)} is null.");
if (_playMode == EPlayMode.OfflinePlayMode)
{
var playModeParameters = parameters as OfflinePlayModeParameters;
if (string.IsNullOrEmpty(playModeParameters.BuildinPackageName))
throw new Exception($"{nameof(playModeParameters.BuildinPackageName)} is empty.");
}
if (_playMode == EPlayMode.HostPlayMode)
{
var playModeParameters = parameters as HostPlayModeParameters;
if (playModeParameters.QueryServices == null)
throw new Exception($"{nameof(IQueryServices)} is null.");
}
if (_isInitialize)
{
throw new Exception("YooAsset is initialized yet.");
}
_locationServices = parameters.LocationServices;
// 检测参数范围
if (parameters.AssetLoadingMaxNumber < 1)
{
@ -193,17 +201,20 @@ namespace YooAsset
YooLogger.Warning($"{nameof(parameters.OperationSystemMaxTimeSlice)} minimum value is 30 milliseconds");
}
// 鉴定运行模式
if (parameters is EditorSimulateModeParameters)
_playMode = EPlayMode.EditorSimulateMode;
else if (parameters is OfflinePlayModeParameters)
_playMode = EPlayMode.OfflinePlayMode;
else if (parameters is HostPlayModeParameters)
_playMode = EPlayMode.HostPlayMode;
else
throw new NotImplementedException();
// 创建驱动器
if (_isInitialize == false)
{
_isInitialize = true;
UnityEngine.GameObject driverGo = new UnityEngine.GameObject("[YooAsset]");
driverGo.AddComponent<YooAssetDriver>();
UnityEngine.Object.DontDestroyOnLoad(driverGo);
// 初始化异步操作系统
#if DEBUG
driverGo.AddComponent<RemoteDebuggerInRuntime>();
#endif
}
// 初始化异步系统
OperationSystem.Initialize(parameters.OperationSystemMaxTimeSlice);
// 初始化下载系统
@ -226,29 +237,32 @@ namespace YooAsset
_editorSimulateModeImpl = new EditorSimulateModeImpl();
_bundleServices = _editorSimulateModeImpl;
AssetSystem.Initialize(true, parameters.AssetLoadingMaxNumber, parameters.DecryptionServices, _bundleServices);
var editorSimulateModeParameters = parameters as EditorSimulateModeParameters;
var simulateModeParameters = parameters as EditorSimulateModeParameters;
initializeOperation = _editorSimulateModeImpl.InitializeAsync(
editorSimulateModeParameters.LocationToLower,
editorSimulateModeParameters.SimulatePatchManifestPath);
simulateModeParameters.LocationToLower,
simulateModeParameters.SimulatePatchManifestPath);
}
else if (_playMode == EPlayMode.OfflinePlayMode)
{
_offlinePlayModeImpl = new OfflinePlayModeImpl();
_bundleServices = _offlinePlayModeImpl;
AssetSystem.Initialize(false, parameters.AssetLoadingMaxNumber, parameters.DecryptionServices, _bundleServices);
initializeOperation = _offlinePlayModeImpl.InitializeAsync(parameters.LocationToLower, parameters.BuildinPackageName);
var playModeParameters = parameters as OfflinePlayModeParameters;
initializeOperation = _offlinePlayModeImpl.InitializeAsync(
playModeParameters.LocationToLower,
playModeParameters.BuildinPackageName);
}
else if (_playMode == EPlayMode.HostPlayMode)
{
_hostPlayModeImpl = new HostPlayModeImpl();
_bundleServices = _hostPlayModeImpl;
AssetSystem.Initialize(false, parameters.AssetLoadingMaxNumber, parameters.DecryptionServices, _bundleServices);
var hostPlayModeParameters = parameters as HostPlayModeParameters;
var playModeParameters = parameters as HostPlayModeParameters;
initializeOperation = _hostPlayModeImpl.InitializeAsync(
hostPlayModeParameters.LocationToLower,
hostPlayModeParameters.BuildinPackageName,
hostPlayModeParameters.DefaultHostServer,
hostPlayModeParameters.FallbackHostServer);
playModeParameters.LocationToLower,
playModeParameters.DefaultHostServer,
playModeParameters.FallbackHostServer,
playModeParameters.QueryServices);
}
else
{