diff --git a/.github/workflows/build-debug.yml b/.github/workflows/build-debug.yml
index 5c069f6..e3bd6a6 100644
--- a/.github/workflows/build-debug.yml
+++ b/.github/workflows/build-debug.yml
@@ -81,6 +81,7 @@ jobs:
# Store artifacts.
- uses: Cysharp/Actions/.github/actions/upload-artifact@main
+ if: ${{ startsWith(matrix.unity, '2021') }} # only execute 2021
with:
name: UniTask.unitypackage-${{ matrix.unity }}.zip
path: ./src/UniTask/*.unitypackage
diff --git a/README.md b/README.md
index 41ed888..2fe49de 100644
--- a/README.md
+++ b/README.md
@@ -526,6 +526,9 @@ It indicates when to run, you can check [PlayerLoopList.md](https://gist.github.
In UniTask, await directly uses native timing, while `WithCancellation` and `ToUniTask` use specified timing. This is usually not a particular problem, but with `LoadSceneAsync`, it causes a different order of Start and continuation after await. So it is recommended not to use `LoadSceneAsync.ToUniTask`.
+> Note: When using Unity 2023.1 or newer, ensure you have `using UnityEngine;` in the using statements of your file when working with new `UnityEngine.Awaitable` methods like `SceneManager.LoadSceneAsync`.
+> This prevents compilation errors by avoiding the use of the `UnityEngine.AsyncOperation` version.
+
In the stacktrace, you can check where it is running in playerloop.

diff --git a/src/UniTask/Assets/Plugins/UniTask/Runtime/UniTask.Factory.cs b/src/UniTask/Assets/Plugins/UniTask/Runtime/UniTask.Factory.cs
index bd66aba..8bdec75 100644
--- a/src/UniTask/Assets/Plugins/UniTask/Runtime/UniTask.Factory.cs
+++ b/src/UniTask/Assets/Plugins/UniTask/Runtime/UniTask.Factory.cs
@@ -184,6 +184,78 @@ namespace Cysharp.Threading.Tasks
return () => asyncAction(state).Forget();
}
+ ///
+ /// Create async void(UniTaskVoid) UnityAction.
+ /// For example: onClick.AddListener(UniTask.UnityAction(async (T arg) => { /* */ } ))
+ ///
+ public static UnityEngine.Events.UnityAction UnityAction(Func asyncAction)
+ {
+ return (arg) => asyncAction(arg).Forget();
+ }
+
+ ///
+ /// Create async void(UniTaskVoid) UnityAction.
+ /// For example: onClick.AddListener(UniTask.UnityAction(async (T0 arg0, T1 arg1) => { /* */ } ))
+ ///
+ public static UnityEngine.Events.UnityAction UnityAction(Func asyncAction)
+ {
+ return (arg0, arg1) => asyncAction(arg0, arg1).Forget();
+ }
+
+ ///
+ /// Create async void(UniTaskVoid) UnityAction.
+ /// For example: onClick.AddListener(UniTask.UnityAction(async (T0 arg0, T1 arg1, T2 arg2) => { /* */ } ))
+ ///
+ public static UnityEngine.Events.UnityAction UnityAction(Func asyncAction)
+ {
+ return (arg0, arg1, arg2) => asyncAction(arg0, arg1, arg2).Forget();
+ }
+
+ ///
+ /// Create async void(UniTaskVoid) UnityAction.
+ /// For example: onClick.AddListener(UniTask.UnityAction(async (T0 arg0, T1 arg1, T2 arg2, T3 arg3) => { /* */ } ))
+ ///
+ public static UnityEngine.Events.UnityAction UnityAction(Func asyncAction)
+ {
+ return (arg0, arg1, arg2, arg3) => asyncAction(arg0, arg1, arg2, arg3).Forget();
+ }
+
+ //
+ /// Create async void(UniTaskVoid) UnityAction.
+ /// For example: onClick.AddListener(UniTask.UnityAction(async (T arg, CancellationToken cancellationToken) => { /* */ } ))
+ ///
+ public static UnityEngine.Events.UnityAction UnityAction(Func asyncAction, CancellationToken cancellationToken)
+ {
+ return (arg) => asyncAction(arg, cancellationToken).Forget();
+ }
+
+ ///
+ /// Create async void(UniTaskVoid) UnityAction.
+ /// For example: onClick.AddListener(UniTask.UnityAction(async (T0 arg0, T1 arg1, CancellationToken cancellationToken) => { /* */ } ))
+ ///
+ public static UnityEngine.Events.UnityAction UnityAction(Func asyncAction, CancellationToken cancellationToken)
+ {
+ return (arg0, arg1) => asyncAction(arg0, arg1, cancellationToken).Forget();
+ }
+
+ ///
+ /// Create async void(UniTaskVoid) UnityAction.
+ /// For example: onClick.AddListener(UniTask.UnityAction(async (T0 arg0, T1 arg1, T2 arg2, CancellationToken cancellationToken) => { /* */ } ))
+ ///
+ public static UnityEngine.Events.UnityAction UnityAction(Func asyncAction, CancellationToken cancellationToken)
+ {
+ return (arg0, arg1, arg2) => asyncAction(arg0, arg1, arg2, cancellationToken).Forget();
+ }
+
+ ///
+ /// Create async void(UniTaskVoid) UnityAction.
+ /// For example: onClick.AddListener(UniTask.UnityAction(async (T0 arg0, T1 arg1, T2 arg2, T3 arg3, CancellationToken cancellationToken) => { /* */ } ))
+ ///
+ public static UnityEngine.Events.UnityAction UnityAction(Func asyncAction, CancellationToken cancellationToken)
+ {
+ return (arg0, arg1, arg2, arg3) => asyncAction(arg0, arg1, arg2, arg3, cancellationToken).Forget();
+ }
+
#endif
///
@@ -202,6 +274,22 @@ namespace Cysharp.Threading.Tasks
return new UniTask(new DeferPromise(factory), 0);
}
+ ///
+ /// Defer the task creation just before call await.
+ ///
+ public static UniTask Defer(TState state, Func factory)
+ {
+ return new UniTask(new DeferPromiseWithState(state, factory), 0);
+ }
+
+ ///
+ /// Defer the task creation just before call await.
+ ///
+ public static UniTask Defer(TState state, Func> factory)
+ {
+ return new UniTask(new DeferPromiseWithState(state, factory), 0);
+ }
+
///
/// Never complete.
///
@@ -465,6 +553,93 @@ namespace Cysharp.Threading.Tasks
}
}
+ sealed class DeferPromiseWithState : IUniTaskSource
+ {
+ Func factory;
+ TState argument;
+ UniTask task;
+ UniTask.Awaiter awaiter;
+
+ public DeferPromiseWithState(TState argument, Func factory)
+ {
+ this.argument = argument;
+ this.factory = factory;
+ }
+
+ public void GetResult(short token)
+ {
+ awaiter.GetResult();
+ }
+
+ public UniTaskStatus GetStatus(short token)
+ {
+ var f = Interlocked.Exchange(ref factory, null);
+ if (f != null)
+ {
+ task = f(argument);
+ awaiter = task.GetAwaiter();
+ }
+
+ return task.Status;
+ }
+
+ public void OnCompleted(Action