363 lines
14 KiB
C#
363 lines
14 KiB
C#
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("DefaultPackages");
|
||
|
||
[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);
|
||
// 初始化资源系统
|
||
YooAssets.Initialize();
|
||
|
||
// 创建默认的资源包
|
||
var package = YooAssets.TryGetPackage(packageName.Value) ?? YooAssets.CreatePackage(packageName.Value);
|
||
|
||
// 设置该资源包为默认的资源包,可以使用YooAssets相关加载接口加载该资源包内容。
|
||
YooAssets.SetDefaultPackage(package);
|
||
|
||
|
||
InitializeParameters initParameters = new HostPlayModeParameters
|
||
{
|
||
BuildinQueryServices = buildinQueryServices,
|
||
RemoteServices = remoteServices
|
||
};
|
||
#if UNITY_EDITOR
|
||
if (IsEditorSimulateMode)
|
||
{
|
||
|
||
var editorParameters = new EditorSimulateModeParameters
|
||
{
|
||
|
||
SimulateManifestFilePath =
|
||
EditorSimulateModeHelper.SimulateBuild("ScriptableBuildPipeline", packageName.Value)
|
||
};
|
||
initParameters = editorParameters;
|
||
}else
|
||
#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
|
||
{
|
||
_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="正在加载场景...";
|
||
await package.LoadSceneAsync(loadEntryScene.Value);
|
||
if (document)
|
||
Destroy(document);
|
||
}
|
||
else
|
||
{
|
||
if (document)
|
||
Destroy(document);
|
||
SceneManager.LoadScene(1);
|
||
}
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
await UniTask.SwitchToMainThread();
|
||
_progressBar.value =0;
|
||
_progressLabel.text = e.Message;
|
||
}
|
||
}
|
||
|
||
private void OnDestroy()
|
||
{
|
||
YooAssets.Destroy();
|
||
}
|
||
}
|
||
|
||
[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}";
|
||
}
|
||
}
|
||
}
|
||
|
||
|