BITKit/Src/Unity/Scripts/Assets/BITFramework.cs

411 lines
16 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using BITKit.IO;
using BITKit.UX;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.UIElements;
using YooAsset;
using Debug = UnityEngine.Debug;
namespace BITKit
{
public class BITFramework : MonoBehaviour
{
private static System.Diagnostics.Stopwatch Stopwatch;
[RuntimeInitializeOnLoadMethod]
private static void Reload()
{
Stopwatch = new Stopwatch();
#if UNITY_EDITOR
#else
SplashScreen.Stop(SplashScreen.StopBehavior.StopImmediate);
#endif
}
// [SerializeField] private AssetReference serviceReference;
// private async void Start()
// {
// if(InitializationState is not InitializationState.None)return;
// InitializationState = InitializationState.Initializing;
// var asyncOperationHandle = serviceReference.LoadAssetAsync<GameObject>();
// await UniTask.WaitUntil(() => asyncOperationHandle.IsDone);
// DontDestroyOnLoad(Instantiate(asyncOperationHandle.Result));
// Stopwatch.Stop();
// BIT4Log.Log<BITFramework>($"BITFramework加载完成,耗时:{Stopwatch.ElapsedMilliseconds}ms");
// }
[SerializeReference, SubclassSelector] private IReference addressableName;
[SerializeReference, SubclassSelector] private IReference packageName = new Reference("DefaultPackage");
[SerializeReference, SubclassSelector] private IRemoteServices remoteServices;
[SerializeReference, SubclassSelector] private IBuildinQueryServices buildinQueryServices;
[SerializeField] private Optional<string> loadEntryScene;
[SerializeField] private UIDocument document;
[SerializeField] private bool isOffline;
[SerializeField] private bool IsEditorSimulateMode;
[SerializeField] private UnityEvent<Action<float>,Action<string>> afterInitialize=new();
[SerializeField] private UnityEvent<string> onGetCurrentVersion;
[UXBindPath("progress-bar",true)]
private ProgressBar _progressBar;
[UXBindPath("progress-fill",true)]
private VisualElement _progressFill;
[UXBindPath("progress-label")]
private Label _progressLabel;
private Action<float> _setProgressValue;
private Action<string> _setProgressLabel;
private async void Start()
{
try
{
#if UNITY_EDITOR
#else
IsEditorSimulateMode = false;
#endif
UXUtils.Inject(this);
if (_progressBar is not null)
{
_setProgressValue = value => _progressBar.value = value;
}else if (_progressFill is not null)
{
_setProgressValue = value =>
_progressFill.style.width = new Length() { value = value*100, unit = LengthUnit.Percent };
}
_setProgressLabel = value => _progressLabel.text = value;
_setProgressValue?.Invoke(0f);
_setProgressLabel?.Invoke("正在初始化资源系统...");
var stopwatch = new Stopwatch();
stopwatch.Start();
DontDestroyOnLoad(gameObject);
// 初始化资源系统
if (YooAssets.Initialized is false)
YooAssets.Initialize();
// 创建默认的资源包
var package = YooAssets.TryGetPackage(packageName.Value) ?? YooAssets.CreatePackage(packageName.Value);
// 设置该资源包为默认的资源包可以使用YooAssets相关加载接口加载该资源包内容。
YooAssets.SetDefaultPackage(package);
if (package.InitializeStatus is EOperationStatus.Succeed)
{
YooAssets.DestroyPackage(package.PackageName);
}
InitializeParameters initParameters = new HostPlayModeParameters
{
BuildinQueryServices = buildinQueryServices,
RemoteServices = remoteServices
};
if (Application.platform is RuntimePlatform.WebGLPlayer)
{
initParameters = new WebPlayModeParameters()
{
BuildinQueryServices = buildinQueryServices,
RemoteServices = remoteServices
};
}
#if UNITY_EDITOR
if (IsEditorSimulateMode)
{
var editorParameters = new EditorSimulateModeParameters
{
SimulateManifestFilePath =
EditorSimulateModeHelper.SimulateBuild("ScriptableBuildPipeline", packageName.Value)
};
initParameters = editorParameters;
}
else
{
switch (UnityEditor.EditorUserBuildSettings.activeBuildTarget)
{
case UnityEditor.BuildTarget.WebGL:
initParameters = new WebPlayModeParameters()
{
BuildinQueryServices = buildinQueryServices,
RemoteServices = remoteServices
};
break;
}
}
#endif
if (isOffline)
{
initParameters = new OfflinePlayModeParameters();
}
InitializationOperation initOperation = null;
try
{
initOperation = package.InitializeAsync(initParameters);
_progressLabel.text ="正在初始化资源系统...";
}
catch (Exception e)
{
_progressLabel.text =e.Message;
initParameters = new HostPlayModeParameters
{
BuildinQueryServices = buildinQueryServices,
RemoteServices = remoteServices
};
initOperation = package.InitializeAsync(initParameters);
}
while (initOperation.IsDone is false)
{
await UniTask.NextFrame(destroyCancellationToken);
//_progressBar.value =initOperation.Progress;
_setProgressValue?.Invoke(initOperation.Progress);
}
try
{
if (isOffline is false)
{
_progressLabel.text = "正在更新资源包版本...";
var operation = package.UpdatePackageVersionAsync();
try
{
onGetCurrentVersion.Invoke(package.GetPackageVersion());
}
catch (Exception e)
{
BIT4Log.LogException(e);
}
while (operation.IsDone is false)
{
await UniTask.NextFrame(destroyCancellationToken);
//_progressBar.value = operation.Progress;
_setProgressValue?.Invoke(operation.Progress);
}
if (operation.Status == EOperationStatus.Succeed)
{
//更新成功
string packageVersion = operation.PackageVersion;
Debug.Log($"Updated package Version : {packageVersion}");
_progressLabel.text = "正在更新资源包清单...";
var manifestOperation = package.UpdatePackageManifestAsync(packageVersion);
await manifestOperation.ToUniTask();
if (manifestOperation.Status == EOperationStatus.Succeed)
{
//更新成功
int downloadingMaxNum = 10;
int failedTryAgain = 3;
var downloader = package.CreateResourceDownloader(downloadingMaxNum, failedTryAgain);
//没有需要下载的资源
if (downloader.TotalDownloadCount != 0)
{
//需要下载的文件总数和总大小
int totalDownloadCount = downloader.TotalDownloadCount;
long totalDownloadBytes = downloader.TotalDownloadBytes;
downloader.OnDownloadProgressCallback = (totalDownloadCount, currentDownloadCount,
totalDownloadBytes, currentDownloadBytes) =>
{
BIT4Log.Log<BITFramework>(
$"{totalDownloadCount},{currentDownloadCount},{totalDownloadBytes},{currentDownloadBytes}");
//下载进度
float progress = (float)currentDownloadBytes / totalDownloadBytes;
_setProgressValue?.Invoke(progress);
_setProgressLabel?.Invoke($"{currentDownloadBytes}/{totalDownloadBytes}");
};
downloader.OnDownloadErrorCallback = (fileName, error) =>
{
_setProgressLabel?.Invoke(error);
};
//注册回调方法
// downloader.OnDownloadErrorCallback = OnDownloadErrorFunction;
// downloader.OnDownloadProgressCallback = OnDownloadProgressUpdateFunction;
// downloader.OnDownloadOverCallback = OnDownloadOverFunction;
// downloader.OnStartDownloadFileCallback = OnStartDownloadFileFunction;
//开启下载
downloader.BeginDownload();
await downloader;
//检测下载结果
if (downloader.Status != EOperationStatus.Succeed)
{
//更新失败
Debug.LogError(operation.Error);
_progressLabel.text = operation.Error;
}
}
}
else
{
//更新失败
Debug.LogError(operation.Error);
_progressLabel.text = operation.Error;
}
}
else
{
//更新失败
Debug.LogError(operation.Error);
_progressLabel.text = operation.Error;
}
}
}
catch (Exception e)
{
BIT4Log.LogException(e);
_progressLabel.text = e.Message;
}
_setProgressLabel?.Invoke("资源系统初始化完成,后处理中...");
afterInitialize.Invoke(_setProgressValue,_setProgressLabel);
_setProgressLabel?.Invoke("资源系统初始化完成,后处理完成");
if (addressableName is not null)
{
_progressLabel.text ="正在初始化Framework";
var frameworkHandle = YooAssets.LoadAssetAsync<GameObject>(addressableName.Value);
while (frameworkHandle.IsDone is false)
{
await UniTask.NextFrame(destroyCancellationToken);
//_progressBar.value=frameworkHandle.Progress;
_setProgressValue?.Invoke(frameworkHandle.Progress);
}
var framework = Instantiate(frameworkHandle.AssetObject);
DontDestroyOnLoad(framework);
_progressLabel.text="已加载完成";
BIT4Log.Log<BITFramework>("BITFramework加载完成,耗时:" + stopwatch.ElapsedMilliseconds + "ms");
}
stopwatch.Stop();
YooAssetUtils.RegisterPackage(packageName.Value);
YooAssetUtils.RegisterResourcePackage(package);
if (loadEntryScene.Allow)
{
_progressLabel.text="正在加载场景...";
try
{
await package.LoadSceneAsync(loadEntryScene.Value);
_progressLabel.text="场景加载完成...";
}
catch (Exception e)
{
Debug.LogException(e);
await UniTask.NextFrame();
_progressLabel.text = e.Message;
}
}
else
{
_progressLabel.text="未找到默认场景,正在加载场景[1]";
SceneManager.LoadScene(1);
}
if (document)
Destroy(document);
}
catch (Exception e)
{
await UniTask.SwitchToMainThread();
_progressBar.value =0;
_progressLabel.text = e.Message;
}
}
private void OnDestroy()
{
#if UNITY_EDITOR
YooAssets.Destroy();
#endif
}
}
[Serializable]
public sealed class GameQueryServices : IBuildinQueryServices
{
public bool Query(string packageName, string fileName)
{
// 注意fileName包含文件格式
return StreamingAssetsHelper.FileExists(packageName, fileName);
}
public bool Query(string packageName, string fileName, string fileCRC)=>Query(packageName,fileName);
}
[Serializable]
public sealed class LocalQueryServices : IBuildinQueryServices
{
public readonly string Path;
public LocalQueryServices(string path)
{
Path = path;
}
public bool Query(string packageName, string fileName, string fileCRC)
{
return File.Exists(System.IO.Path.Combine(Path, fileName));
}
}
/// <summary>
/// 远端资源地址查询服务类
/// </summary>
[Serializable]
public sealed class RemoteServices : IRemoteServices
{
[SerializeField] private string _defaultHostServer;
[SerializeField] private string _fallbackHostServer;
public RemoteServices(){}
public RemoteServices(string defaultHostServer, string fallbackHostServer)
{
_defaultHostServer = defaultHostServer;
_fallbackHostServer = fallbackHostServer;
}
string IRemoteServices.GetRemoteMainURL(string fileName)
{
return $"{_defaultHostServer}/{fileName}";
}
string IRemoteServices.GetRemoteFallbackURL(string fileName)
{
return $"{_fallbackHostServer}/{fileName}";
}
}
}