备份CatanBuilding瘦身独立工程
This commit is contained in:
473
Assets/Scripts/Services/LoadResourceService.cs
Normal file
473
Assets/Scripts/Services/LoadResourceService.cs
Normal file
@@ -0,0 +1,473 @@
|
||||
using asap.core;
|
||||
using GameCore;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
using UnityEngine.ResourceManagement.AsyncOperations;
|
||||
public interface ILoadResourceService
|
||||
{
|
||||
Task<bool> Load(string label);
|
||||
Task<bool> Loads(List<string> label);
|
||||
//后台排队静默下载
|
||||
void Load(List<string> label);
|
||||
/// <summary>
|
||||
/// 登陆游戏预下载地图资源
|
||||
/// </summary>
|
||||
/// <param name="assetName"></param>
|
||||
/// <param name="progress"></param>
|
||||
/// <returns></returns>
|
||||
Task<bool> Loading(List<string> assetName, System.Action<float> progress);
|
||||
//检查是否需要下载资源,不下载
|
||||
Task<bool> CheckResource(string label);
|
||||
Task<bool> CheckResourceLoadQueue(string key, List<string> label);
|
||||
Task<bool> CheckResourceLoadQueue(List<string> label);
|
||||
string curName { get; }
|
||||
string oldName { get; }
|
||||
}
|
||||
public class LoadResourceData
|
||||
{
|
||||
public string name;
|
||||
public AsyncOperationHandle downloadOp;
|
||||
}
|
||||
public struct LoadEventResourceEvent
|
||||
{
|
||||
public string key;
|
||||
public List<string> label;
|
||||
public bool isSucceeded;
|
||||
}
|
||||
public class LoadProgressEvent
|
||||
{
|
||||
public string name;
|
||||
public float progress;
|
||||
public float totalDownloadSize;
|
||||
public bool isSucceeded;
|
||||
public bool isFailed;
|
||||
}
|
||||
public class LoadResourceService : ILoadResourceService
|
||||
{
|
||||
[Inject]
|
||||
public IConfig config { get; set; }
|
||||
Dictionary<string, AsyncOperationHandle> loadResourceDatas = new Dictionary<string, AsyncOperationHandle>();
|
||||
LinkedList<string> loadQueue = new LinkedList<string>();
|
||||
LinkedList<LoadEventResourceEvent> loadEventQueue = new LinkedList<LoadEventResourceEvent>();
|
||||
bool LoadEventResourceing = false;
|
||||
Dictionary<string, bool> loadRecord = new Dictionary<string, bool>();
|
||||
//检查资源是否需要更新
|
||||
public string curName { get; private set; }
|
||||
public string oldName { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 登陆游戏预下载地图资源
|
||||
/// </summary>
|
||||
/// <param name="assetName"></param>
|
||||
/// <param name="progress"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> Loading(List<string> assetName, System.Action<float> progress)
|
||||
{
|
||||
if (!loadResourceDatas.ContainsKey(assetName[0]))
|
||||
{
|
||||
var locationsOp = Addressables.LoadResourceLocationsAsync(assetName, Addressables.MergeMode.Union);
|
||||
var locations = await locationsOp.Task;
|
||||
var totalDownloadSize = await Addressables.GetDownloadSizeAsync(locations).Task;
|
||||
|
||||
if (totalDownloadSize > 1024)
|
||||
{
|
||||
AsyncOperationHandle download = Addressables.DownloadDependenciesAsync(locations.Select(_ => _.PrimaryKey), Addressables.MergeMode.Union);
|
||||
loadResourceDatas[assetName[0]] = download;
|
||||
}
|
||||
Addressables.Release(locationsOp);
|
||||
}
|
||||
bool result = true;
|
||||
if (loadResourceDatas.ContainsKey(assetName[0]))
|
||||
{
|
||||
#if AGG
|
||||
using (var e = GEvent.GameEvent("Preload_start"))
|
||||
{
|
||||
e.AddContent("expected_assets", string.Join(',', assetName));
|
||||
}
|
||||
#endif
|
||||
float percent = 0;
|
||||
LoadingScreen.SetLoadingInfo(LocalizationMgr.GetText("UI_ToastPanel_26"));
|
||||
|
||||
AsyncOperationHandle downloadOp = loadResourceDatas[assetName[0]];
|
||||
DateTime startTime = DateTime.Now;
|
||||
LoadingScreen.SetSubProgress(0, "");
|
||||
LoadingScreen.ShowSubProgressBar();
|
||||
while (!downloadOp.IsDone && downloadOp.Status != AsyncOperationStatus.Failed)
|
||||
{
|
||||
var downloadStatus = downloadOp.GetDownloadStatus();
|
||||
if (downloadStatus.Percent > percent)
|
||||
percent = downloadStatus.Percent;
|
||||
progress?.Invoke(percent);
|
||||
LoadingScreen.SetSubProgress(percent, GetSizeByBytes(downloadStatus.TotalBytes, percent));
|
||||
await Awaiters.NextFrame;
|
||||
}
|
||||
LoadingScreen.HideSubProgressBar();
|
||||
loadResourceDatas.Remove(assetName[0]);
|
||||
if (downloadOp.Status == AsyncOperationStatus.Failed
|
||||
|| downloadOp.OperationException != null)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
DateTime endTime = DateTime.Now;
|
||||
Debug.Log($"Preload finished, result:{result}, time cost:{(endTime - startTime).TotalSeconds}s");
|
||||
#if AGG
|
||||
using (var e = GEvent.GameEvent("Preload_finish"))
|
||||
{
|
||||
e.AddContent("status", result ? "Succeeded" : "Failed")
|
||||
.AddContent("duration_ms", (endTime - startTime).TotalMilliseconds);
|
||||
if (downloadOp.OperationException != null)
|
||||
{
|
||||
e.AddContent("error", downloadOp.OperationException.Message);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Addressables.Release(downloadOp);
|
||||
}
|
||||
progress?.Invoke(1);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private const float byte2mb = 1024 * 1024;
|
||||
private string GetSizeByBytes(long total, float percent)
|
||||
{
|
||||
return $"{(percent * total / byte2mb).ToString("0.0")}MB/{(total / byte2mb).ToString("0.0")}MB";
|
||||
}
|
||||
|
||||
private string GetSizeByBytes(long total)
|
||||
{
|
||||
return $"{(total / byte2mb).ToString("0.00")}MB";
|
||||
}
|
||||
|
||||
public async Task<bool> Load(string label)
|
||||
{
|
||||
try
|
||||
{
|
||||
oldName = label;
|
||||
if (loadResourceDatas.ContainsKey(label))
|
||||
{
|
||||
curName = label;
|
||||
return false;
|
||||
}
|
||||
var locationsOp = Addressables.LoadResourceLocationsAsync(label);
|
||||
GameCore.UIManager.ShowWaitingBlock("LoadResourceService::Load");
|
||||
var locations = await locationsOp.Task;
|
||||
var totalDownloadSize = await Addressables.GetDownloadSizeAsync(locations).Task;
|
||||
GameCore.UIManager.HideWaitingBlock("LoadResourceService::Load");
|
||||
if (totalDownloadSize > 1)
|
||||
{
|
||||
Load(label, totalDownloadSize, locations.Select(_ => _.PrimaryKey).ToList());
|
||||
return false;
|
||||
}
|
||||
Addressables.Release(locationsOp);
|
||||
return true;
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
GameCore.UIManager.HideWaitingBlock("LoadResourceService:Load");
|
||||
Debug.LogError(e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public async Task<bool> Loads(List<string> labels)
|
||||
{
|
||||
try
|
||||
{
|
||||
oldName = labels[0];
|
||||
if (loadResourceDatas.ContainsKey(labels[0]))
|
||||
{
|
||||
curName = labels[0];
|
||||
return false;
|
||||
}
|
||||
var locationsOp = Addressables.LoadResourceLocationsAsync(labels, Addressables.MergeMode.Union);
|
||||
GameCore.UIManager.ShowWaitingBlock("LoadResourceService::Loads");
|
||||
var locations = await locationsOp.Task;
|
||||
var totalDownloadSize = await Addressables.GetDownloadSizeAsync(locations).Task;
|
||||
GameCore.UIManager.HideWaitingBlock("LoadResourceService::Loads");
|
||||
if (totalDownloadSize > 1)
|
||||
{
|
||||
Load(labels[0], totalDownloadSize, locations.Select(_ => _.PrimaryKey).ToList());
|
||||
return false;
|
||||
}
|
||||
Addressables.Release(locationsOp);
|
||||
return true;
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
GameCore.UIManager.HideWaitingBlock("LoadResourceService::Loads");
|
||||
Debug.LogError(e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public async Task<bool> CheckResource(string label)
|
||||
{
|
||||
try
|
||||
{
|
||||
var locationsOp = Addressables.LoadResourceLocationsAsync(label);
|
||||
GameCore.UIManager.ShowWaitingBlock("LoadResourceService::Load");
|
||||
var locations = await locationsOp.Task;
|
||||
var totalDownloadSize = await Addressables.GetDownloadSizeAsync(locations).Task;
|
||||
GameCore.UIManager.HideWaitingBlock("LoadResourceService::Load");
|
||||
Addressables.Release(locationsOp);
|
||||
if (totalDownloadSize > 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
GameCore.UIManager.HideWaitingBlock("LoadResourceService:Load");
|
||||
Debug.LogError(e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public async void Load(List<string> label)
|
||||
{
|
||||
var locationsOp = Addressables.LoadResourceLocationsAsync(label, Addressables.MergeMode.Union);
|
||||
var locations = await locationsOp.Task;
|
||||
var totalDownloadSize = await Addressables.GetDownloadSizeAsync(locations).Task;
|
||||
if (totalDownloadSize > 0)
|
||||
{
|
||||
for (int i = 0; locations.Count > i; i++)
|
||||
{
|
||||
//判断 loadQueue 是否包含当前资源
|
||||
if (loadQueue.Contains(locations[i].PrimaryKey))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
loadQueue.AddLast(locations[i].PrimaryKey);
|
||||
if (loadQueue.Count == 1)
|
||||
{
|
||||
LoadKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
Addressables.Release(locationsOp);
|
||||
}
|
||||
async void Load(string name, float totalDownloadSize, IList<string> keys)
|
||||
{
|
||||
try
|
||||
{
|
||||
curName = name;
|
||||
AsyncOperationHandle downloadOp = Addressables.DownloadDependenciesAsync(keys, Addressables.MergeMode.Union);
|
||||
loadResourceDatas[name] = downloadOp;
|
||||
LoadProgressEvent loadProgressEvent = new LoadProgressEvent() { name = name, progress = downloadOp.GetDownloadStatus().Percent, totalDownloadSize = totalDownloadSize };
|
||||
while (!downloadOp.IsDone && downloadOp.Status != AsyncOperationStatus.Failed)
|
||||
{
|
||||
if (name == curName)
|
||||
{
|
||||
loadProgressEvent.progress = downloadOp.GetDownloadStatus().Percent;
|
||||
loadProgressEvent.totalDownloadSize = totalDownloadSize;
|
||||
GContext.Publish(loadProgressEvent);
|
||||
}
|
||||
await Awaiters.Seconds(0.2f);
|
||||
}
|
||||
|
||||
if (name == curName)
|
||||
{
|
||||
if (downloadOp.Status == AsyncOperationStatus.Succeeded)
|
||||
{
|
||||
loadProgressEvent.progress = 1.0001f;
|
||||
loadProgressEvent.isSucceeded = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
loadProgressEvent.isFailed = true;
|
||||
}
|
||||
loadProgressEvent.totalDownloadSize = totalDownloadSize;
|
||||
GContext.Publish(loadProgressEvent);
|
||||
}
|
||||
try
|
||||
{
|
||||
OnLoadGameEvent(downloadOp, string.Join(',', keys));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError(e);
|
||||
}
|
||||
|
||||
Addressables.Release(downloadOp);
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
Debug.LogError(e);
|
||||
}
|
||||
loadResourceDatas.Remove(name);
|
||||
}
|
||||
async void LoadKey()
|
||||
{
|
||||
while (loadQueue.Count > 0)
|
||||
{
|
||||
string key = loadQueue.First.Value;
|
||||
AsyncOperationHandle downloadOp = Addressables.DownloadDependenciesAsync(key);
|
||||
await downloadOp.Task;
|
||||
|
||||
OnLoadGameEvent(downloadOp, key);
|
||||
|
||||
Addressables.Release(downloadOp);
|
||||
await Awaiters.NextFrame;
|
||||
loadQueue.RemoveFirst();
|
||||
}
|
||||
}
|
||||
public async Task<bool> CheckResourceLoadQueue(List<string> label)
|
||||
{
|
||||
string key = string.Join(",", label);
|
||||
return await ResourceLoadQueue(key, label);
|
||||
}
|
||||
public async Task<bool> CheckResourceLoadQueue(string key, List<string> label)
|
||||
{
|
||||
bool NoCheckResource = config.Get("NoCheckResource", "0") == "1";
|
||||
if (NoCheckResource)
|
||||
return true;
|
||||
return await ResourceLoadQueue(key, label);
|
||||
}
|
||||
async Task<bool> ResourceLoadQueue(string key, List<string> label)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (loadRecord.ContainsKey(key))
|
||||
{
|
||||
return loadRecord[key];
|
||||
}
|
||||
var locationsOp = Addressables.LoadResourceLocationsAsync(label, Addressables.MergeMode.Union);
|
||||
GameCore.UIManager.ShowWaitingBlock("LoadResourceService::Load");
|
||||
var locations = await locationsOp.Task;
|
||||
var totalDownloadSize = await Addressables.GetDownloadSizeAsync(locations).Task;
|
||||
GameCore.UIManager.HideWaitingBlock("LoadResourceService::Load");
|
||||
Addressables.Release(locationsOp);
|
||||
if (totalDownloadSize > 1)
|
||||
{
|
||||
loadRecord[key] = false;
|
||||
LoadEventResourceEvent loadEventData = new LoadEventResourceEvent();
|
||||
loadEventData.key = key;
|
||||
loadEventData.label = label;
|
||||
LoadEventResource(loadEventData);
|
||||
return false;
|
||||
}
|
||||
loadRecord[key] = true;
|
||||
return true;
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
loadRecord.Remove(key);
|
||||
GameCore.UIManager.HideWaitingBlock("LoadResourceService:Load");
|
||||
Debug.LogError(e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/// <summary>
|
||||
/// 排队下载活动资源
|
||||
/// </summary>
|
||||
/// <param name="loadEventData"></param>
|
||||
void LoadEventResource(LoadEventResourceEvent loadEventData)
|
||||
{
|
||||
if (loadEventData.label == null || loadEventData.label.Count == 0)
|
||||
return;
|
||||
loadEventQueue.AddLast(loadEventData);
|
||||
if (loadEventQueue.Count == 1)
|
||||
{
|
||||
LoadEventKey();
|
||||
}
|
||||
}
|
||||
async void LoadEventKey()
|
||||
{
|
||||
LoadEventResourceing = true;
|
||||
while (loadEventQueue.Count > 0)
|
||||
{
|
||||
LoadEventResourceEvent loadEventData = loadEventQueue.First.Value;
|
||||
if (loadEventData.label == null || loadEventData.label.Count == 0)
|
||||
{
|
||||
loadEventQueue.RemoveFirst();
|
||||
continue;
|
||||
}
|
||||
try
|
||||
{
|
||||
var locationsOp = Addressables.LoadResourceLocationsAsync(loadEventData.label, Addressables.MergeMode.Union);
|
||||
var locations = await locationsOp.Task;
|
||||
Addressables.Release(locationsOp);
|
||||
|
||||
// 检查locations是否有效
|
||||
if (locations == null || locations.Count == 0)
|
||||
{
|
||||
Debug.Log("未找到任何资源位置");
|
||||
loadEventData.isSucceeded = false;
|
||||
GContext.Publish(loadEventData);
|
||||
loadEventQueue.RemoveFirst();
|
||||
continue;
|
||||
}
|
||||
var totalDownloadSize = await Addressables.GetDownloadSizeAsync(locations).Task;
|
||||
if (totalDownloadSize > 0)
|
||||
{
|
||||
var keys = locations.Select(_ => _.PrimaryKey).ToList();
|
||||
string keyStr = string.Join(",", keys);
|
||||
Debug.Log($"资源名称:{keyStr}");
|
||||
Debug.Log($"资源大小:{GetSizeByBytes(totalDownloadSize)}");
|
||||
|
||||
AsyncOperationHandle downloadOp = Addressables.DownloadDependenciesAsync(keys, Addressables.MergeMode.Union);
|
||||
await downloadOp.Task;
|
||||
await Awaiters.NextFrame;
|
||||
OnLoadGameEvent(downloadOp, keyStr);
|
||||
bool isSucceeded = downloadOp.Status == AsyncOperationStatus.Succeeded;
|
||||
loadEventData.isSucceeded = isSucceeded;
|
||||
GContext.Publish(loadEventData);
|
||||
if (isSucceeded)
|
||||
{
|
||||
loadRecord[loadEventData.key] = isSucceeded;
|
||||
}
|
||||
else
|
||||
{
|
||||
loadRecord.Remove(loadEventData.key);
|
||||
}
|
||||
Addressables.Release(downloadOp);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log($"资源大小:{0}");
|
||||
await Awaiters.NextFrame;
|
||||
loadEventData.isSucceeded = true;
|
||||
GContext.Publish(loadEventData);
|
||||
loadRecord[loadEventData.key] = true;
|
||||
}
|
||||
loadEventQueue.RemoveFirst();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"资源下载: {e.Message} {e.StackTrace}");
|
||||
loadEventData.isSucceeded = false;
|
||||
GContext.Publish(loadEventData);
|
||||
loadRecord.Remove(loadEventData.key);
|
||||
loadEventQueue.RemoveFirst();
|
||||
Debug.Log($"错误下载活动资源队列 count == {loadEventQueue.Count}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void OnLoadGameEvent(AsyncOperationHandle downloadOp, string key)
|
||||
{
|
||||
if (downloadOp.Status == AsyncOperationStatus.Failed || downloadOp.OperationException != null)
|
||||
{
|
||||
Exception exception = downloadOp.OperationException;
|
||||
using (var e = GEvent.GameEvent("resource_load_finish"))
|
||||
{
|
||||
e.AddContent("status", "Failed")
|
||||
.AddContent("keys", key)
|
||||
;
|
||||
if (exception != null)
|
||||
{
|
||||
e.AddContent("error", exception.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user