using System;
using System.Collections;
using System.IO;
using Cysharp.Threading.Tasks;
using UnityEngine;
using YooAsset;
using ZFramework.Runtime;
using ZGame;
namespace HK
{
public class InitializePackage
{
///
/// 资源系统运行模式
///
private EPlayMode PlayMode = EPlayMode.EditorSimulateMode;
private string PackageName = "DefaultPackage";
public InitializePackage(EPlayMode playMode, string packageName, string hostServerIP, string appVersion)
{
PlayMode = playMode;
PackageName = packageName;
this.hostServerIP = hostServerIP;
this.appVersion = appVersion;
}
public async UniTask Start()
{
Debug.Log($"资源系统运行模式:{PlayMode}");
Application.targetFrameRate = 60;
Application.runInBackground = true;
// 游戏管理器
// GameManager.Instance.Behaviour = this;
//
// // 初始化事件系统
// UniEvent.Initalize();
// 初始化资源系统
YooAssets.Initialize();
// 加载更新页面
var go = Resources.Load("PatchWindow");
GameObject.Instantiate(go);
#if ENABLE_WEBGL || PLATFORM_WEBGL
YooAssets.SetCacheSystemDisableCacheOnWebGL();
#endif
EventManager.Instance.Subscribe(UpdatePackageCallbackEventArgs.EventId, UpdatePackageCallbackEvent);
// 开始补丁更新流程
// var operation = new PatchOperation("DefaultPackage", PlayMode);
// YooAssets.StartOperation(operation);
await InitPackage();
// 设置默认的资源包
var gamePackage = YooAssets.GetPackage("DefaultPackage");
YooAssets.SetDefaultPackage(gamePackage);
// 切换到主页面场景
// SceneEventDefine.ChangeToHomeScene.SendEventMessage();
// YooAssets.LoadSceneSync(SceneName);
Debug.Log("完成");
}
private void UpdatePackageCallbackEvent(object sender, GameEventArgs e)
{
var args = e as UpdatePackageCallbackEventArgs;
switch (args.callbackType)
{
case UpdatePackageCallbackType.再次初始化资源包:
this.InitPackage().Forget();
break;
case UpdatePackageCallbackType.开始下载网络文件:
this.FsmDownloadPackageFiles().Forget();
break;
case UpdatePackageCallbackType.再次更新静态版本:
this.UpdatePackageVersion().Forget();
break;
case UpdatePackageCallbackType.再次更新补丁清单:
this.FsmUpdatePackageManifest().Forget();
break;
case UpdatePackageCallbackType.再次下载网络文件:
this.FsmDownloadPackageFiles().Forget();
break;
default:
throw new ArgumentOutOfRangeException();
}
}
#region FsmInitializePackage
private async UniTask InitPackage()
{
// 创建资源包裹类
var package = YooAssets.TryGetPackage(PackageName);
if (package == null)
package = YooAssets.CreatePackage(PackageName);
// 编辑器下的模拟模式
InitializationOperation initializationOperation = null;
if (PlayMode == EPlayMode.EditorSimulateMode)
{
var buildResult = EditorSimulateModeHelper.SimulateBuild(PackageName);
var packageRoot = buildResult.PackageRootDirectory;
var createParameters = new EditorSimulateModeParameters();
createParameters.EditorFileSystemParameters =
FileSystemParameters.CreateDefaultEditorFileSystemParameters(packageRoot);
initializationOperation = package.InitializeAsync(createParameters);
}
// 单机运行模式
if (PlayMode == EPlayMode.OfflinePlayMode)
{
var createParameters = new OfflinePlayModeParameters();
createParameters.BuildinFileSystemParameters =
FileSystemParameters.CreateDefaultBuildinFileSystemParameters();
initializationOperation = package.InitializeAsync(createParameters);
}
// 联机运行模式
if (PlayMode == EPlayMode.HostPlayMode)
{
string defaultHostServer = GetHostServerURL();
string fallbackHostServer = GetHostServerURL();
IRemoteServices remoteServices = new RemoteServices(defaultHostServer, fallbackHostServer);
var createParameters = new HostPlayModeParameters();
createParameters.BuildinFileSystemParameters =
FileSystemParameters.CreateDefaultBuildinFileSystemParameters();
createParameters.CacheFileSystemParameters =
FileSystemParameters.CreateDefaultCacheFileSystemParameters(remoteServices);
initializationOperation = package.InitializeAsync(createParameters);
}
// WebGL运行模式
if (PlayMode == EPlayMode.WebPlayMode)
{
#if UNITY_WEBGL && WEIXINMINIGAME && !UNITY_EDITOR
var createParameters = new WebPlayModeParameters();
string defaultHostServer = GetHostServerURL();
string fallbackHostServer = GetHostServerURL();
string packageRoot = $"{WeChatWASM.WX.env.USER_DATA_PATH}/__GAME_FILE_CACHE"; //注意:如果有子目录,请修改此处!
IRemoteServices remoteServices = new RemoteServices(defaultHostServer, fallbackHostServer);
createParameters.WebServerFileSystemParameters =
WechatFileSystemCreater.CreateFileSystemParameters(packageRoot, remoteServices);
initializationOperation = package.InitializeAsync(createParameters);
#else
var createParameters = new WebPlayModeParameters();
createParameters.WebServerFileSystemParameters =
FileSystemParameters.CreateDefaultWebServerFileSystemParameters();
initializationOperation = package.InitializeAsync(createParameters);
#endif
}
await initializationOperation.Task;
// 如果初始化失败弹出提示界面
if (initializationOperation.Status != EOperationStatus.Succeed)
{
Debug.LogWarning($"{initializationOperation.Error}");
// PatchEventDefine.InitializeFailed.SendEventMessage();
EventManager.Instance.FireNow(this, new InitializeFailedEventArgs());
}
else
{
// _machine.ChangeState();
await UpdatePackageVersion();
}
}
string hostServerIP = "http://127.0.0.1";
string appVersion = "v1.0";
///
/// 获取资源服务器地址
///
private string GetHostServerURL()
{
//string hostServerIP = "http://10.0.2.2"; //安卓模拟器地址
// string hostServerIP = "http://127.0.0.1";
// string appVersion = "v1.0";
#if UNITY_EDITOR
if (UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.Android)
return $"{hostServerIP}/CDN/Android/{Application.productName}/{appVersion}";
else if (UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.iOS)
return $"{hostServerIP}/CDN/IPhone/{Application.productName}/{appVersion}";
else if (UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.WebGL)
return $"{hostServerIP}/CDN/WebGL/{Application.productName}/{appVersion}";
else
return $"{hostServerIP}/CDN/PC/{Application.productName}/{appVersion}";
#else
if (Application.platform == RuntimePlatform.Android)
return $"{hostServerIP}/CDN/Android/{Application.productName}/{appVersion}";
else if (Application.platform == RuntimePlatform.IPhonePlayer)
return $"{hostServerIP}/CDN/IPhone/{Application.productName}/{appVersion}";
else if (Application.platform == RuntimePlatform.WebGLPlayer)
return $"{hostServerIP}/CDN/WebGL/{Application.productName}/{appVersion}";
else
return $"{hostServerIP}/CDN/PC/{Application.productName}/{appVersion}";
#endif
}
///
/// 远端资源地址查询服务类
///
private class RemoteServices : IRemoteServices
{
private readonly string _defaultHostServer;
private readonly string _fallbackHostServer;
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}";
}
}
#endregion
#region FsmRequestPackageVersion
private async UniTask UpdatePackageVersion()
{
var package = YooAssets.GetPackage(PackageName);
var operation = package.RequestPackageVersionAsync();
await operation.Task;
if (operation.Status != EOperationStatus.Succeed)
{
Debug.LogWarning(operation.Error);
EventManager.Instance.FireNow(this, new PackageVersionUpdateFailedEventArgs());
}
else
{
Debug.Log($"Request package version : {operation.PackageVersion}");
packageVersion = operation.PackageVersion;
await FsmUpdatePackageManifest();
}
}
string packageVersion;
#endregion
#region FsmUpdatePackageManifest
private async UniTask FsmUpdatePackageManifest()
{
var package = YooAssets.GetPackage(PackageName);
var operation = package.UpdatePackageManifestAsync(packageVersion);
await operation.Task;
if (operation.Status != EOperationStatus.Succeed)
{
Debug.LogWarning(operation.Error);
EventManager.Instance.FireNow(this, new PatchManifestUpdateFailedEventArgs());
return;
}
else
{
await FsmCreateDownloader();
}
}
#endregion
#region FsmCreateDownloader
private async UniTask FsmCreateDownloader()
{
await UniTask.Yield();
Log.Debug("创建资源下载器!");
CreateDownloader();
}
ResourceDownloaderOperation downloader;
void CreateDownloader()
{
var package = YooAssets.GetPackage(PackageName);
int downloadingMaxNum = 10;
int failedTryAgain = 3;
downloader = package.CreateResourceDownloader(downloadingMaxNum, failedTryAgain);
// _machine.SetBlackboardValue("Downloader", downloader);
if (downloader.TotalDownloadCount == 0)
{
Debug.Log("Not found any download files !");
// _machine.ChangeState();
UniTask.Run(FsmStartGame);
}
else
{
// 发现新更新文件后,挂起流程系统
// 注意:开发者需要在下载前检测磁盘空间不足
int totalDownloadCount = downloader.TotalDownloadCount;
long totalDownloadBytes = downloader.TotalDownloadBytes;
EventManager.Instance.FireNow(this,
new FoundUpdateFilesEventArgs(totalDownloadCount, totalDownloadBytes));
}
}
#endregion
#region FsmDownloadPackageFiles
private async UniTask FsmDownloadPackageFiles()
{
await UniTask.Yield();
Log.Debug("开始下载资源文件!");
downloader.DownloadErrorCallback = DownloadErrorCallback;
downloader.DownloadUpdateCallback = DownloadProgressCallback;
downloader.BeginDownload();
await downloader.Task;
// 检测下载结果
if (downloader.Status != EOperationStatus.Succeed)
return;
await FsmDownloadPackageOver();
void DownloadErrorCallback(DownloadErrorData data)
{
Debug.Log($"下载补丁出错!{data.ErrorInfo}");
EventManager.Instance.FireNow(this, new WebFileDownloadFailedEventArgs(data.FileName, data.ErrorInfo));
}
void DownloadProgressCallback(DownloadUpdateData data)
{
Debug.Log(
$"下载进度:{data.CurrentDownloadCount}/{data.TotalDownloadCount} , {data.CurrentDownloadBytes}/{data.TotalDownloadBytes}!");
EventManager.Instance.FireNow(this, new DownloadProgressUpdateEventArgs(data.CurrentDownloadCount,
data.TotalDownloadCount, data.CurrentDownloadBytes, data.TotalDownloadBytes));
}
}
#endregion
#region FsmDownloadPackageOver
private async UniTask FsmDownloadPackageOver()
{
await UniTask.Yield();
Log.Debug("资源文件下载完毕!");
await FsmClearCacheBundle();
}
#endregion
#region FsmClearCacheBundle
private async UniTask FsmClearCacheBundle()
{
await UniTask.Yield();
Log.Debug("清理未使用的缓存文件!");
var package = YooAssets.GetPackage(PackageName);
var operation = package.ClearCacheFilesAsync(EFileClearMode.ClearUnusedBundleFiles);
operation.Completed += Operation_Completed;
}
private void Operation_Completed(YooAsset.AsyncOperationBase obj)
{
UniTask.Run(FsmStartGame);
}
#endregion
#region FsmStartGame
private async UniTask FsmStartGame()
{
await UniTask.Yield();
Log.Debug("开始游戏!");
}
#endregion
}
}