【m】框架大更新

This commit is contained in:
2025-10-31 11:18:23 +08:00
parent ae6e7c804b
commit 8e1d52ddbf
1883 changed files with 213934 additions and 640 deletions

View File

@@ -0,0 +1,342 @@
using System;
using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace YooAsset
{
public abstract class AsyncOperationBase : IEnumerator, IComparable<AsyncOperationBase>
{
private Action<AsyncOperationBase> _callback;
private string _packageName = null;
private int _whileFrame = 1000;
/// <summary>
/// 所有子任务
/// </summary>
internal readonly List<AsyncOperationBase> Childs = new List<AsyncOperationBase>(10);
/// <summary>
/// 等待异步执行完成
/// </summary>
internal bool IsWaitForAsyncComplete { private set; get; } = false;
/// <summary>
/// 是否已经完成
/// </summary>
internal bool IsFinish { private set; get; } = false;
/// <summary>
/// 任务优先级
/// </summary>
public uint Priority { set; get; } = 0;
/// <summary>
/// 任务状态
/// </summary>
public EOperationStatus Status { get; protected set; } = EOperationStatus.None;
/// <summary>
/// 错误信息
/// </summary>
public string Error { get; protected set; }
/// <summary>
/// 处理进度
/// </summary>
public float Progress { get; protected set; }
/// <summary>
/// 所属包裹名称
/// </summary>
public string PackageName
{
get
{
return _packageName;
}
}
/// <summary>
/// 是否已经完成
/// </summary>
public bool IsDone
{
get
{
return Status == EOperationStatus.Failed || Status == EOperationStatus.Succeed;
}
}
/// <summary>
/// 完成事件
/// </summary>
public event Action<AsyncOperationBase> Completed
{
add
{
if (IsDone)
value.Invoke(this);
else
_callback += value;
}
remove
{
_callback -= value;
}
}
/// <summary>
/// 异步操作任务
/// </summary>
public Task Task
{
get
{
if (_taskCompletionSource == null)
{
_taskCompletionSource = new TaskCompletionSource<object>();
if (IsDone)
_taskCompletionSource.SetResult(null);
}
return _taskCompletionSource.Task;
}
}
internal abstract void InternalStart();
internal abstract void InternalUpdate();
internal virtual void InternalAbort()
{
}
internal virtual void InternalWaitForAsyncComplete()
{
throw new System.NotImplementedException(this.GetType().Name);
}
internal virtual string InternalGetDesc()
{
return string.Empty;
}
/// <summary>
/// 设置包裹名称
/// </summary>
internal void SetPackageName(string packageName)
{
_packageName = packageName;
}
/// <summary>
/// 添加子任务
/// </summary>
internal void AddChildOperation(AsyncOperationBase child)
{
#if UNITY_EDITOR
if (Childs.Contains(child))
throw new Exception($"The child node {child.GetType().Name} already exists !");
#endif
Childs.Add(child);
}
/// <summary>
/// 获取异步操作说明
/// </summary>
internal string GetOperationDesc()
{
return InternalGetDesc();
}
/// <summary>
/// 开始异步操作
/// </summary>
internal void StartOperation()
{
if (Status == EOperationStatus.None)
{
Status = EOperationStatus.Processing;
// 开始记录
DebugBeginRecording();
// 开始任务
InternalStart();
}
}
/// <summary>
/// 更新异步操作
/// </summary>
internal void UpdateOperation()
{
if (IsDone == false)
{
// 更新记录
DebugUpdateRecording();
// 更新任务
InternalUpdate();
}
if (IsDone && IsFinish == false)
{
IsFinish = true;
// 进度百分百完成
Progress = 1f;
// 结束记录
DebugEndRecording();
//注意如果完成回调内发生异常会导致Task无限期等待
_callback?.Invoke(this);
if (_taskCompletionSource != null)
_taskCompletionSource.TrySetResult(null);
}
}
/// <summary>
/// 终止异步任务
/// </summary>
internal void AbortOperation()
{
foreach (var child in Childs)
{
child.AbortOperation();
}
if (IsDone == false)
{
Status = EOperationStatus.Failed;
Error = "user abort";
YooLogger.Warning($"Async operaiton {this.GetType().Name} has been abort !");
InternalAbort();
}
}
/// <summary>
/// 执行While循环
/// </summary>
protected bool ExecuteWhileDone()
{
if (IsDone == false)
{
// 执行更新逻辑
InternalUpdate();
// 当执行次数用完时
_whileFrame--;
if (_whileFrame <= 0)
{
Status = EOperationStatus.Failed;
Error = $"Operation {this.GetType().Name} failed to wait for async complete !";
YooLogger.Error(Error);
}
}
return IsDone;
}
/// <summary>
/// 清空完成回调
/// </summary>
protected void ClearCompletedCallback()
{
_callback = null;
}
/// <summary>
/// 等待异步执行完毕
/// </summary>
public void WaitForAsyncComplete()
{
if (IsDone)
return;
//TODO 防止异步操作被挂起陷入无限死循环!
// 例如:文件解压任务或者文件导入任务!
if (Status == EOperationStatus.None)
{
StartOperation();
}
if (IsWaitForAsyncComplete == false)
{
IsWaitForAsyncComplete = true;
InternalWaitForAsyncComplete();
}
}
#region
/// <summary>
/// 开始的时间
/// </summary>
public string BeginTime = string.Empty;
/// <summary>
/// 处理耗时(单位:毫秒)
/// </summary>
public long ProcessTime { protected set; get; }
// 加载耗时统计
private Stopwatch _watch = null;
[Conditional("DEBUG")]
private void DebugBeginRecording()
{
if (_watch == null)
{
BeginTime = SpawnTimeToString(UnityEngine.Time.realtimeSinceStartup);
_watch = Stopwatch.StartNew();
}
}
[Conditional("DEBUG")]
private void DebugUpdateRecording()
{
if (_watch != null)
{
ProcessTime = _watch.ElapsedMilliseconds;
}
}
[Conditional("DEBUG")]
private void DebugEndRecording()
{
if (_watch != null)
{
ProcessTime = _watch.ElapsedMilliseconds;
_watch = null;
}
}
private string SpawnTimeToString(float spawnTime)
{
float h = UnityEngine.Mathf.FloorToInt(spawnTime / 3600f);
float m = UnityEngine.Mathf.FloorToInt(spawnTime / 60f - h * 60f);
float s = UnityEngine.Mathf.FloorToInt(spawnTime - m * 60f - h * 3600f);
return h.ToString("00") + ":" + m.ToString("00") + ":" + s.ToString("00");
}
#endregion
#region
public int CompareTo(AsyncOperationBase other)
{
return other.Priority.CompareTo(this.Priority);
}
#endregion
#region
bool IEnumerator.MoveNext()
{
return !IsDone;
}
void IEnumerator.Reset()
{
}
object IEnumerator.Current => null;
private TaskCompletionSource<object> _taskCompletionSource;
#endregion
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 59d1dd4dd869e444a9ee2800c5a1180d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,11 @@
namespace YooAsset
{
public enum EOperationStatus
{
None,
Processing,
Succeed,
Failed
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 289c4d5f219f9a4468fafaf31e99687d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,59 @@
namespace YooAsset
{
public abstract class GameAsyncOperation : AsyncOperationBase
{
internal override void InternalStart()
{
OnStart();
}
internal override void InternalUpdate()
{
OnUpdate();
}
internal override void InternalAbort()
{
OnAbort();
}
internal override void InternalWaitForAsyncComplete()
{
OnWaitForAsyncComplete();
}
/// <summary>
/// 异步操作开始
/// </summary>
protected abstract void OnStart();
/// <summary>
/// 异步操作更新
/// </summary>
protected abstract void OnUpdate();
/// <summary>
/// 异步操作终止
/// </summary>
protected abstract void OnAbort();
/// <summary>
/// 异步等待完成
/// </summary>
protected virtual void OnWaitForAsyncComplete() { }
/// <summary>
/// 异步操作系统是否繁忙
/// </summary>
protected bool IsBusy()
{
return OperationSystem.IsBusy;
}
/// <summary>
/// 终止异步操作
/// </summary>
protected void Abort()
{
AbortOperation();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 707dafc9d89a0e240bd574cbc99e1f61
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,210 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
namespace YooAsset
{
internal class OperationSystem
{
#if UNITY_EDITOR
[UnityEngine.RuntimeInitializeOnLoadMethod(UnityEngine.RuntimeInitializeLoadType.SubsystemRegistration)]
private static void OnRuntimeInitialize()
{
DestroyAll();
}
#endif
private static readonly List<AsyncOperationBase> _operations = new List<AsyncOperationBase>(1000);
private static readonly List<AsyncOperationBase> _newList = new List<AsyncOperationBase>(1000);
private static Action<string, AsyncOperationBase> _startCallback = null;
private static Action<string, AsyncOperationBase> _finishCallback = null;
// 计时器相关
private static Stopwatch _watch;
private static long _frameTime;
/// <summary>
/// 异步操作的最小时间片段
/// </summary>
public static long MaxTimeSlice { set; get; } = long.MaxValue;
/// <summary>
/// 处理器是否繁忙
/// </summary>
public static bool IsBusy
{
get
{
// NOTE : 单次调用开销约1微秒
return _watch.ElapsedMilliseconds - _frameTime >= MaxTimeSlice;
}
}
/// <summary>
/// 初始化异步操作系统
/// </summary>
public static void Initialize()
{
_watch = Stopwatch.StartNew();
}
/// <summary>
/// 更新异步操作系统
/// </summary>
public static void Update()
{
// 移除已经完成的异步操作
// 注意:移除上一帧完成的异步操作,方便调试器接收到完整的信息!
for (int i = _operations.Count - 1; i >= 0; i--)
{
var operation = _operations[i];
if (operation.IsFinish)
{
_operations.RemoveAt(i);
if (_finishCallback != null)
_finishCallback.Invoke(operation.PackageName, operation);
}
}
// 添加新增的异步操作
if (_newList.Count > 0)
{
bool sorting = false;
foreach (var operation in _newList)
{
if (operation.Priority > 0)
{
sorting = true;
break;
}
}
_operations.AddRange(_newList);
_newList.Clear();
// 重新排序优先级
if (sorting)
_operations.Sort();
}
// 更新进行中的异步操作
bool checkBusy = MaxTimeSlice < long.MaxValue;
_frameTime = _watch.ElapsedMilliseconds;
for (int i = 0; i < _operations.Count; i++)
{
if (checkBusy && IsBusy)
break;
var operation = _operations[i];
if (operation.IsFinish)
continue;
operation.UpdateOperation();
}
}
/// <summary>
/// 销毁异步操作系统
/// </summary>
public static void DestroyAll()
{
_operations.Clear();
_newList.Clear();
_startCallback = null;
_finishCallback = null;
_watch = null;
_frameTime = 0;
MaxTimeSlice = long.MaxValue;
}
/// <summary>
/// 销毁包裹的所有任务
/// </summary>
public static void ClearPackageOperation(string packageName)
{
// 终止临时队列里的任务
foreach (var operation in _newList)
{
if (operation.PackageName == packageName)
{
operation.AbortOperation();
}
}
// 终止正在进行的任务
foreach (var operation in _operations)
{
if (operation.PackageName == packageName)
{
operation.AbortOperation();
}
}
}
/// <summary>
/// 开始处理异步操作类
/// </summary>
public static void StartOperation(string packageName, AsyncOperationBase operation)
{
_newList.Add(operation);
operation.SetPackageName(packageName);
operation.StartOperation();
if (_startCallback != null)
_startCallback.Invoke(packageName, operation);
}
/// <summary>
/// 监听任务开始
/// </summary>
public static void RegisterStartCallback(Action<string, AsyncOperationBase> callback)
{
_startCallback = callback;
}
/// <summary>
/// 监听任务结束
/// </summary>
public static void RegisterFinishCallback(Action<string, AsyncOperationBase> callback)
{
_finishCallback = callback;
}
#region
internal static List<DebugOperationInfo> GetDebugOperationInfos(string packageName)
{
List<DebugOperationInfo> result = new List<DebugOperationInfo>(_operations.Count);
foreach (var operation in _operations)
{
if (operation.PackageName == packageName)
{
var operationInfo = GetDebugOperationInfo(operation);
result.Add(operationInfo);
}
}
return result;
}
internal static DebugOperationInfo GetDebugOperationInfo(AsyncOperationBase operation)
{
var operationInfo = new DebugOperationInfo();
operationInfo.OperationName = operation.GetType().Name;
operationInfo.OperationDesc = operation.GetOperationDesc();
operationInfo.Priority = operation.Priority;
operationInfo.Progress = operation.Progress;
operationInfo.BeginTime = operation.BeginTime;
operationInfo.ProcessTime = operation.ProcessTime;
operationInfo.Status = operation.Status.ToString();
operationInfo.Childs = new List<DebugOperationInfo>(operation.Childs.Count);
foreach (var child in operation.Childs)
{
var childInfo = GetDebugOperationInfo(child);
operationInfo.Childs.Add(childInfo);
}
return operationInfo;
}
#endregion
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 07137e8cbd1a61448843960a307f68d1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: