UniTask使用笔记,将Action回调改写成await,以PlayableDirector的Stopped为例

UniTask提供了很多异步方法,如Resources.LoadAsync,UniTask.NextFrame,UniTask.WaitUntil,按钮事件button.OnClickAsync等
当没有内置方法时,我们希望能将自己的回调方法改写为await的形式。
比如将PlayableDirector的stopped回调改写成await,实现如下代码。

Copy
private async UniTask PlayAndDebug() { await _director.OnStoppedAsync(); Debug.Log("director stopped,do something else"); }

原理:通过实现IUniTaskSource和IUniTaskSource接口,实现自己的await逻辑,实现接口我们可以参考AsyncUnityEventHandler里的方法

Copy
public class PlayableDirectorAsyncHandler:IUniTaskSource { static Action<object> cancellationCallback = CancellationCallback; private CancellationToken cancellationToken; private CancellationTokenRegistration registration; private UniTaskCompletionSourceCore<bool> core; bool isDisposed; bool callOnce; private PlayableDirector _director; public PlayableDirectorAsyncHandler(PlayableDirector director,CancellationToken cancellationToken, bool callOnce) { this.cancellationToken = cancellationToken; if (cancellationToken.IsCancellationRequested) { isDisposed = true; return; } this.callOnce = callOnce; _director = director; _director.stopped += OnDirectorStopped; if (cancellationToken.CanBeCanceled) { registration = cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallback, this); } TaskTracker.TrackActiveTask(this, 3); } static void CancellationCallback(object state) { var self = (PlayableDirectorAsyncHandler)state; self.Dispose(); } private void OnDirectorStopped(PlayableDirector obj) { core.TrySetResult(true); } public void Dispose() { if (!isDisposed) { isDisposed = true; TaskTracker.RemoveTracking(this); registration.Dispose(); _director.stopped -= OnDirectorStopped; core.TrySetCanceled(cancellationToken); } } public UniTask OnInvokeAsync() { core.Reset(); if (isDisposed) { core.TrySetCanceled(this.cancellationToken); } return new UniTask(this, core.Version); } public UniTaskStatus GetStatus(short token) { return core.GetStatus(token); } public void OnCompleted(Action<object> continuation, object state, short token) { core.OnCompleted(continuation, state, token); } public void GetResult(short token) { try { core.GetResult(token); } finally { if (callOnce) { Dispose(); } } } public UniTaskStatus UnsafeGetStatus() { return core.UnsafeGetStatus(); } }

最后实现一个扩展方法

Copy
public static class UniTaskAsyncExtensions { public static UniTask OnStoppedAsync(this PlayableDirector director,CancellationToken cancellationToken = default,bool callOnce = true) { return new PlayableDirectorAsyncHandler(director,cancellationToken, callOnce).OnInvokeAsync(); } }

扩展完成。

posted @   jeoyao  阅读(1042)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示