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

411 lines
16 KiB
C#
Raw Normal View History

2023-11-15 23:55:06 +08:00
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
2024-03-31 23:31:00 +08:00
using BITKit.IO;
2023-11-15 23:55:06 +08:00
using BITKit.UX;
using Cysharp.Threading.Tasks;
using UnityEngine;
2024-07-21 14:19:40 +08:00
using UnityEngine.Events;
2023-11-15 23:55:06 +08:00
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.UIElements;
using YooAsset;
using Debug = UnityEngine.Debug;
namespace BITKit
{
public class BITFramework : MonoBehaviour
{
2024-12-25 11:35:30 +08:00
public static BITFramework Singleton { get; private set; }
2023-11-15 23:55:06 +08:00
private static System.Diagnostics.Stopwatch Stopwatch;
[RuntimeInitializeOnLoadMethod]
private static void Reload()
{
Stopwatch = new Stopwatch();
#if UNITY_EDITOR
#else
SplashScreen.Stop(SplashScreen.StopBehavior.StopImmediate);
#endif
}
2024-03-31 23:31:00 +08:00
[SerializeReference, SubclassSelector] private IReference addressableName;
2024-08-13 18:42:51 +08:00
[SerializeReference, SubclassSelector] private IReference packageName = new Reference("DefaultPackage");
2024-03-31 23:31:00 +08:00
[SerializeReference, SubclassSelector] private IRemoteServices remoteServices;
[SerializeReference, SubclassSelector] private IBuildinQueryServices buildinQueryServices;
2024-07-29 09:39:22 +08:00
2024-03-31 23:31:00 +08:00
2024-05-31 01:23:15 +08:00
[SerializeField] private Optional<string> loadEntryScene;
2023-11-15 23:55:06 +08:00
[SerializeField] private UIDocument document;
2024-03-31 23:31:00 +08:00
[SerializeField] private bool isOffline;
2023-11-15 23:55:06 +08:00
[SerializeField] private bool IsEditorSimulateMode;
2024-07-21 14:19:40 +08:00
2024-07-29 09:39:22 +08:00
[SerializeField] private UnityEvent<Action<float>,Action<string>> afterInitialize=new();
[SerializeField] private UnityEvent<string> onGetCurrentVersion;
2023-11-15 23:55:06 +08:00
2024-07-15 17:26:08 +08:00
[UXBindPath("progress-bar",true)]
2024-03-31 23:31:00 +08:00
private ProgressBar _progressBar;
2024-07-15 17:26:08 +08:00
[UXBindPath("progress-fill",true)]
private VisualElement _progressFill;
2024-03-31 23:31:00 +08:00
[UXBindPath("progress-label")]
private Label _progressLabel;
2024-07-15 17:26:08 +08:00
private Action<float> _setProgressValue;
2024-07-21 14:19:40 +08:00
private Action<string> _setProgressLabel;
2023-11-15 23:55:06 +08:00
private async void Start()
{
2024-12-25 11:35:30 +08:00
Singleton = this;
2024-03-31 23:31:00 +08:00
try
2023-11-15 23:55:06 +08:00
{
2024-03-31 23:31:00 +08:00
#if UNITY_EDITOR
#else
IsEditorSimulateMode = false;
#endif
UXUtils.Inject(this);
2024-07-15 17:26:08 +08:00
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 };
}
2024-07-21 14:19:40 +08:00
_setProgressLabel = value => _progressLabel.text = value;
2024-07-15 17:26:08 +08:00
_setProgressValue?.Invoke(0f);
2024-07-21 14:19:40 +08:00
_setProgressLabel?.Invoke("正在初始化资源系统...");
2024-03-31 23:31:00 +08:00
var stopwatch = new Stopwatch();
stopwatch.Start();
DontDestroyOnLoad(gameObject);
// 初始化资源系统
2024-12-13 16:14:20 +08:00
if (YooAssets.Initialized is false)
YooAssets.Initialize();
2024-03-31 23:31:00 +08:00
// 创建默认的资源包
var package = YooAssets.TryGetPackage(packageName.Value) ?? YooAssets.CreatePackage(packageName.Value);
// 设置该资源包为默认的资源包可以使用YooAssets相关加载接口加载该资源包内容。
YooAssets.SetDefaultPackage(package);
2024-12-13 16:14:20 +08:00
if (package.InitializeStatus is EOperationStatus.Succeed)
{
YooAssets.DestroyPackage(package.PackageName);
}
2024-03-31 23:31:00 +08:00
InitializeParameters initParameters = new HostPlayModeParameters
2023-11-15 23:55:06 +08:00
{
2024-03-31 23:31:00 +08:00
BuildinQueryServices = buildinQueryServices,
RemoteServices = remoteServices
2023-11-15 23:55:06 +08:00
};
2024-12-13 16:14:20 +08:00
if (Application.platform is RuntimePlatform.WebGLPlayer)
{
initParameters = new WebPlayModeParameters()
{
BuildinQueryServices = buildinQueryServices,
RemoteServices = remoteServices
};
}
2024-06-14 14:11:28 +08:00
#if UNITY_EDITOR
2024-03-31 23:31:00 +08:00
if (IsEditorSimulateMode)
{
var editorParameters = new EditorSimulateModeParameters
{
SimulateManifestFilePath =
EditorSimulateModeHelper.SimulateBuild("ScriptableBuildPipeline", packageName.Value)
};
initParameters = editorParameters;
2024-12-13 16:14:20 +08:00
}
else
{
switch (UnityEditor.EditorUserBuildSettings.activeBuildTarget)
{
case UnityEditor.BuildTarget.WebGL:
initParameters = new WebPlayModeParameters()
{
BuildinQueryServices = buildinQueryServices,
RemoteServices = remoteServices
};
break;
}
}
#endif
2024-12-26 18:00:56 +08:00
2024-12-26 18:00:05 +08:00
if (isOffline&& IsEditorSimulateMode is false)
2024-12-25 11:35:30 +08:00
{
initParameters = new OfflinePlayModeParameters();
}
2023-11-15 23:55:06 +08:00
2024-03-31 23:31:00 +08:00
InitializationOperation initOperation = null;
try
{
initOperation = package.InitializeAsync(initParameters);
2024-12-26 18:00:05 +08:00
var text = $"正在初始化资源系统...,使用{initParameters.GetType().Name}";
_progressLabel.text =text;
Debug.Log(text);
2024-03-31 23:31:00 +08:00
}
catch (Exception e)
{
_progressLabel.text =e.Message;
2023-11-15 23:55:06 +08:00
2024-03-31 23:31:00 +08:00
initParameters = new HostPlayModeParameters
{
BuildinQueryServices = buildinQueryServices,
RemoteServices = remoteServices
};
2023-11-15 23:55:06 +08:00
2024-03-31 23:31:00 +08:00
initOperation = package.InitializeAsync(initParameters);
}
while (initOperation.IsDone is false)
{
await UniTask.NextFrame(destroyCancellationToken);
2024-07-15 17:26:08 +08:00
//_progressBar.value =initOperation.Progress;
_setProgressValue?.Invoke(initOperation.Progress);
2024-03-31 23:31:00 +08:00
}
2023-11-15 23:55:06 +08:00
2024-03-31 23:31:00 +08:00
try
{
2024-11-03 16:38:17 +08:00
if (isOffline is false)
2024-07-29 09:39:22 +08:00
{
2024-11-03 16:38:17 +08:00
_progressLabel.text = "正在更新资源包版本...";
var operation = package.UpdatePackageVersionAsync();
try
{
onGetCurrentVersion.Invoke(package.GetPackageVersion());
}
catch (Exception e)
{
BIT4Log.LogException(e);
}
2024-03-31 23:31:00 +08:00
2024-11-03 16:38:17 +08:00
while (operation.IsDone is false)
{
await UniTask.NextFrame(destroyCancellationToken);
//_progressBar.value = operation.Progress;
_setProgressValue?.Invoke(operation.Progress);
}
2024-03-31 23:31:00 +08:00
2024-11-03 16:38:17 +08:00
if (operation.Status == EOperationStatus.Succeed)
2024-07-26 15:45:10 +08:00
{
//更新成功
2024-11-03 16:38:17 +08:00
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)
2024-07-26 15:45:10 +08:00
{
2024-11-03 16:38:17 +08:00
//需要下载的文件总数和总大小
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;
}
2024-07-26 15:45:10 +08:00
}
}
2024-11-03 16:38:17 +08:00
else
{
//更新失败
Debug.LogError(operation.Error);
_progressLabel.text = operation.Error;
}
2024-07-26 15:45:10 +08:00
}
else
{
//更新失败
Debug.LogError(operation.Error);
2024-11-03 16:38:17 +08:00
_progressLabel.text = operation.Error;
2024-07-26 15:45:10 +08:00
}
2024-03-31 23:31:00 +08:00
}
}
catch (Exception e)
{
2024-11-03 16:38:17 +08:00
BIT4Log.LogException(e);
_progressLabel.text = e.Message;
2024-03-31 23:31:00 +08:00
}
2024-11-03 16:38:17 +08:00
2024-07-21 14:19:40 +08:00
_setProgressLabel?.Invoke("资源系统初始化完成,后处理中...");
afterInitialize.Invoke(_setProgressValue,_setProgressLabel);
2024-03-31 23:31:00 +08:00
2024-07-21 14:19:40 +08:00
_setProgressLabel?.Invoke("资源系统初始化完成,后处理完成");
2024-07-26 15:45:10 +08:00
2024-03-31 23:31:00 +08:00
if (addressableName is not null)
{
_progressLabel.text ="正在初始化Framework";
var frameworkHandle = YooAssets.LoadAssetAsync<GameObject>(addressableName.Value);
while (frameworkHandle.IsDone is false)
{
await UniTask.NextFrame(destroyCancellationToken);
2024-07-15 17:26:08 +08:00
//_progressBar.value=frameworkHandle.Progress;
_setProgressValue?.Invoke(frameworkHandle.Progress);
2024-03-31 23:31:00 +08:00
}
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);
2024-12-25 11:35:30 +08:00
await AfterInit(package);
2024-03-31 23:31:00 +08:00
}
catch (Exception e)
{
2024-05-31 01:23:15 +08:00
await UniTask.SwitchToMainThread();
2024-03-31 23:31:00 +08:00
_progressBar.value =0;
_progressLabel.text = e.Message;
}
2023-11-15 23:55:06 +08:00
}
2024-12-25 11:35:30 +08:00
private async UniTask AfterInit(ResourcePackage 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);
}
2023-11-15 23:55:06 +08:00
private void OnDestroy()
{
2024-12-13 16:14:20 +08:00
#if UNITY_EDITOR
YooAssets.Destroy();
#endif
2023-11-15 23:55:06 +08:00
}
}
2024-03-31 23:31:00 +08:00
[Serializable]
public sealed class GameQueryServices : IBuildinQueryServices
2023-11-15 23:55:06 +08:00
{
public bool Query(string packageName, string fileName)
{
// 注意fileName包含文件格式
return StreamingAssetsHelper.FileExists(packageName, fileName);
}
2024-03-31 23:31:00 +08:00
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));
}
2023-11-15 23:55:06 +08:00
}
/// <summary>
/// 远端资源地址查询服务类
/// </summary>
2024-03-31 23:31:00 +08:00
[Serializable]
public sealed class RemoteServices : IRemoteServices
2023-11-15 23:55:06 +08:00
{
2024-03-31 23:31:00 +08:00
[SerializeField] private string _defaultHostServer;
[SerializeField] private string _fallbackHostServer;
public RemoteServices(){}
2023-11-15 23:55:06 +08:00
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}";
}
}
}