mirror of
https://github.com/Cysharp/UniTask.git
synced 2026-05-15 03:20:16 +00:00
Compare commits
70 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3bebaef969 | ||
|
|
37e8b4500e | ||
|
|
8537ddf8a6 | ||
|
|
346b1e0a6b | ||
|
|
fc7b9660a5 | ||
|
|
21e5cc22c7 | ||
|
|
3f18b37e5f | ||
|
|
5d4a90e9bd | ||
|
|
2bf9f4f062 | ||
|
|
d69490cb49 | ||
|
|
4e460c11ca | ||
|
|
9313969314 | ||
|
|
a40f89a922 | ||
|
|
e0d8410b62 | ||
|
|
bef1bd8ad1 | ||
|
|
81b4fcfac1 | ||
|
|
f1e4a3c65d | ||
|
|
65622b01f6 | ||
|
|
87dd5f13fd | ||
|
|
79cd2c17ba | ||
|
|
85fb08552e | ||
|
|
7bd4b6faf7 | ||
|
|
0b1ae7e295 | ||
|
|
35a893ad9e | ||
|
|
4955ed18f1 | ||
|
|
fe462328ab | ||
|
|
5136d92efa | ||
|
|
227f7872cb | ||
|
|
725b2fdc35 | ||
|
|
75abc8059f | ||
|
|
f1193743c8 | ||
|
|
109730eacd | ||
|
|
1f736afe86 | ||
|
|
4d554a6718 | ||
|
|
69c0c362e9 | ||
|
|
3bb446556a | ||
|
|
ea950d8cec | ||
|
|
a65f4da7a2 | ||
|
|
0bdc933c20 | ||
|
|
0c0f79c6db | ||
|
|
32f9b9d4ac | ||
|
|
53907a3719 | ||
|
|
4937aeee3f | ||
|
|
5e5b8aff89 | ||
|
|
a2cbbd82d0 | ||
|
|
7eac5d8ba8 | ||
|
|
e2b1ed55ae | ||
|
|
727c7102d3 | ||
|
|
1494ea6717 | ||
|
|
f1ce64dbd3 | ||
|
|
3bad5cd2bf | ||
|
|
7432c0073a | ||
|
|
f1813a7c94 | ||
|
|
9e45c0a4d1 | ||
|
|
2c652cdde7 | ||
|
|
7718d345c8 | ||
|
|
9f39708325 | ||
|
|
bb6dbfa920 | ||
|
|
ba265005bb | ||
|
|
4d7cc7ed61 | ||
|
|
b64f31eb0b | ||
|
|
38d159b69e | ||
|
|
d5455f3716 | ||
|
|
a72ceeba11 | ||
|
|
c6b7d332b2 | ||
|
|
f37278f2a6 | ||
|
|
3f3e03b83d | ||
|
|
c99d3eb3c3 | ||
|
|
08d5183e7e | ||
|
|
51769b2224 |
7
.github/workflows/build-debug.yml
vendored
7
.github/workflows/build-debug.yml
vendored
@@ -42,13 +42,6 @@ jobs:
|
||||
steps:
|
||||
- run: apt update && apt install git -y
|
||||
- uses: actions/checkout@v2
|
||||
# create unity activation file and store to artifacts.
|
||||
- run: /opt/Unity/Editor/Unity -quit -batchmode -nographics -logFile -createManualActivationFile || exit 0
|
||||
- uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: Unity_v${{ matrix.unity }}.alf
|
||||
path: ./Unity_v${{ matrix.unity }}.alf
|
||||
# activate Unity from manual license file(ulf)
|
||||
- run: echo -n "$UNITY_LICENSE" >> .Unity.ulf
|
||||
env:
|
||||
UNITY_LICENSE: ${{ secrets[matrix.license] }}
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -253,3 +253,5 @@ src/UniTask/UnityEngine.UI.Player.csproj
|
||||
src/UniTask/DOTween.Modules.Player.csproj
|
||||
|
||||
src/UniTask/Assembly-CSharp.Player.csproj
|
||||
|
||||
src/UniTask/Unity.EditorCoroutines.Editor.csproj
|
||||
|
||||
70
README.md
70
README.md
@@ -14,7 +14,8 @@ Provides an efficient allocation free async/await integration to Unity.
|
||||
* Highly compatible behaviour with Task/ValueTask/IValueTaskSource
|
||||
|
||||
Techinical details, see blog post: [UniTask v2 — Zero Allocation async/await for Unity, with Asynchronous LINQ
|
||||
](https://medium.com/@neuecc/unitask-v2-zero-allocation-async-await-for-unity-with-asynchronous-linq-1aa9c96aa7dd)
|
||||
](https://medium.com/@neuecc/unitask-v2-zero-allocation-async-await-for-unity-with-asynchronous-linq-1aa9c96aa7dd)
|
||||
Advanced tips, see blog post: [Extends UnityWebRequest via async decorator pattern — Advanced Techniques of UniTask](https://medium.com/@neuecc/extends-unitywebrequest-via-async-decorator-pattern-advanced-techniques-of-unitask-ceff9c5ee846)
|
||||
|
||||
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
||||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
||||
@@ -32,8 +33,12 @@ Techinical details, see blog post: [UniTask v2 — Zero Allocation async/await f
|
||||
- [Awaitable Events](#awaitable-events)
|
||||
- [Channel](#channel)
|
||||
- [For Unit Testing](#for-unit-testing)
|
||||
- [ThreadPool limitation](#threadpool-limitation)
|
||||
- [IEnumerator.ToUniTask limitation](#ienumeratortounitask-limitation)
|
||||
- [For UnityEditor](#for-unityeditor)
|
||||
- [Compare with Standard Task API](#compare-with-standard-task-api)
|
||||
- [Pooling Configuration](#pooling-configuration)
|
||||
- [Allocation on Profiler](#allocation-on-profiler)
|
||||
- [UniTaskSynchronizationContext](#unitasksynchronizationcontext)
|
||||
- [API References](#api-references)
|
||||
- [UPM Package](#upm-package)
|
||||
@@ -151,25 +156,24 @@ UniTask provides three pattern of extension methods.
|
||||
|
||||
> Note: WithCancellation is returned from native timing of PlayerLoop but ToUniTask is returned from specified PlayerLoopTiming. Details of timing, see: [PlayerLoop](#playerloop) section.
|
||||
|
||||
> Note: AssetBundleRequest has `asset` and `allAssets`, in default await returns `asset`. If you want to get `allAssets`, you can use `AwaitForAllAssets()` method.
|
||||
|
||||
The type of `UniTask` can use utility like `UniTask.WhenAll`, `UniTask.WhenAny`. It is like Task.WhenAll/WhenAny but return type is more useful, returns value tuple so can deconsrtuct each result and pass multiple type.
|
||||
|
||||
```csharp
|
||||
public class SceneAssets
|
||||
public async UniTaskVoid LoadManyAsync()
|
||||
{
|
||||
public SceneAssets()
|
||||
{
|
||||
// parallel load.
|
||||
var (a, b, c) = await UniTask.WhenAll(
|
||||
LoadAsSprite("foo"),
|
||||
LoadAsSprite("bar"),
|
||||
LoadAsSprite("baz"));
|
||||
}
|
||||
// parallel load.
|
||||
var (a, b, c) = await UniTask.WhenAll(
|
||||
LoadAsSprite("foo"),
|
||||
LoadAsSprite("bar"),
|
||||
LoadAsSprite("baz"));
|
||||
}
|
||||
|
||||
async UniTask<Sprite> LoadAsSprite(string path)
|
||||
{
|
||||
var resource = await Resources.LoadAsync<Sprite>(path);
|
||||
return (resource as Sprite);
|
||||
}
|
||||
async UniTask<Sprite> LoadAsSprite(string path)
|
||||
{
|
||||
var resource = await Resources.LoadAsync<Sprite>(path);
|
||||
return (resource as Sprite);
|
||||
}
|
||||
```
|
||||
|
||||
@@ -347,6 +351,8 @@ It indicates when to run, you can check [PlayerLoopList.md](https://gist.github.
|
||||
|
||||
`PlayerLoopTiming.Update` is similar as `yield return null` in coroutine, but it is called before Update(Update and uGUI events(button.onClick, etc...) are called on `ScriptRunBehaviourUpdate`, yield return null is called on `ScriptRunDelayedDynamicFrameRate`). `PlayerLoopTiming.FixedUpdate` is similar as `WaitForFixedUpdate`, `PlayerLoopTiming.LastPostLateUpdate` is similar as `WaitForEndOfFrame` in coroutine.
|
||||
|
||||
> `await UniTask.WaitForEndOfFrame()` is not equilavelnt to coroutine's `yield return new WaitForEndOfFrame()`. Coroutine's WaitForEndOfFrame seems to run after the PlayerLoop is done. Some methods that require coroutine's end of frame(`ScreenCapture.CaptureScreenshotAsTexture`, `CommandBuffer`, etc) does not work correctly when replace to async/await. In that case, use a coroutine.
|
||||
|
||||
`yield return null` and `UniTask.Yield` is similar but different. `yield return null` always return next frame but `UniTask.Yield` return next called, that is, call `UniTask.Yield(PlayerLoopTiming.Update)` on `PreUpdate`, it returns same frame. `UniTask.NextFrame()` gurantees return next frame, this would be expected to behave exactly the same as `yield return null`.
|
||||
|
||||
> UniTask.Yield(without CancellationToken) is a special type, returns `YieldAwaitable` and run on YieldRunner. It is most lightweight and faster.
|
||||
@@ -489,6 +495,8 @@ await UniTask.WhenAll(
|
||||
transform.DOScale(10, 3).WithCancellation(ct));
|
||||
```
|
||||
|
||||
DOTween support's default behaviour(`await`, `WithCancellation`, `ToUniTask`) awaits tween is killed. It works both Complete(true/false) and Kill(true/false). But if you want to tween reuse(`SetAutoKill(false)`), it does not work you expected. Or, if you want to await for another timing, the following extension methods exist in Tween, `AwaitForComplete`, `AwaitForPause`, `AwaitForPlay`, `AwaitForRewind`, `AwaitForStepComplete`.
|
||||
|
||||
AsyncEnumerable and Async LINQ
|
||||
---
|
||||
Unity 2020.2.0a12 supports C# 8.0 so you can use `await foreach`. This is the new Update notation in async era.
|
||||
@@ -778,6 +786,26 @@ public IEnumerator DelayIgnore() => UniTask.ToCoroutine(async () =>
|
||||
|
||||
UniTask itself's unit test is written by Unity Test Runner and [Cysharp/RuntimeUnitTestToolkit](https://github.com/Cysharp/RuntimeUnitTestToolkit) to check on CI and IL2CPP working.
|
||||
|
||||
ThreadPool limitation
|
||||
---
|
||||
Most UniTask methods run in a single thread (PlayerLoop), but only `UniTask.Run` and `UniTask.SwitchToThreadPool` run on a thread pool. If you use a thread pool, it won't work with WebGL and so on.
|
||||
|
||||
`UniTask.Run` will be deprecated in the future (marked with an Obsolete) and only `RunOnThreadPool` will be used. Also, if you use `UniTask.Run`, consider whether you can use `UniTask.Create` or `UniTask.Void`.
|
||||
|
||||
IEnumerator.ToUniTask limitation
|
||||
---
|
||||
You can convert coroutine(IEnumerator) to UniTask(or await directly) but has some limitations.
|
||||
|
||||
* `WaitForEndOfFrame`/`WaitForFixedUpdate` is not supported, used `yield return null` instead.
|
||||
* Consuming loop timing is not same as StartCoroutine, it is used specified PlayerLoopTiming, and default's `PlayerLoopTiming.Update` is run before MonoBehaviour's Update and StartCoroutine's loop.
|
||||
|
||||
For UnityEditor
|
||||
---
|
||||
UniTask can run on Unity Edtitor like Editor Coroutine. However, there are some limitations.
|
||||
|
||||
* Delay, DelayFrame is not work correctly because can not get deltaTime in editor. Return the result of the await immediately; you can use `DelayType.Realtime` to wait for the right time.
|
||||
* All PlayerLoopTiming run on timing, `EditorApplication.update`.
|
||||
|
||||
Compare with Standard Task API
|
||||
---
|
||||
UniTask has many standard Task-like APIs. This table shows what is the alternative apis.
|
||||
@@ -835,7 +863,15 @@ foreach (var (type, size) in TaskPool.GetCacheSizeInfo())
|
||||
}
|
||||
```
|
||||
|
||||
> In UnityEditor profiler shows allocation of compiler generated AsyncStateMachine but it only occurs in debug(development) build. C# Compiler generate AsyncStateMachine as class on Debug build and as struct on Release build.
|
||||
Allocation on Profiler
|
||||
---
|
||||
In UnityEditor profiler shows allocation of compiler generated AsyncStateMachine but it only occurs in debug(development) build. C# Compiler generate AsyncStateMachine as class on Debug build and as struct on Release build.
|
||||
|
||||
After Unity 2020.1 supports Code Optimization option on UnityEditor(right, footer).
|
||||
|
||||

|
||||
|
||||
You can change C# compiler optimization to release, it removes AsyncStateMachine allocation. Andalso optimization option can set via `Compilation.CompilationPipeline-codeOptimization`, and `Compilation.CodeOptimization`.
|
||||
|
||||
UniTaskSynchronizationContext
|
||||
---
|
||||
@@ -872,7 +908,7 @@ After Unity 2019.3.4f1, Unity 2020.1a21, that support path query parameter of gi
|
||||
|
||||
or add `"com.cysharp.unitask": "https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask"` to `Packages/manifest.json`.
|
||||
|
||||
If you want to set a target version, UniTask is using `*.*.*` release tag so you can specify a version like `#2.0.24`. For example `https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask#2.0.24`.
|
||||
If you want to set a target version, UniTask is using `*.*.*` release tag so you can specify a version like `#2.0.36`. For example `https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask#2.0.36`.
|
||||
|
||||
### Install via OpenUPM
|
||||
|
||||
|
||||
@@ -62,7 +62,8 @@ namespace Cysharp.Threading.Tasks
|
||||
sealed class ThreadPoolWorkItem : IThreadPoolWorkItem, ITaskPoolNode<ThreadPoolWorkItem>
|
||||
{
|
||||
static TaskPool<ThreadPoolWorkItem> pool;
|
||||
public ThreadPoolWorkItem NextNode { get; set; }
|
||||
ThreadPoolWorkItem nextNode;
|
||||
public ref ThreadPoolWorkItem NextNode => ref nextNode;
|
||||
|
||||
static ThreadPoolWorkItem()
|
||||
{
|
||||
|
||||
@@ -10,11 +10,14 @@ public class QueueCheck
|
||||
{
|
||||
Node node1 = new Node();
|
||||
Node node2 = new Node();
|
||||
RefNode refNode1 = new RefNode();
|
||||
RefNode refNode2 = new RefNode();
|
||||
Queue<Node> q1 = new Queue<Node>();
|
||||
Stack<Node> s1 = new Stack<Node>();
|
||||
ConcurrentQueue<Node> cq = new ConcurrentQueue<Node>();
|
||||
ConcurrentStack<Node> cs = new ConcurrentStack<Node>();
|
||||
static TaskPool<Node> pool;
|
||||
static TaskPoolRefNode<RefNode> poolRefNode;
|
||||
static TaskPoolEqualNull<Node> poolEqualNull;
|
||||
static TaskPoolClass<Node> poolClass = new TaskPoolClass<Node>();
|
||||
static TaskPoolWithoutSize<Node> poolWithoutSize;
|
||||
@@ -82,6 +85,14 @@ public class QueueCheck
|
||||
pool.TryPop(out _);
|
||||
pool.TryPop(out _);
|
||||
}
|
||||
[Benchmark]
|
||||
public void TaskPoolRefNode()
|
||||
{
|
||||
poolRefNode.TryPush(refNode1);
|
||||
poolRefNode.TryPush(refNode2);
|
||||
poolRefNode.TryPop(out _);
|
||||
poolRefNode.TryPop(out _);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void TaskPoolEqualNull()
|
||||
@@ -130,6 +141,18 @@ public interface ITaskPoolNode<T>
|
||||
T NextNode { get; set; }
|
||||
}
|
||||
|
||||
public sealed class RefNode :ITaskPoolRefNode<RefNode>
|
||||
{
|
||||
RefNode nextNode;
|
||||
public ref RefNode NextNode => ref nextNode;
|
||||
}
|
||||
|
||||
public interface ITaskPoolRefNode<T>
|
||||
{
|
||||
ref T NextNode { get; }
|
||||
}
|
||||
|
||||
|
||||
// mutable struct, don't mark readonly.
|
||||
[StructLayout(LayoutKind.Auto)]
|
||||
public struct TaskPoolWithoutLock<T>
|
||||
@@ -237,6 +260,60 @@ public struct TaskPool<T>
|
||||
return false;
|
||||
}
|
||||
}
|
||||
[StructLayout(LayoutKind.Auto)]
|
||||
public struct TaskPoolRefNode<T>
|
||||
where T : class, ITaskPoolRefNode<T>
|
||||
{
|
||||
int gate;
|
||||
int size;
|
||||
T root;
|
||||
|
||||
public int Size => size;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool TryPop(out T result)
|
||||
{
|
||||
if (Interlocked.CompareExchange(ref gate, 1, 0) == 0)
|
||||
{
|
||||
var v = root;
|
||||
if (!(v is null))
|
||||
{
|
||||
ref var nextNode = ref v.NextNode;
|
||||
root = nextNode;
|
||||
nextNode = null;
|
||||
size--;
|
||||
result = v;
|
||||
Volatile.Write(ref gate, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
Volatile.Write(ref gate, 0);
|
||||
}
|
||||
result = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool TryPush(T item)
|
||||
{
|
||||
if (Interlocked.CompareExchange(ref gate, 1, 0) == 0)
|
||||
{
|
||||
//if (size < TaskPool.MaxPoolSize)
|
||||
{
|
||||
item.NextNode = root;
|
||||
root = item;
|
||||
size++;
|
||||
Volatile.Write(ref gate, 0);
|
||||
return true;
|
||||
}
|
||||
//else
|
||||
{
|
||||
// Volatile.Write(ref gate, 0);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Auto)]
|
||||
public struct TaskPoolEqualNull<T>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"autoReferenced": false,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
|
||||
@@ -87,7 +87,8 @@ namespace Cysharp.Threading.Tasks
|
||||
static Action<object> cancellationCallback = CancellationCallback;
|
||||
|
||||
static TaskPool<WaitAsyncSource> pool;
|
||||
WaitAsyncSource ITaskPoolNode<WaitAsyncSource>.NextNode { get; set; }
|
||||
WaitAsyncSource nextNode;
|
||||
ref WaitAsyncSource ITaskPoolNode<WaitAsyncSource>.NextNode => ref nextNode;
|
||||
|
||||
static WaitAsyncSource()
|
||||
{
|
||||
@@ -404,7 +405,8 @@ namespace Cysharp.Threading.Tasks
|
||||
static Action<object> cancellationCallback = CancellationCallback;
|
||||
|
||||
static TaskPool<WaitAsyncSource> pool;
|
||||
WaitAsyncSource ITaskPoolNode<WaitAsyncSource>.NextNode { get; set; }
|
||||
WaitAsyncSource nextNode;
|
||||
ref WaitAsyncSource ITaskPoolNode<WaitAsyncSource>.NextNode => ref nextNode;
|
||||
|
||||
static WaitAsyncSource()
|
||||
{
|
||||
|
||||
@@ -30,10 +30,10 @@ namespace Cysharp.Threading.Tasks
|
||||
return ToCancellationToken(task);
|
||||
}
|
||||
|
||||
var cts = new CancellationTokenSource();
|
||||
var cts = CancellationTokenSource.CreateLinkedTokenSource(linkToken);
|
||||
ToCancellationTokenCore(task, cts).Forget();
|
||||
|
||||
return CancellationTokenSource.CreateLinkedTokenSource(linkToken).Token;
|
||||
return cts.Token;
|
||||
}
|
||||
|
||||
public static CancellationToken ToCancellationToken<T>(this UniTask<T> task)
|
||||
|
||||
@@ -87,7 +87,8 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
||||
TaskPool.RegisterSizeGetter(typeof(AsyncUniTaskVoid<TStateMachine>), () => pool.Size);
|
||||
}
|
||||
|
||||
public AsyncUniTaskVoid<TStateMachine> NextNode { get; set; }
|
||||
AsyncUniTaskVoid<TStateMachine> nextNode;
|
||||
public ref AsyncUniTaskVoid<TStateMachine> NextNode => ref nextNode;
|
||||
|
||||
public void Return()
|
||||
{
|
||||
@@ -157,7 +158,8 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
||||
result.stateMachine = stateMachine; // copy struct StateMachine(in release build).
|
||||
}
|
||||
|
||||
public AsyncUniTask<TStateMachine> NextNode { get; set; }
|
||||
AsyncUniTask<TStateMachine> nextNode;
|
||||
public ref AsyncUniTask<TStateMachine> NextNode => ref nextNode;
|
||||
|
||||
static AsyncUniTask()
|
||||
{
|
||||
@@ -279,7 +281,8 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
||||
result.stateMachine = stateMachine; // copy struct StateMachine(in release build).
|
||||
}
|
||||
|
||||
public AsyncUniTask<TStateMachine, T> NextNode { get; set; }
|
||||
AsyncUniTask<TStateMachine, T> nextNode;
|
||||
public ref AsyncUniTask<TStateMachine, T> NextNode => ref nextNode;
|
||||
|
||||
static AsyncUniTask()
|
||||
{
|
||||
|
||||
@@ -32,10 +32,24 @@ namespace Cysharp.Threading.Tasks
|
||||
return new UniTask(EnumeratorPromise.Create(enumerator, timing, cancellationToken, out var token), token);
|
||||
}
|
||||
|
||||
public static UniTask ToUniTask(this IEnumerator enumerator, MonoBehaviour coroutineRunner)
|
||||
{
|
||||
var source = AutoResetUniTaskCompletionSource.Create();
|
||||
coroutineRunner.StartCoroutine(Core(enumerator, coroutineRunner, source));
|
||||
return source.Task;
|
||||
}
|
||||
|
||||
static IEnumerator Core(IEnumerator inner, MonoBehaviour coroutineRunner, AutoResetUniTaskCompletionSource source)
|
||||
{
|
||||
yield return coroutineRunner.StartCoroutine(inner);
|
||||
source.TrySetResult();
|
||||
}
|
||||
|
||||
sealed class EnumeratorPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<EnumeratorPromise>
|
||||
{
|
||||
static TaskPool<EnumeratorPromise> pool;
|
||||
public EnumeratorPromise NextNode { get; set; }
|
||||
EnumeratorPromise nextNode;
|
||||
public ref EnumeratorPromise NextNode => ref nextNode;
|
||||
|
||||
static EnumeratorPromise()
|
||||
{
|
||||
@@ -44,6 +58,9 @@ namespace Cysharp.Threading.Tasks
|
||||
|
||||
IEnumerator innerEnumerator;
|
||||
CancellationToken cancellationToken;
|
||||
int initialFrame;
|
||||
bool loopRunning;
|
||||
bool calledGetResult;
|
||||
|
||||
UniTaskCompletionSourceCore<object> core;
|
||||
|
||||
@@ -66,10 +83,15 @@ namespace Cysharp.Threading.Tasks
|
||||
|
||||
result.innerEnumerator = ConsumeEnumerator(innerEnumerator);
|
||||
result.cancellationToken = cancellationToken;
|
||||
result.loopRunning = true;
|
||||
result.calledGetResult = false;
|
||||
result.initialFrame = -1;
|
||||
|
||||
PlayerLoopHelper.AddAction(timing, result);
|
||||
|
||||
token = result.core.Version;
|
||||
|
||||
result.MoveNext(); // run immediately.
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -77,11 +99,15 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
try
|
||||
{
|
||||
calledGetResult = true;
|
||||
core.GetResult(token);
|
||||
}
|
||||
finally
|
||||
{
|
||||
TryReturn();
|
||||
if (!loopRunning)
|
||||
{
|
||||
TryReturn();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,12 +128,38 @@ namespace Cysharp.Threading.Tasks
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
if (calledGetResult)
|
||||
{
|
||||
loopRunning = false;
|
||||
TryReturn();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (innerEnumerator == null) // invalid status, returned but loop running?
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
loopRunning = false;
|
||||
core.TrySetCanceled(cancellationToken);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (initialFrame == -1)
|
||||
{
|
||||
// Time can not touch in threadpool.
|
||||
if (PlayerLoopHelper.IsMainThread)
|
||||
{
|
||||
initialFrame = Time.frameCount;
|
||||
}
|
||||
}
|
||||
else if (initialFrame == Time.frameCount)
|
||||
{
|
||||
return true; // already executed in first frame, skip.
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (innerEnumerator.MoveNext())
|
||||
@@ -117,10 +169,12 @@ namespace Cysharp.Threading.Tasks
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
loopRunning = false;
|
||||
core.TrySetException(ex);
|
||||
return false;
|
||||
}
|
||||
|
||||
loopRunning = false;
|
||||
core.TrySetResult(null);
|
||||
return false;
|
||||
}
|
||||
@@ -145,11 +199,10 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
else if (current is CustomYieldInstruction)
|
||||
else if (current is CustomYieldInstruction cyi)
|
||||
{
|
||||
// WWW, WaitForSecondsRealtime
|
||||
var e2 = UnwrapWaitCustomYieldInstruction((CustomYieldInstruction)current);
|
||||
while (e2.MoveNext())
|
||||
while (cyi.keepWaiting)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
@@ -175,7 +228,7 @@ namespace Cysharp.Threading.Tasks
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return null;
|
||||
goto WARN;
|
||||
}
|
||||
}
|
||||
else if (current is IEnumerator e3)
|
||||
@@ -188,17 +241,14 @@ namespace Cysharp.Threading.Tasks
|
||||
}
|
||||
else
|
||||
{
|
||||
// WaitForEndOfFrame, WaitForFixedUpdate, others.
|
||||
yield return null;
|
||||
goto WARN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
|
||||
// WWW and others as CustomYieldInstruction.
|
||||
static IEnumerator UnwrapWaitCustomYieldInstruction(CustomYieldInstruction yieldInstruction)
|
||||
{
|
||||
while (yieldInstruction.keepWaiting)
|
||||
{
|
||||
WARN:
|
||||
// WaitForEndOfFrame, WaitForFixedUpdate, others.
|
||||
UnityEngine.Debug.LogWarning($"yield {current.GetType().Name} is not supported on await IEnumerator or IEnumerator.ToUniTask(), please use ToUniTask(MonoBehaviour coroutineRunner) instead.");
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
@@ -208,12 +258,12 @@ namespace Cysharp.Threading.Tasks
|
||||
static IEnumerator UnwrapWaitForSeconds(WaitForSeconds waitForSeconds)
|
||||
{
|
||||
var second = (float)waitForSeconds_Seconds.GetValue(waitForSeconds);
|
||||
var startTime = DateTimeOffset.UtcNow;
|
||||
var elapsed = 0.0f;
|
||||
while (true)
|
||||
{
|
||||
yield return null;
|
||||
|
||||
var elapsed = (DateTimeOffset.UtcNow - startTime).TotalSeconds;
|
||||
elapsed += Time.deltaTime;
|
||||
if (elapsed >= second)
|
||||
{
|
||||
break;
|
||||
@@ -230,5 +280,4 @@ namespace Cysharp.Threading.Tasks
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,7 +13,7 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
public static class AddressablesAsyncExtensions
|
||||
{
|
||||
#region AsyncOperationHandle
|
||||
#region AsyncOperationHandle
|
||||
|
||||
public static UniTask.Awaiter GetAwaiter(this AsyncOperationHandle handle)
|
||||
{
|
||||
@@ -31,7 +31,8 @@ namespace Cysharp.Threading.Tasks
|
||||
|
||||
if (!handle.IsValid())
|
||||
{
|
||||
throw new Exception("Attempting to use an invalid operation handle");
|
||||
// autoReleaseHandle:true handle is invalid(immediately internal handle == null) so return completed.
|
||||
return UniTask.CompletedTask;
|
||||
}
|
||||
|
||||
if (handle.IsDone)
|
||||
@@ -94,7 +95,8 @@ namespace Cysharp.Threading.Tasks
|
||||
sealed class AsyncOperationHandleConfiguredSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<AsyncOperationHandleConfiguredSource>
|
||||
{
|
||||
static TaskPool<AsyncOperationHandleConfiguredSource> pool;
|
||||
public AsyncOperationHandleConfiguredSource NextNode { get; set; }
|
||||
AsyncOperationHandleConfiguredSource nextNode;
|
||||
public ref AsyncOperationHandleConfiguredSource NextNode => ref nextNode;
|
||||
|
||||
static AsyncOperationHandleConfiguredSource()
|
||||
{
|
||||
@@ -221,9 +223,9 @@ namespace Cysharp.Threading.Tasks
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region AsyncOperationHandle_T
|
||||
#region AsyncOperationHandle_T
|
||||
|
||||
public static UniTask<T>.Awaiter GetAwaiter<T>(this AsyncOperationHandle<T> handle)
|
||||
{
|
||||
@@ -259,7 +261,8 @@ namespace Cysharp.Threading.Tasks
|
||||
sealed class AsyncOperationHandleConfiguredSource<T> : IUniTaskSource<T>, IPlayerLoopItem, ITaskPoolNode<AsyncOperationHandleConfiguredSource<T>>
|
||||
{
|
||||
static TaskPool<AsyncOperationHandleConfiguredSource<T>> pool;
|
||||
public AsyncOperationHandleConfiguredSource<T> NextNode { get; set; }
|
||||
AsyncOperationHandleConfiguredSource<T> nextNode;
|
||||
public ref AsyncOperationHandleConfiguredSource<T> NextNode => ref nextNode;
|
||||
|
||||
static AsyncOperationHandleConfiguredSource()
|
||||
{
|
||||
@@ -391,7 +394,7 @@ namespace Cysharp.Threading.Tasks
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ using System.Threading;
|
||||
|
||||
namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
// The idea of TweenCancelBehaviour is borrowed from https://www.shibuya24.info/entry/dotween_async_await
|
||||
public enum TweenCancelBehaviour
|
||||
{
|
||||
Kill,
|
||||
@@ -29,6 +28,16 @@ namespace Cysharp.Threading.Tasks
|
||||
|
||||
public static class DOTweenAsyncExtensions
|
||||
{
|
||||
enum CallbackType
|
||||
{
|
||||
Kill,
|
||||
Complete,
|
||||
Pause,
|
||||
Play,
|
||||
Rewind,
|
||||
StepComplete
|
||||
}
|
||||
|
||||
public static TweenAwaiter GetAwaiter(this Tween tween)
|
||||
{
|
||||
return new TweenAwaiter(tween);
|
||||
@@ -39,7 +48,7 @@ namespace Cysharp.Threading.Tasks
|
||||
Error.ThrowArgumentNullException(tween, nameof(tween));
|
||||
|
||||
if (!tween.IsActive()) return UniTask.CompletedTask;
|
||||
return new UniTask(TweenConfiguredSource.Create(tween, TweenCancelBehaviour.Kill, cancellationToken, out var token), token);
|
||||
return new UniTask(TweenConfiguredSource.Create(tween, TweenCancelBehaviour.Kill, cancellationToken, CallbackType.Kill, out var token), token);
|
||||
}
|
||||
|
||||
public static UniTask ToUniTask(this Tween tween, TweenCancelBehaviour tweenCancelBehaviour = TweenCancelBehaviour.Kill, CancellationToken cancellationToken = default)
|
||||
@@ -47,7 +56,47 @@ namespace Cysharp.Threading.Tasks
|
||||
Error.ThrowArgumentNullException(tween, nameof(tween));
|
||||
|
||||
if (!tween.IsActive()) return UniTask.CompletedTask;
|
||||
return new UniTask(TweenConfiguredSource.Create(tween, tweenCancelBehaviour, cancellationToken, out var token), token);
|
||||
return new UniTask(TweenConfiguredSource.Create(tween, tweenCancelBehaviour, cancellationToken, CallbackType.Kill, out var token), token);
|
||||
}
|
||||
|
||||
public static UniTask AwaitForComplete(this Tween tween, TweenCancelBehaviour tweenCancelBehaviour = TweenCancelBehaviour.Kill, CancellationToken cancellationToken = default)
|
||||
{
|
||||
Error.ThrowArgumentNullException(tween, nameof(tween));
|
||||
|
||||
if (!tween.IsActive()) return UniTask.CompletedTask;
|
||||
return new UniTask(TweenConfiguredSource.Create(tween, tweenCancelBehaviour, cancellationToken, CallbackType.Complete, out var token), token);
|
||||
}
|
||||
|
||||
public static UniTask AwaitForPause(this Tween tween, TweenCancelBehaviour tweenCancelBehaviour = TweenCancelBehaviour.Kill, CancellationToken cancellationToken = default)
|
||||
{
|
||||
Error.ThrowArgumentNullException(tween, nameof(tween));
|
||||
|
||||
if (!tween.IsActive()) return UniTask.CompletedTask;
|
||||
return new UniTask(TweenConfiguredSource.Create(tween, tweenCancelBehaviour, cancellationToken, CallbackType.Pause, out var token), token);
|
||||
}
|
||||
|
||||
public static UniTask AwaitForPlay(this Tween tween, TweenCancelBehaviour tweenCancelBehaviour = TweenCancelBehaviour.Kill, CancellationToken cancellationToken = default)
|
||||
{
|
||||
Error.ThrowArgumentNullException(tween, nameof(tween));
|
||||
|
||||
if (!tween.IsActive()) return UniTask.CompletedTask;
|
||||
return new UniTask(TweenConfiguredSource.Create(tween, tweenCancelBehaviour, cancellationToken, CallbackType.Play, out var token), token);
|
||||
}
|
||||
|
||||
public static UniTask AwaitForRewind(this Tween tween, TweenCancelBehaviour tweenCancelBehaviour = TweenCancelBehaviour.Kill, CancellationToken cancellationToken = default)
|
||||
{
|
||||
Error.ThrowArgumentNullException(tween, nameof(tween));
|
||||
|
||||
if (!tween.IsActive()) return UniTask.CompletedTask;
|
||||
return new UniTask(TweenConfiguredSource.Create(tween, tweenCancelBehaviour, cancellationToken, CallbackType.Rewind, out var token), token);
|
||||
}
|
||||
|
||||
public static UniTask AwaitForStepComplete(this Tween tween, TweenCancelBehaviour tweenCancelBehaviour = TweenCancelBehaviour.Kill, CancellationToken cancellationToken = default)
|
||||
{
|
||||
Error.ThrowArgumentNullException(tween, nameof(tween));
|
||||
|
||||
if (!tween.IsActive()) return UniTask.CompletedTask;
|
||||
return new UniTask(TweenConfiguredSource.Create(tween, tweenCancelBehaviour, cancellationToken, CallbackType.StepComplete, out var token), token);
|
||||
}
|
||||
|
||||
public struct TweenAwaiter : ICriticalNotifyCompletion
|
||||
@@ -86,7 +135,8 @@ namespace Cysharp.Threading.Tasks
|
||||
sealed class TweenConfiguredSource : IUniTaskSource, ITaskPoolNode<TweenConfiguredSource>
|
||||
{
|
||||
static TaskPool<TweenConfiguredSource> pool;
|
||||
public TweenConfiguredSource NextNode { get; set; }
|
||||
TweenConfiguredSource nextNode;
|
||||
public ref TweenConfiguredSource NextNode => ref nextNode;
|
||||
|
||||
static TweenConfiguredSource()
|
||||
{
|
||||
@@ -95,12 +145,13 @@ namespace Cysharp.Threading.Tasks
|
||||
|
||||
static readonly TweenCallback EmptyTweenCallback = () => { };
|
||||
|
||||
readonly TweenCallback onKillDelegate;
|
||||
readonly TweenCallback onCompleteCallbackDelegate;
|
||||
readonly TweenCallback onUpdateDelegate;
|
||||
|
||||
Tween tween;
|
||||
TweenCancelBehaviour cancelBehaviour;
|
||||
CancellationToken cancellationToken;
|
||||
CallbackType callbackType;
|
||||
bool canceled;
|
||||
|
||||
TweenCallback originalUpdateAction;
|
||||
@@ -108,11 +159,11 @@ namespace Cysharp.Threading.Tasks
|
||||
|
||||
TweenConfiguredSource()
|
||||
{
|
||||
onKillDelegate = OnKill;
|
||||
onCompleteCallbackDelegate = OnCompleteCallbackDelegate;
|
||||
onUpdateDelegate = OnUpdate;
|
||||
}
|
||||
|
||||
public static IUniTaskSource Create(Tween tween, TweenCancelBehaviour cancelBehaviour, CancellationToken cancellationToken, out short token)
|
||||
public static IUniTaskSource Create(Tween tween, TweenCancelBehaviour cancelBehaviour, CancellationToken cancellationToken, CallbackType callbackType, out short token)
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
@@ -128,6 +179,7 @@ namespace Cysharp.Threading.Tasks
|
||||
result.tween = tween;
|
||||
result.cancelBehaviour = cancelBehaviour;
|
||||
result.cancellationToken = cancellationToken;
|
||||
result.callbackType = callbackType;
|
||||
|
||||
result.originalUpdateAction = tween.onUpdate;
|
||||
result.canceled = false;
|
||||
@@ -138,7 +190,30 @@ namespace Cysharp.Threading.Tasks
|
||||
}
|
||||
|
||||
tween.onUpdate = result.onUpdateDelegate;
|
||||
tween.onKill = result.onKillDelegate;
|
||||
|
||||
switch (callbackType)
|
||||
{
|
||||
case CallbackType.Kill:
|
||||
tween.onKill = result.onCompleteCallbackDelegate;
|
||||
break;
|
||||
case CallbackType.Complete:
|
||||
tween.onComplete = result.onCompleteCallbackDelegate;
|
||||
break;
|
||||
case CallbackType.Pause:
|
||||
tween.onPause = result.onCompleteCallbackDelegate;
|
||||
break;
|
||||
case CallbackType.Play:
|
||||
tween.onPlay = result.onCompleteCallbackDelegate;
|
||||
break;
|
||||
case CallbackType.Rewind:
|
||||
tween.onRewind = result.onCompleteCallbackDelegate;
|
||||
break;
|
||||
case CallbackType.StepComplete:
|
||||
tween.onStepComplete = result.onCompleteCallbackDelegate;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
TaskTracker.TrackActiveTask(result, 3);
|
||||
|
||||
@@ -146,7 +221,7 @@ namespace Cysharp.Threading.Tasks
|
||||
return result;
|
||||
}
|
||||
|
||||
void OnKill()
|
||||
void OnCompleteCallbackDelegate()
|
||||
{
|
||||
if (canceled)
|
||||
{
|
||||
@@ -199,7 +274,31 @@ namespace Cysharp.Threading.Tasks
|
||||
this.tween.Complete(true);
|
||||
break;
|
||||
case TweenCancelBehaviour.CancelAwait:
|
||||
this.tween.onKill = EmptyTweenCallback; // replace to empty(avoid callback after Canceled(instance is returned to pool.)
|
||||
// replace to empty(avoid callback after Canceled(instance is returned to pool.)
|
||||
switch (callbackType)
|
||||
{
|
||||
case CallbackType.Kill:
|
||||
tween.onKill = EmptyTweenCallback;
|
||||
break;
|
||||
case CallbackType.Complete:
|
||||
tween.onComplete = EmptyTweenCallback;
|
||||
break;
|
||||
case CallbackType.Pause:
|
||||
tween.onPause = EmptyTweenCallback;
|
||||
break;
|
||||
case CallbackType.Play:
|
||||
tween.onPlay = EmptyTweenCallback;
|
||||
break;
|
||||
case CallbackType.Rewind:
|
||||
tween.onRewind = EmptyTweenCallback;
|
||||
break;
|
||||
case CallbackType.StepComplete:
|
||||
tween.onStepComplete = EmptyTweenCallback;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
this.core.TrySetCanceled(this.cancellationToken);
|
||||
break;
|
||||
}
|
||||
@@ -272,7 +371,31 @@ namespace Cysharp.Threading.Tasks
|
||||
TaskTracker.RemoveTracking(this);
|
||||
core.Reset();
|
||||
tween.onUpdate = originalUpdateAction;
|
||||
tween.onKill = null;
|
||||
|
||||
switch (callbackType)
|
||||
{
|
||||
case CallbackType.Kill:
|
||||
tween.onKill = null;
|
||||
break;
|
||||
case CallbackType.Complete:
|
||||
tween.onComplete = null;
|
||||
break;
|
||||
case CallbackType.Pause:
|
||||
tween.onPause = null;
|
||||
break;
|
||||
case CallbackType.Play:
|
||||
tween.onPlay = null;
|
||||
break;
|
||||
case CallbackType.Rewind:
|
||||
tween.onRewind = null;
|
||||
break;
|
||||
case CallbackType.StepComplete:
|
||||
tween.onStepComplete = null;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
tween = default;
|
||||
cancellationToken = default;
|
||||
originalUpdateAction = default;
|
||||
|
||||
@@ -9,6 +9,7 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
public static partial class TextMeshProAsyncExtensions
|
||||
{
|
||||
// <string> -> Text
|
||||
public static void BindTo(this IUniTaskAsyncEnumerable<string> source, TMP_Text text, bool rebindOnError = true)
|
||||
{
|
||||
BindToCore(source, text, text.GetCancellationTokenOnDestroy(), rebindOnError).Forget();
|
||||
@@ -62,6 +63,67 @@ namespace Cysharp.Threading.Tasks
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// <T> -> Text
|
||||
|
||||
public static void BindTo<T>(this IUniTaskAsyncEnumerable<T> source, TMP_Text text, bool rebindOnError = true)
|
||||
{
|
||||
BindToCore(source, text, text.GetCancellationTokenOnDestroy(), rebindOnError).Forget();
|
||||
}
|
||||
|
||||
public static void BindTo<T>(this IUniTaskAsyncEnumerable<T> source, TMP_Text text, CancellationToken cancellationToken, bool rebindOnError = true)
|
||||
{
|
||||
BindToCore(source, text, cancellationToken, rebindOnError).Forget();
|
||||
}
|
||||
|
||||
public static void BindTo<T>(this AsyncReactiveProperty<T> source, TMP_Text text, bool rebindOnError = true)
|
||||
{
|
||||
BindToCore(source, text, text.GetCancellationTokenOnDestroy(), rebindOnError).Forget();
|
||||
}
|
||||
|
||||
static async UniTaskVoid BindToCore<T>(IUniTaskAsyncEnumerable<T> source, TMP_Text text, CancellationToken cancellationToken, bool rebindOnError)
|
||||
{
|
||||
var repeat = false;
|
||||
BIND_AGAIN:
|
||||
var e = source.GetAsyncEnumerator(cancellationToken);
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
bool moveNext;
|
||||
try
|
||||
{
|
||||
moveNext = await e.MoveNextAsync();
|
||||
repeat = false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (ex is OperationCanceledException) return;
|
||||
|
||||
if (rebindOnError && !repeat)
|
||||
{
|
||||
repeat = true;
|
||||
goto BIND_AGAIN;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
if (!moveNext) return;
|
||||
|
||||
text.text = e.Current.ToString();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (e != null)
|
||||
{
|
||||
await e.DisposeAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -70,13 +70,17 @@ namespace Cysharp.Threading.Tasks.Internal
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
public int Clear()
|
||||
{
|
||||
var rest = actionListCount + waitingListCount;
|
||||
|
||||
actionListCount = 0;
|
||||
actionList = new Action[InitialSize];
|
||||
|
||||
waitingListCount = 0;
|
||||
waitingList = new Action[InitialSize];
|
||||
|
||||
return rest;
|
||||
}
|
||||
|
||||
// delegate entrypoint.
|
||||
@@ -170,9 +174,9 @@ namespace Cysharp.Threading.Tasks.Internal
|
||||
|
||||
for (int i = 0; i < actionListCount; i++)
|
||||
{
|
||||
|
||||
var action = actionList[i];
|
||||
actionList[i] = null;
|
||||
|
||||
try
|
||||
{
|
||||
action();
|
||||
|
||||
@@ -48,14 +48,24 @@ namespace Cysharp.Threading.Tasks.Internal
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
public int Clear()
|
||||
{
|
||||
lock (arrayLock)
|
||||
{
|
||||
var rest = 0;
|
||||
|
||||
for (var index = 0; index < loopItems.Length; index++)
|
||||
{
|
||||
if (loopItems[index] != null)
|
||||
{
|
||||
rest++;
|
||||
}
|
||||
|
||||
loopItems[index] = null;
|
||||
}
|
||||
|
||||
tail = 0;
|
||||
return rest;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,7 +153,6 @@ namespace Cysharp.Threading.Tasks.Internal
|
||||
{
|
||||
var j = tail - 1;
|
||||
|
||||
// eliminate array-bound check for i
|
||||
for (int i = 0; i < loopItems.Length; i++)
|
||||
{
|
||||
var action = loopItems[i];
|
||||
|
||||
@@ -7,7 +7,8 @@ namespace Cysharp.Threading.Tasks.Internal
|
||||
{
|
||||
static TaskPool<PooledDelegate<T>> pool;
|
||||
|
||||
public PooledDelegate<T> NextNode { get; set; }
|
||||
PooledDelegate<T> nextNode;
|
||||
public ref PooledDelegate<T> NextNode => ref nextNode;
|
||||
|
||||
static PooledDelegate()
|
||||
{
|
||||
|
||||
@@ -63,6 +63,42 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
Subscribes.SubscribeCore(source, action, Subscribes.NopError, Subscribes.NopCompleted, cancellationToken).Forget();
|
||||
}
|
||||
|
||||
public static IDisposable SubscribeAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask> onNext)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
||||
|
||||
var cts = new CancellationTokenDisposable();
|
||||
Subscribes.SubscribeAwaitCore(source, onNext, Subscribes.NopError, Subscribes.NopCompleted, cts.Token).Forget();
|
||||
return cts;
|
||||
}
|
||||
|
||||
public static void SubscribeAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask> onNext, CancellationToken cancellationToken)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
||||
|
||||
Subscribes.SubscribeAwaitCore(source, onNext, Subscribes.NopError, Subscribes.NopCompleted, cancellationToken).Forget();
|
||||
}
|
||||
|
||||
public static IDisposable SubscribeAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask> onNext)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
||||
|
||||
var cts = new CancellationTokenDisposable();
|
||||
Subscribes.SubscribeAwaitCore(source, onNext, Subscribes.NopError, Subscribes.NopCompleted, cts.Token).Forget();
|
||||
return cts;
|
||||
}
|
||||
|
||||
public static void SubscribeAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask> onNext, CancellationToken cancellationToken)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
||||
|
||||
Subscribes.SubscribeAwaitCore(source, onNext, Subscribes.NopError, Subscribes.NopCompleted, cancellationToken).Forget();
|
||||
}
|
||||
|
||||
// OnNext, OnError
|
||||
|
||||
public static IDisposable Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Action<TSource> onNext, Action<Exception> onError)
|
||||
@@ -105,6 +141,46 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
Subscribes.SubscribeCore(source, onNext, onError, Subscribes.NopCompleted, cancellationToken).Forget();
|
||||
}
|
||||
|
||||
public static IDisposable SubscribeAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask> onNext, Action<Exception> onError)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
||||
Error.ThrowArgumentNullException(onError, nameof(onError));
|
||||
|
||||
var cts = new CancellationTokenDisposable();
|
||||
Subscribes.SubscribeAwaitCore(source, onNext, onError, Subscribes.NopCompleted, cts.Token).Forget();
|
||||
return cts;
|
||||
}
|
||||
|
||||
public static void SubscribeAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask> onNext, Action<Exception> onError, CancellationToken cancellationToken)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
||||
Error.ThrowArgumentNullException(onError, nameof(onError));
|
||||
|
||||
Subscribes.SubscribeAwaitCore(source, onNext, onError, Subscribes.NopCompleted, cancellationToken).Forget();
|
||||
}
|
||||
|
||||
public static IDisposable SubscribeAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask> onNext, Action<Exception> onError)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
||||
Error.ThrowArgumentNullException(onError, nameof(onError));
|
||||
|
||||
var cts = new CancellationTokenDisposable();
|
||||
Subscribes.SubscribeAwaitCore(source, onNext, onError, Subscribes.NopCompleted, cts.Token).Forget();
|
||||
return cts;
|
||||
}
|
||||
|
||||
public static void SubscribeAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask> onNext, Action<Exception> onError, CancellationToken cancellationToken)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
||||
Error.ThrowArgumentNullException(onError, nameof(onError));
|
||||
|
||||
Subscribes.SubscribeAwaitCore(source, onNext, onError, Subscribes.NopCompleted, cancellationToken).Forget();
|
||||
}
|
||||
|
||||
// OnNext, OnCompleted
|
||||
|
||||
public static IDisposable Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Action<TSource> onNext, Action onCompleted)
|
||||
@@ -147,6 +223,46 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
Subscribes.SubscribeCore(source, onNext, Subscribes.NopError, onCompleted, cancellationToken).Forget();
|
||||
}
|
||||
|
||||
public static IDisposable SubscribeAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask> onNext, Action onCompleted)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
||||
Error.ThrowArgumentNullException(onCompleted, nameof(onCompleted));
|
||||
|
||||
var cts = new CancellationTokenDisposable();
|
||||
Subscribes.SubscribeAwaitCore(source, onNext, Subscribes.NopError, onCompleted, cts.Token).Forget();
|
||||
return cts;
|
||||
}
|
||||
|
||||
public static void SubscribeAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask> onNext, Action onCompleted, CancellationToken cancellationToken)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
||||
Error.ThrowArgumentNullException(onCompleted, nameof(onCompleted));
|
||||
|
||||
Subscribes.SubscribeAwaitCore(source, onNext, Subscribes.NopError, onCompleted, cancellationToken).Forget();
|
||||
}
|
||||
|
||||
public static IDisposable SubscribeAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask> onNext, Action onCompleted)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
||||
Error.ThrowArgumentNullException(onCompleted, nameof(onCompleted));
|
||||
|
||||
var cts = new CancellationTokenDisposable();
|
||||
Subscribes.SubscribeAwaitCore(source, onNext, Subscribes.NopError, onCompleted, cts.Token).Forget();
|
||||
return cts;
|
||||
}
|
||||
|
||||
public static void SubscribeAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask> onNext, Action onCompleted, CancellationToken cancellationToken)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
||||
Error.ThrowArgumentNullException(onCompleted, nameof(onCompleted));
|
||||
|
||||
Subscribes.SubscribeAwaitCore(source, onNext, Subscribes.NopError, onCompleted, cancellationToken).Forget();
|
||||
}
|
||||
|
||||
// IObserver
|
||||
|
||||
public static IDisposable Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, IObserver<TSource> observer)
|
||||
@@ -195,7 +311,14 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
{
|
||||
while (await e.MoveNextAsync())
|
||||
{
|
||||
onNext(e.Current);
|
||||
try
|
||||
{
|
||||
onNext(e.Current);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||
}
|
||||
}
|
||||
onCompleted();
|
||||
}
|
||||
@@ -227,7 +350,14 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
{
|
||||
while (await e.MoveNextAsync())
|
||||
{
|
||||
onNext(e.Current).Forget();
|
||||
try
|
||||
{
|
||||
onNext(e.Current).Forget();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||
}
|
||||
}
|
||||
onCompleted();
|
||||
}
|
||||
@@ -259,7 +389,14 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
{
|
||||
while (await e.MoveNextAsync())
|
||||
{
|
||||
onNext(e.Current, cancellationToken).Forget();
|
||||
try
|
||||
{
|
||||
onNext(e.Current, cancellationToken).Forget();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||
}
|
||||
}
|
||||
onCompleted();
|
||||
}
|
||||
@@ -291,7 +428,14 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
{
|
||||
while (await e.MoveNextAsync())
|
||||
{
|
||||
observer.OnNext(e.Current);
|
||||
try
|
||||
{
|
||||
observer.OnNext(e.Current);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||
}
|
||||
}
|
||||
observer.OnCompleted();
|
||||
}
|
||||
@@ -309,5 +453,84 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static async UniTaskVoid SubscribeAwaitCore<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask> onNext, Action<Exception> onError, Action onCompleted, CancellationToken cancellationToken)
|
||||
{
|
||||
var e = source.GetAsyncEnumerator(cancellationToken);
|
||||
try
|
||||
{
|
||||
while (await e.MoveNextAsync())
|
||||
{
|
||||
try
|
||||
{
|
||||
await onNext(e.Current);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||
}
|
||||
}
|
||||
onCompleted();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (onError == NopError)
|
||||
{
|
||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ex is OperationCanceledException) return;
|
||||
|
||||
onError(ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (e != null)
|
||||
{
|
||||
await e.DisposeAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static async UniTaskVoid SubscribeAwaitCore<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask> onNext, Action<Exception> onError, Action onCompleted, CancellationToken cancellationToken)
|
||||
{
|
||||
var e = source.GetAsyncEnumerator(cancellationToken);
|
||||
try
|
||||
{
|
||||
while (await e.MoveNextAsync())
|
||||
{
|
||||
try
|
||||
{
|
||||
await onNext(e.Current, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||
}
|
||||
}
|
||||
onCompleted();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (onError == NopError)
|
||||
{
|
||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ex is OperationCanceledException) return;
|
||||
|
||||
onError(ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (e != null)
|
||||
{
|
||||
await e.DisposeAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -19,8 +19,6 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
{
|
||||
internal static async UniTask<TSource[]> ToArrayAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
|
||||
{
|
||||
// UnityEngine.Debug.Log("Called ToArray");
|
||||
|
||||
var pool = ArrayPool<TSource>.Shared;
|
||||
var array = pool.Rent(16);
|
||||
|
||||
|
||||
@@ -208,7 +208,6 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
UnityEngine.Debug.Log("TRY_RESULT:" + target.TryGetTarget(out var _));
|
||||
if (disposed || cancellationToken.IsCancellationRequested || !target.TryGetTarget(out var t))
|
||||
{
|
||||
completionSource.TrySetResult(false);
|
||||
|
||||
@@ -110,27 +110,30 @@ namespace Cysharp.Threading.Tasks
|
||||
#if UNITY_EDITOR
|
||||
EditorApplication.playModeStateChanged += (state) =>
|
||||
{
|
||||
if (state == PlayModeStateChange.EnteredEditMode || state == PlayModeStateChange.EnteredPlayMode)
|
||||
if (state == PlayModeStateChange.EnteredEditMode || state == PlayModeStateChange.ExitingEditMode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// run rest action before clear.
|
||||
if (runner != null)
|
||||
{
|
||||
runner.Run();
|
||||
runner.Clear();
|
||||
}
|
||||
if (lastRunner != null)
|
||||
{
|
||||
lastRunner.Run();
|
||||
lastRunner.Clear();
|
||||
}
|
||||
|
||||
if (runner != null)
|
||||
{
|
||||
runner.Clear();
|
||||
}
|
||||
if (lastRunner != null)
|
||||
{
|
||||
lastRunner.Clear();
|
||||
}
|
||||
|
||||
if (cq != null)
|
||||
{
|
||||
cq.Clear();
|
||||
}
|
||||
if (lastCq != null)
|
||||
{
|
||||
lastCq.Clear();
|
||||
if (cq != null)
|
||||
{
|
||||
cq.Run();
|
||||
cq.Clear();
|
||||
}
|
||||
if (lastCq != null)
|
||||
{
|
||||
lastCq.Run();
|
||||
lastCq.Clear();
|
||||
}
|
||||
}
|
||||
};
|
||||
#endif
|
||||
@@ -288,7 +291,7 @@ namespace Cysharp.Threading.Tasks
|
||||
// Initialization
|
||||
copyList[0].subSystemList = InsertRunner(copyList[0], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldInitialization), yielders[0] = new ContinuationQueue(PlayerLoopTiming.Initialization),
|
||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldInitialization), yielders[1] = new ContinuationQueue(PlayerLoopTiming.LastInitialization),
|
||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerInitialization), runners[1] = new PlayerLoopRunner(PlayerLoopTiming.Initialization),
|
||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerInitialization), runners[0] = new PlayerLoopRunner(PlayerLoopTiming.Initialization),
|
||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastInitialization), runners[1] = new PlayerLoopRunner(PlayerLoopTiming.LastInitialization));
|
||||
// EarlyUpdate
|
||||
copyList[1].subSystemList = InsertRunner(copyList[1], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldEarlyUpdate), yielders[2] = new ContinuationQueue(PlayerLoopTiming.EarlyUpdate),
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace Cysharp.Threading.Tasks
|
||||
|
||||
public interface ITaskPoolNode<T>
|
||||
{
|
||||
T NextNode { get; set; }
|
||||
ref T NextNode { get; }
|
||||
}
|
||||
|
||||
// mutable struct, don't mark readonly.
|
||||
@@ -77,8 +77,9 @@ namespace Cysharp.Threading.Tasks
|
||||
var v = root;
|
||||
if (!(v is null))
|
||||
{
|
||||
root = v.NextNode;
|
||||
v.NextNode = null;
|
||||
ref var nextNode = ref v.NextNode;
|
||||
root = nextNode;
|
||||
nextNode = null;
|
||||
size--;
|
||||
result = v;
|
||||
Volatile.Write(ref gate, 0);
|
||||
|
||||
@@ -1541,6 +1541,7 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||
#endregion
|
||||
|
||||
#region MouseDown
|
||||
#if !(UNITY_IPHONE || UNITY_ANDROID || UNITY_METRO)
|
||||
|
||||
public interface IAsyncOnMouseDownHandler
|
||||
{
|
||||
@@ -1597,9 +1598,11 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||
return ((IAsyncOnMouseDownHandler)new AsyncTriggerHandler<AsyncUnit>(this, cancellationToken, true)).OnMouseDownAsync();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endregion
|
||||
|
||||
#region MouseDrag
|
||||
#if !(UNITY_IPHONE || UNITY_ANDROID || UNITY_METRO)
|
||||
|
||||
public interface IAsyncOnMouseDragHandler
|
||||
{
|
||||
@@ -1656,9 +1659,11 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||
return ((IAsyncOnMouseDragHandler)new AsyncTriggerHandler<AsyncUnit>(this, cancellationToken, true)).OnMouseDragAsync();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endregion
|
||||
|
||||
#region MouseEnter
|
||||
#if !(UNITY_IPHONE || UNITY_ANDROID || UNITY_METRO)
|
||||
|
||||
public interface IAsyncOnMouseEnterHandler
|
||||
{
|
||||
@@ -1715,9 +1720,11 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||
return ((IAsyncOnMouseEnterHandler)new AsyncTriggerHandler<AsyncUnit>(this, cancellationToken, true)).OnMouseEnterAsync();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endregion
|
||||
|
||||
#region MouseExit
|
||||
#if !(UNITY_IPHONE || UNITY_ANDROID || UNITY_METRO)
|
||||
|
||||
public interface IAsyncOnMouseExitHandler
|
||||
{
|
||||
@@ -1774,9 +1781,11 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||
return ((IAsyncOnMouseExitHandler)new AsyncTriggerHandler<AsyncUnit>(this, cancellationToken, true)).OnMouseExitAsync();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endregion
|
||||
|
||||
#region MouseOver
|
||||
#if !(UNITY_IPHONE || UNITY_ANDROID || UNITY_METRO)
|
||||
|
||||
public interface IAsyncOnMouseOverHandler
|
||||
{
|
||||
@@ -1833,9 +1842,11 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||
return ((IAsyncOnMouseOverHandler)new AsyncTriggerHandler<AsyncUnit>(this, cancellationToken, true)).OnMouseOverAsync();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endregion
|
||||
|
||||
#region MouseUp
|
||||
#if !(UNITY_IPHONE || UNITY_ANDROID || UNITY_METRO)
|
||||
|
||||
public interface IAsyncOnMouseUpHandler
|
||||
{
|
||||
@@ -1892,9 +1903,11 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||
return ((IAsyncOnMouseUpHandler)new AsyncTriggerHandler<AsyncUnit>(this, cancellationToken, true)).OnMouseUpAsync();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endregion
|
||||
|
||||
#region MouseUpAsButton
|
||||
#if !(UNITY_IPHONE || UNITY_ANDROID || UNITY_METRO)
|
||||
|
||||
public interface IAsyncOnMouseUpAsButtonHandler
|
||||
{
|
||||
@@ -1951,6 +1964,7 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||
return ((IAsyncOnMouseUpAsButtonHandler)new AsyncTriggerHandler<AsyncUnit>(this, cancellationToken, true)).OnMouseUpAsButtonAsync();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endregion
|
||||
|
||||
#region ParticleCollision
|
||||
|
||||
@@ -25,13 +25,7 @@
|
||||
("Update", "Update", "AsyncUnit", null, empty),
|
||||
("FixedUpdate", "FixedUpdate", "AsyncUnit", null, empty),
|
||||
("LateUpdate", "LateUpdate", "AsyncUnit", null, empty),
|
||||
("MouseDown", "OnMouseDown", "AsyncUnit", null, empty),
|
||||
("MouseDrag", "OnMouseDrag", "AsyncUnit", null, empty),
|
||||
("MouseEnter", "OnMouseEnter", "AsyncUnit", null, empty),
|
||||
("MouseExit", "OnMouseExit", "AsyncUnit", null, empty),
|
||||
("MouseOver", "OnMouseOver", "AsyncUnit", null, empty),
|
||||
("MouseUp", "OnMouseUp", "AsyncUnit", null, empty),
|
||||
("MouseUpAsButton", "OnMouseUpAsButton", "AsyncUnit", null, empty),
|
||||
|
||||
("ParticleCollision", "OnParticleCollision", "GameObject", null, new []{ ("GameObject", "other") }),
|
||||
("RectTransformDimensionsChange", "OnRectTransformDimensionsChange", "AsyncUnit", null, empty),
|
||||
("RectTransformRemoved", "OnRectTransformRemoved", "AsyncUnit", null, empty),
|
||||
@@ -47,6 +41,15 @@
|
||||
("BecameInvisible", "OnBecameInvisible", "AsyncUnit", null, empty),
|
||||
("BecameVisible", "OnBecameVisible", "AsyncUnit", null, empty),
|
||||
|
||||
// Mouse... #if !(UNITY_IPHONE || UNITY_ANDROID || UNITY_METRO)
|
||||
("MouseDown", "OnMouseDown", "AsyncUnit", null, empty),
|
||||
("MouseDrag", "OnMouseDrag", "AsyncUnit", null, empty),
|
||||
("MouseEnter", "OnMouseEnter", "AsyncUnit", null, empty),
|
||||
("MouseExit", "OnMouseExit", "AsyncUnit", null, empty),
|
||||
("MouseOver", "OnMouseOver", "AsyncUnit", null, empty),
|
||||
("MouseUp", "OnMouseUp", "AsyncUnit", null, empty),
|
||||
("MouseUpAsButton", "OnMouseUpAsButton", "AsyncUnit", null, empty),
|
||||
|
||||
// new in v2
|
||||
("ApplicationFocus", "OnApplicationFocus", "bool", null, new []{("bool", "hasFocus") }),
|
||||
("ApplicationPause", "OnApplicationPause", "bool", null, new []{("bool", "pauseStatus") }),
|
||||
@@ -104,6 +107,7 @@
|
||||
Func<(string argType, string argName)[], string> BuildResultParameter = x => x.Length == 0 ? "AsyncUnit.Default" : "(" + string.Join(", ", x.Select(y => y.argName)) + ")";
|
||||
|
||||
Func<string, bool> Is2019_3 = x => x == "ParticleUpdateJobScheduled";
|
||||
Func<string, bool> IsMouseTrigger = x => x.StartsWith("Mouse");
|
||||
#>
|
||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||
|
||||
@@ -117,6 +121,9 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||
#region <#= t.triggerName #>
|
||||
<# if(Is2019_3(t.triggerName)) { #>
|
||||
#if UNITY_2019_3_OR_NEWER
|
||||
<# } #>
|
||||
<# if(IsMouseTrigger(t.triggerName)) { #>
|
||||
#if !(UNITY_IPHONE || UNITY_ANDROID || UNITY_METRO)
|
||||
<# } #>
|
||||
|
||||
public interface <#= ToInterfaceName(t.methodName) #>
|
||||
@@ -174,7 +181,7 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||
return ((<#= ToInterfaceName(t.methodName) #>)new AsyncTriggerHandler<<#= t.returnType #>>(this, cancellationToken, true)).<#= t.methodName #>Async();
|
||||
}
|
||||
}
|
||||
<# if(Is2019_3(t.triggerName)) { #>
|
||||
<# if(Is2019_3(t.triggerName) || IsMouseTrigger(t.triggerName)) { #>
|
||||
#endif
|
||||
<# } #>
|
||||
#endregion
|
||||
|
||||
@@ -127,7 +127,8 @@ namespace Cysharp.Threading.Tasks
|
||||
sealed class YieldPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<YieldPromise>
|
||||
{
|
||||
static TaskPool<YieldPromise> pool;
|
||||
public YieldPromise NextNode { get; set; }
|
||||
YieldPromise nextNode;
|
||||
public ref YieldPromise NextNode => ref nextNode;
|
||||
|
||||
static YieldPromise()
|
||||
{
|
||||
@@ -215,7 +216,8 @@ namespace Cysharp.Threading.Tasks
|
||||
sealed class NextFramePromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<NextFramePromise>
|
||||
{
|
||||
static TaskPool<NextFramePromise> pool;
|
||||
public NextFramePromise NextNode { get; set; }
|
||||
NextFramePromise nextNode;
|
||||
public ref NextFramePromise NextNode => ref nextNode;
|
||||
|
||||
static NextFramePromise()
|
||||
{
|
||||
@@ -309,7 +311,8 @@ namespace Cysharp.Threading.Tasks
|
||||
sealed class DelayFramePromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<DelayFramePromise>
|
||||
{
|
||||
static TaskPool<DelayFramePromise> pool;
|
||||
public DelayFramePromise NextNode { get; set; }
|
||||
DelayFramePromise nextNode;
|
||||
public ref DelayFramePromise NextNode => ref nextNode;
|
||||
|
||||
static DelayFramePromise()
|
||||
{
|
||||
@@ -424,7 +427,8 @@ namespace Cysharp.Threading.Tasks
|
||||
sealed class DelayPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<DelayPromise>
|
||||
{
|
||||
static TaskPool<DelayPromise> pool;
|
||||
public DelayPromise NextNode { get; set; }
|
||||
DelayPromise nextNode;
|
||||
public ref DelayPromise NextNode => ref nextNode;
|
||||
|
||||
static DelayPromise()
|
||||
{
|
||||
@@ -534,7 +538,8 @@ namespace Cysharp.Threading.Tasks
|
||||
sealed class DelayIgnoreTimeScalePromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<DelayIgnoreTimeScalePromise>
|
||||
{
|
||||
static TaskPool<DelayIgnoreTimeScalePromise> pool;
|
||||
public DelayIgnoreTimeScalePromise NextNode { get; set; }
|
||||
DelayIgnoreTimeScalePromise nextNode;
|
||||
public ref DelayIgnoreTimeScalePromise NextNode => ref nextNode;
|
||||
|
||||
static DelayIgnoreTimeScalePromise()
|
||||
{
|
||||
@@ -644,7 +649,8 @@ namespace Cysharp.Threading.Tasks
|
||||
sealed class DelayRealtimePromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<DelayRealtimePromise>
|
||||
{
|
||||
static TaskPool<DelayRealtimePromise> pool;
|
||||
public DelayRealtimePromise NextNode { get; set; }
|
||||
DelayRealtimePromise nextNode;
|
||||
public ref DelayRealtimePromise NextNode => ref nextNode;
|
||||
|
||||
static DelayRealtimePromise()
|
||||
{
|
||||
|
||||
@@ -7,7 +7,11 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
public partial struct UniTask
|
||||
{
|
||||
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
||||
#region OBSOLETE_RUN
|
||||
|
||||
// Run is a confusing name, use only RunOnThreadPool in the future.
|
||||
|
||||
/// <summary>[Obsolete]recommend to use RunOnThreadPool(or UniTask.Void(async void), UniTask.Create(async UniTask)).</summary>
|
||||
public static async UniTask Run(Action action, bool configureAwait = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
@@ -35,7 +39,7 @@ namespace Cysharp.Threading.Tasks
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
||||
/// <summary>[Obsolete]recommend to use RunOnThreadPool(or UniTask.Void(async void), UniTask.Create(async UniTask)).</summary>
|
||||
public static async UniTask Run(Action<object> action, object state, bool configureAwait = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
@@ -63,7 +67,7 @@ namespace Cysharp.Threading.Tasks
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
||||
/// <summary>[Obsolete]recommend to use RunOnThreadPool(or UniTask.Void(async void), UniTask.Create(async UniTask)).</summary>
|
||||
public static async UniTask Run(Func<UniTask> action, bool configureAwait = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
@@ -91,7 +95,7 @@ namespace Cysharp.Threading.Tasks
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
||||
/// <summary>[Obsolete]recommend to use RunOnThreadPool(or UniTask.Void(async void), UniTask.Create(async UniTask)).</summary>
|
||||
public static async UniTask Run(Func<object, UniTask> action, object state, bool configureAwait = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
@@ -119,7 +123,7 @@ namespace Cysharp.Threading.Tasks
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
||||
/// <summary>[Obsolete]recommend to use RunOnThreadPool(or UniTask.Void(async void), UniTask.Create(async UniTask)).</summary>
|
||||
public static async UniTask<T> Run<T>(Func<T> func, bool configureAwait = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
@@ -146,7 +150,7 @@ namespace Cysharp.Threading.Tasks
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
||||
/// <summary>[Obsolete]recommend to use RunOnThreadPool(or UniTask.Void(async void), UniTask.Create(async UniTask)).</summary>
|
||||
public static async UniTask<T> Run<T>(Func<UniTask<T>> func, bool configureAwait = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
@@ -176,7 +180,7 @@ namespace Cysharp.Threading.Tasks
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
||||
/// <summary>[Obsolete]recommend to use RunOnThreadPool(or UniTask.Void(async void), UniTask.Create(async UniTask)).</summary>
|
||||
public static async UniTask<T> Run<T>(Func<object, T> func, object state, bool configureAwait = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
@@ -203,7 +207,7 @@ namespace Cysharp.Threading.Tasks
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
||||
/// <summary>[Obsolete]recommend to use RunOnThreadPool(or UniTask.Void(async void), UniTask.Create(async UniTask)).</summary>
|
||||
public static async UniTask<T> Run<T>(Func<object, UniTask<T>> func, object state, bool configureAwait = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
@@ -232,6 +236,235 @@ namespace Cysharp.Threading.Tasks
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
||||
public static async UniTask RunOnThreadPool(Action action, bool configureAwait = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
await UniTask.SwitchToThreadPool();
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (configureAwait)
|
||||
{
|
||||
try
|
||||
{
|
||||
action();
|
||||
}
|
||||
finally
|
||||
{
|
||||
await UniTask.Yield();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
action();
|
||||
}
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
||||
public static async UniTask RunOnThreadPool(Action<object> action, object state, bool configureAwait = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
await UniTask.SwitchToThreadPool();
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (configureAwait)
|
||||
{
|
||||
try
|
||||
{
|
||||
action(state);
|
||||
}
|
||||
finally
|
||||
{
|
||||
await UniTask.Yield();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
action(state);
|
||||
}
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
||||
public static async UniTask RunOnThreadPool(Func<UniTask> action, bool configureAwait = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
await UniTask.SwitchToThreadPool();
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (configureAwait)
|
||||
{
|
||||
try
|
||||
{
|
||||
await action();
|
||||
}
|
||||
finally
|
||||
{
|
||||
await UniTask.Yield();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await action();
|
||||
}
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
||||
public static async UniTask RunOnThreadPool(Func<object, UniTask> action, object state, bool configureAwait = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
await UniTask.SwitchToThreadPool();
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (configureAwait)
|
||||
{
|
||||
try
|
||||
{
|
||||
await action(state);
|
||||
}
|
||||
finally
|
||||
{
|
||||
await UniTask.Yield();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await action(state);
|
||||
}
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
||||
public static async UniTask<T> RunOnThreadPool<T>(Func<T> func, bool configureAwait = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
await UniTask.SwitchToThreadPool();
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (configureAwait)
|
||||
{
|
||||
try
|
||||
{
|
||||
return func();
|
||||
}
|
||||
finally
|
||||
{
|
||||
await UniTask.Yield();
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return func();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
||||
public static async UniTask<T> RunOnThreadPool<T>(Func<UniTask<T>> func, bool configureAwait = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
await UniTask.SwitchToThreadPool();
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (configureAwait)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await func();
|
||||
}
|
||||
finally
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
await UniTask.Yield();
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await func();
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
||||
public static async UniTask<T> RunOnThreadPool<T>(Func<object, T> func, object state, bool configureAwait = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
await UniTask.SwitchToThreadPool();
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (configureAwait)
|
||||
{
|
||||
try
|
||||
{
|
||||
return func(state);
|
||||
}
|
||||
finally
|
||||
{
|
||||
await UniTask.Yield();
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return func(state);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Run action on the threadPool and return to main thread if configureAwait = true.</summary>
|
||||
public static async UniTask<T> RunOnThreadPool<T>(Func<object, UniTask<T>> func, object state, bool configureAwait = true, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
await UniTask.SwitchToThreadPool();
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (configureAwait)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await func(state);
|
||||
}
|
||||
finally
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
await UniTask.Yield();
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await func(state);
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -224,7 +224,8 @@ namespace Cysharp.Threading.Tasks
|
||||
sealed class ThreadPoolWorkItem : IThreadPoolWorkItem, ITaskPoolNode<ThreadPoolWorkItem>
|
||||
{
|
||||
static TaskPool<ThreadPoolWorkItem> pool;
|
||||
public ThreadPoolWorkItem NextNode { get; set; }
|
||||
ThreadPoolWorkItem nextNode;
|
||||
public ref ThreadPoolWorkItem NextNode => ref nextNode;
|
||||
|
||||
static ThreadPoolWorkItem()
|
||||
{
|
||||
|
||||
@@ -38,7 +38,8 @@ namespace Cysharp.Threading.Tasks
|
||||
sealed class WaitUntilPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<WaitUntilPromise>
|
||||
{
|
||||
static TaskPool<WaitUntilPromise> pool;
|
||||
public WaitUntilPromise NextNode { get; set; }
|
||||
WaitUntilPromise nextNode;
|
||||
public ref WaitUntilPromise NextNode => ref nextNode;
|
||||
|
||||
static WaitUntilPromise()
|
||||
{
|
||||
@@ -142,7 +143,8 @@ namespace Cysharp.Threading.Tasks
|
||||
sealed class WaitWhilePromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<WaitWhilePromise>
|
||||
{
|
||||
static TaskPool<WaitWhilePromise> pool;
|
||||
public WaitWhilePromise NextNode { get; set; }
|
||||
WaitWhilePromise nextNode;
|
||||
public ref WaitWhilePromise NextNode => ref nextNode;
|
||||
|
||||
static WaitWhilePromise()
|
||||
{
|
||||
@@ -246,7 +248,8 @@ namespace Cysharp.Threading.Tasks
|
||||
sealed class WaitUntilCanceledPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<WaitUntilCanceledPromise>
|
||||
{
|
||||
static TaskPool<WaitUntilCanceledPromise> pool;
|
||||
public WaitUntilCanceledPromise NextNode { get; set; }
|
||||
WaitUntilCanceledPromise nextNode;
|
||||
public ref WaitUntilCanceledPromise NextNode => ref nextNode;
|
||||
|
||||
static WaitUntilCanceledPromise()
|
||||
{
|
||||
@@ -334,7 +337,8 @@ namespace Cysharp.Threading.Tasks
|
||||
sealed class WaitUntilValueChangedUnityObjectPromise<T, U> : IUniTaskSource<U>, IPlayerLoopItem, ITaskPoolNode<WaitUntilValueChangedUnityObjectPromise<T, U>>
|
||||
{
|
||||
static TaskPool<WaitUntilValueChangedUnityObjectPromise<T, U>> pool;
|
||||
public WaitUntilValueChangedUnityObjectPromise<T, U> NextNode { get; set; }
|
||||
WaitUntilValueChangedUnityObjectPromise<T, U> nextNode;
|
||||
public ref WaitUntilValueChangedUnityObjectPromise<T, U> NextNode => ref nextNode;
|
||||
|
||||
static WaitUntilValueChangedUnityObjectPromise()
|
||||
{
|
||||
@@ -457,7 +461,8 @@ namespace Cysharp.Threading.Tasks
|
||||
where T : class
|
||||
{
|
||||
static TaskPool<WaitUntilValueChangedStandardObjectPromise<T, U>> pool;
|
||||
public WaitUntilValueChangedStandardObjectPromise<T, U> NextNode { get; set; }
|
||||
WaitUntilValueChangedStandardObjectPromise<T, U> nextNode;
|
||||
public ref WaitUntilValueChangedStandardObjectPromise<T, U> NextNode => ref nextNode;
|
||||
|
||||
static WaitUntilValueChangedStandardObjectPromise()
|
||||
{
|
||||
|
||||
@@ -10,6 +10,11 @@
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [
|
||||
{
|
||||
"name": "com.unity.modules.assetbundle",
|
||||
"expression": "",
|
||||
"define": "UNITASK_ASSETBUNDLE_SUPPORT"
|
||||
}
|
||||
],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -319,7 +319,8 @@ namespace Cysharp.Threading.Tasks
|
||||
public class AutoResetUniTaskCompletionSource : IUniTaskSource, ITaskPoolNode<AutoResetUniTaskCompletionSource>, IPromise
|
||||
{
|
||||
static TaskPool<AutoResetUniTaskCompletionSource> pool;
|
||||
public AutoResetUniTaskCompletionSource NextNode { get; set; }
|
||||
AutoResetUniTaskCompletionSource nextNode;
|
||||
public ref AutoResetUniTaskCompletionSource NextNode => ref nextNode;
|
||||
|
||||
static AutoResetUniTaskCompletionSource()
|
||||
{
|
||||
@@ -441,7 +442,8 @@ namespace Cysharp.Threading.Tasks
|
||||
public class AutoResetUniTaskCompletionSource<T> : IUniTaskSource<T>, ITaskPoolNode<AutoResetUniTaskCompletionSource<T>>, IPromise<T>
|
||||
{
|
||||
static TaskPool<AutoResetUniTaskCompletionSource<T>> pool;
|
||||
public AutoResetUniTaskCompletionSource<T> NextNode { get; set; }
|
||||
AutoResetUniTaskCompletionSource<T> nextNode;
|
||||
public ref AutoResetUniTaskCompletionSource<T> NextNode => ref nextNode;
|
||||
|
||||
static AutoResetUniTaskCompletionSource()
|
||||
{
|
||||
|
||||
@@ -561,21 +561,23 @@ namespace Cysharp.Threading.Tasks
|
||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
awaiter.SourceOnCompleted(state =>
|
||||
else
|
||||
{
|
||||
using (var t = (StateTuple<UniTask.Awaiter>)state)
|
||||
awaiter.SourceOnCompleted(state =>
|
||||
{
|
||||
try
|
||||
using (var t = (StateTuple<UniTask.Awaiter>)state)
|
||||
{
|
||||
t.Item1.GetResult();
|
||||
try
|
||||
{
|
||||
t.Item1.GetResult();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||
}
|
||||
}
|
||||
}, StateTuple.Create(awaiter));
|
||||
}, StateTuple.Create(awaiter));
|
||||
}
|
||||
}
|
||||
|
||||
public static void Forget(this UniTask task, Action<Exception> exceptionHandler, bool handleExceptionOnMainThread = true)
|
||||
@@ -629,21 +631,23 @@ namespace Cysharp.Threading.Tasks
|
||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
awaiter.SourceOnCompleted(state =>
|
||||
else
|
||||
{
|
||||
using (var t = (StateTuple<UniTask<T>.Awaiter>)state)
|
||||
awaiter.SourceOnCompleted(state =>
|
||||
{
|
||||
try
|
||||
using (var t = (StateTuple<UniTask<T>.Awaiter>)state)
|
||||
{
|
||||
t.Item1.GetResult();
|
||||
try
|
||||
{
|
||||
t.Item1.GetResult();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||
}
|
||||
}
|
||||
}, StateTuple.Create(awaiter));
|
||||
}, StateTuple.Create(awaiter));
|
||||
}
|
||||
}
|
||||
|
||||
public static void Forget<T>(this UniTask<T> task, Action<Exception> exceptionHandler, bool handleExceptionOnMainThread = true)
|
||||
@@ -732,11 +736,51 @@ namespace Cysharp.Threading.Tasks
|
||||
return await await task;
|
||||
}
|
||||
|
||||
public static async UniTask Unwrap<T>(this UniTask<UniTask> task)
|
||||
public static async UniTask Unwrap(this UniTask<UniTask> task)
|
||||
{
|
||||
await await task;
|
||||
}
|
||||
|
||||
public static async UniTask<T> Unwrap<T>(this Task<UniTask<T>> task)
|
||||
{
|
||||
return await await task;
|
||||
}
|
||||
|
||||
public static async UniTask<T> Unwrap<T>(this Task<UniTask<T>> task, bool continueOnCapturedContext)
|
||||
{
|
||||
return await await task.ConfigureAwait(continueOnCapturedContext);
|
||||
}
|
||||
|
||||
public static async UniTask Unwrap(this Task<UniTask> task)
|
||||
{
|
||||
await await task;
|
||||
}
|
||||
|
||||
public static async UniTask Unwrap(this Task<UniTask> task, bool continueOnCapturedContext)
|
||||
{
|
||||
await await task.ConfigureAwait(continueOnCapturedContext);
|
||||
}
|
||||
|
||||
public static async UniTask<T> Unwrap<T>(this UniTask<Task<T>> task)
|
||||
{
|
||||
return await await task;
|
||||
}
|
||||
|
||||
public static async UniTask<T> Unwrap<T>(this UniTask<Task<T>> task, bool continueOnCapturedContext)
|
||||
{
|
||||
return await (await task).ConfigureAwait(continueOnCapturedContext);
|
||||
}
|
||||
|
||||
public static async UniTask Unwrap(this UniTask<Task> task)
|
||||
{
|
||||
await await task;
|
||||
}
|
||||
|
||||
public static async UniTask Unwrap(this UniTask<Task> task, bool continueOnCapturedContext)
|
||||
{
|
||||
await (await task).ConfigureAwait(continueOnCapturedContext);
|
||||
}
|
||||
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
|
||||
sealed class ToCoroutineEnumerator : IEnumerator
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||
|
||||
#if UNITY_2018_4 || UNITY_2019_4_OR_NEWER
|
||||
#if UNITASK_ASSETBUNDLE_SUPPORT
|
||||
|
||||
using Cysharp.Threading.Tasks.Internal;
|
||||
using System;
|
||||
@@ -45,6 +46,11 @@ namespace Cysharp.Threading.Tasks
|
||||
this.continuationAction = null;
|
||||
}
|
||||
|
||||
public AssetBundleRequestAllAssetsAwaiter GetAwaiter()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
public bool IsCompleted => asyncOperation.isDone;
|
||||
|
||||
public UnityEngine.Object[] GetResult()
|
||||
@@ -81,7 +87,8 @@ namespace Cysharp.Threading.Tasks
|
||||
sealed class AssetBundleRequestAllAssetsWithCancellationSource : IUniTaskSource<UnityEngine.Object[]>, IPlayerLoopItem, ITaskPoolNode<AssetBundleRequestAllAssetsWithCancellationSource>
|
||||
{
|
||||
static TaskPool<AssetBundleRequestAllAssetsWithCancellationSource> pool;
|
||||
public AssetBundleRequestAllAssetsWithCancellationSource NextNode { get; set; }
|
||||
AssetBundleRequestAllAssetsWithCancellationSource nextNode;
|
||||
public ref AssetBundleRequestAllAssetsWithCancellationSource NextNode => ref nextNode;
|
||||
|
||||
static AssetBundleRequestAllAssetsWithCancellationSource()
|
||||
{
|
||||
@@ -203,7 +210,8 @@ namespace Cysharp.Threading.Tasks
|
||||
sealed class AssetBundleRequestAllAssetsConfiguredSource : IUniTaskSource<UnityEngine.Object[]>, IPlayerLoopItem, ITaskPoolNode<AssetBundleRequestAllAssetsConfiguredSource>
|
||||
{
|
||||
static TaskPool<AssetBundleRequestAllAssetsConfiguredSource> pool;
|
||||
public AssetBundleRequestAllAssetsConfiguredSource NextNode { get; set; }
|
||||
AssetBundleRequestAllAssetsConfiguredSource nextNode;
|
||||
public ref AssetBundleRequestAllAssetsConfiguredSource NextNode => ref nextNode;
|
||||
|
||||
static AssetBundleRequestAllAssetsConfiguredSource()
|
||||
{
|
||||
@@ -312,4 +320,5 @@ namespace Cysharp.Threading.Tasks
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -29,7 +29,8 @@ namespace Cysharp.Threading.Tasks
|
||||
sealed class AsyncGPUReadbackRequestAwaiterConfiguredSource : IUniTaskSource<AsyncGPUReadbackRequest>, IPlayerLoopItem, ITaskPoolNode<AsyncGPUReadbackRequestAwaiterConfiguredSource>
|
||||
{
|
||||
static TaskPool<AsyncGPUReadbackRequestAwaiterConfiguredSource> pool;
|
||||
public AsyncGPUReadbackRequestAwaiterConfiguredSource NextNode { get; set; }
|
||||
AsyncGPUReadbackRequestAwaiterConfiguredSource nextNode;
|
||||
public ref AsyncGPUReadbackRequestAwaiterConfiguredSource NextNode => ref nextNode;
|
||||
|
||||
static AsyncGPUReadbackRequestAwaiterConfiguredSource()
|
||||
{
|
||||
|
||||
@@ -80,7 +80,8 @@ namespace Cysharp.Threading.Tasks
|
||||
sealed class AsyncOperationWithCancellationSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<AsyncOperationWithCancellationSource>
|
||||
{
|
||||
static TaskPool<AsyncOperationWithCancellationSource> pool;
|
||||
public AsyncOperationWithCancellationSource NextNode { get; set; }
|
||||
AsyncOperationWithCancellationSource nextNode;
|
||||
public ref AsyncOperationWithCancellationSource NextNode => ref nextNode;
|
||||
|
||||
static AsyncOperationWithCancellationSource()
|
||||
{
|
||||
@@ -198,7 +199,8 @@ namespace Cysharp.Threading.Tasks
|
||||
sealed class AsyncOperationConfiguredSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<AsyncOperationConfiguredSource>
|
||||
{
|
||||
static TaskPool<AsyncOperationConfiguredSource> pool;
|
||||
public AsyncOperationConfiguredSource NextNode { get; set; }
|
||||
AsyncOperationConfiguredSource nextNode;
|
||||
public ref AsyncOperationConfiguredSource NextNode => ref nextNode;
|
||||
|
||||
static AsyncOperationConfiguredSource()
|
||||
{
|
||||
@@ -374,7 +376,8 @@ namespace Cysharp.Threading.Tasks
|
||||
sealed class ResourceRequestWithCancellationSource : IUniTaskSource<UnityEngine.Object>, IPlayerLoopItem, ITaskPoolNode<ResourceRequestWithCancellationSource>
|
||||
{
|
||||
static TaskPool<ResourceRequestWithCancellationSource> pool;
|
||||
public ResourceRequestWithCancellationSource NextNode { get; set; }
|
||||
ResourceRequestWithCancellationSource nextNode;
|
||||
public ref ResourceRequestWithCancellationSource NextNode => ref nextNode;
|
||||
|
||||
static ResourceRequestWithCancellationSource()
|
||||
{
|
||||
@@ -496,7 +499,8 @@ namespace Cysharp.Threading.Tasks
|
||||
sealed class ResourceRequestConfiguredSource : IUniTaskSource<UnityEngine.Object>, IPlayerLoopItem, ITaskPoolNode<ResourceRequestConfiguredSource>
|
||||
{
|
||||
static TaskPool<ResourceRequestConfiguredSource> pool;
|
||||
public ResourceRequestConfiguredSource NextNode { get; set; }
|
||||
ResourceRequestConfiguredSource nextNode;
|
||||
public ref ResourceRequestConfiguredSource NextNode => ref nextNode;
|
||||
|
||||
static ResourceRequestConfiguredSource()
|
||||
{
|
||||
@@ -605,6 +609,7 @@ namespace Cysharp.Threading.Tasks
|
||||
|
||||
#endregion
|
||||
|
||||
#if UNITASK_ASSETBUNDLE_SUPPORT
|
||||
#region AssetBundleRequest
|
||||
|
||||
public static AssetBundleRequestAwaiter GetAwaiter(this AssetBundleRequest asyncOperation)
|
||||
@@ -676,7 +681,8 @@ namespace Cysharp.Threading.Tasks
|
||||
sealed class AssetBundleRequestWithCancellationSource : IUniTaskSource<UnityEngine.Object>, IPlayerLoopItem, ITaskPoolNode<AssetBundleRequestWithCancellationSource>
|
||||
{
|
||||
static TaskPool<AssetBundleRequestWithCancellationSource> pool;
|
||||
public AssetBundleRequestWithCancellationSource NextNode { get; set; }
|
||||
AssetBundleRequestWithCancellationSource nextNode;
|
||||
public ref AssetBundleRequestWithCancellationSource NextNode => ref nextNode;
|
||||
|
||||
static AssetBundleRequestWithCancellationSource()
|
||||
{
|
||||
@@ -798,7 +804,8 @@ namespace Cysharp.Threading.Tasks
|
||||
sealed class AssetBundleRequestConfiguredSource : IUniTaskSource<UnityEngine.Object>, IPlayerLoopItem, ITaskPoolNode<AssetBundleRequestConfiguredSource>
|
||||
{
|
||||
static TaskPool<AssetBundleRequestConfiguredSource> pool;
|
||||
public AssetBundleRequestConfiguredSource NextNode { get; set; }
|
||||
AssetBundleRequestConfiguredSource nextNode;
|
||||
public ref AssetBundleRequestConfiguredSource NextNode => ref nextNode;
|
||||
|
||||
static AssetBundleRequestConfiguredSource()
|
||||
{
|
||||
@@ -906,7 +913,9 @@ namespace Cysharp.Threading.Tasks
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endif
|
||||
|
||||
#if UNITASK_ASSETBUNDLE_SUPPORT
|
||||
#region AssetBundleCreateRequest
|
||||
|
||||
public static AssetBundleCreateRequestAwaiter GetAwaiter(this AssetBundleCreateRequest asyncOperation)
|
||||
@@ -978,7 +987,8 @@ namespace Cysharp.Threading.Tasks
|
||||
sealed class AssetBundleCreateRequestWithCancellationSource : IUniTaskSource<AssetBundle>, IPlayerLoopItem, ITaskPoolNode<AssetBundleCreateRequestWithCancellationSource>
|
||||
{
|
||||
static TaskPool<AssetBundleCreateRequestWithCancellationSource> pool;
|
||||
public AssetBundleCreateRequestWithCancellationSource NextNode { get; set; }
|
||||
AssetBundleCreateRequestWithCancellationSource nextNode;
|
||||
public ref AssetBundleCreateRequestWithCancellationSource NextNode => ref nextNode;
|
||||
|
||||
static AssetBundleCreateRequestWithCancellationSource()
|
||||
{
|
||||
@@ -1100,7 +1110,8 @@ namespace Cysharp.Threading.Tasks
|
||||
sealed class AssetBundleCreateRequestConfiguredSource : IUniTaskSource<AssetBundle>, IPlayerLoopItem, ITaskPoolNode<AssetBundleCreateRequestConfiguredSource>
|
||||
{
|
||||
static TaskPool<AssetBundleCreateRequestConfiguredSource> pool;
|
||||
public AssetBundleCreateRequestConfiguredSource NextNode { get; set; }
|
||||
AssetBundleCreateRequestConfiguredSource nextNode;
|
||||
public ref AssetBundleCreateRequestConfiguredSource NextNode => ref nextNode;
|
||||
|
||||
static AssetBundleCreateRequestConfiguredSource()
|
||||
{
|
||||
@@ -1208,6 +1219,7 @@ namespace Cysharp.Threading.Tasks
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endif
|
||||
|
||||
#if ENABLE_UNITYWEBREQUEST
|
||||
#region UnityWebRequestAsyncOperation
|
||||
@@ -1303,7 +1315,8 @@ namespace Cysharp.Threading.Tasks
|
||||
sealed class UnityWebRequestAsyncOperationWithCancellationSource : IUniTaskSource<UnityWebRequest>, IPlayerLoopItem, ITaskPoolNode<UnityWebRequestAsyncOperationWithCancellationSource>
|
||||
{
|
||||
static TaskPool<UnityWebRequestAsyncOperationWithCancellationSource> pool;
|
||||
public UnityWebRequestAsyncOperationWithCancellationSource NextNode { get; set; }
|
||||
UnityWebRequestAsyncOperationWithCancellationSource nextNode;
|
||||
public ref UnityWebRequestAsyncOperationWithCancellationSource NextNode => ref nextNode;
|
||||
|
||||
static UnityWebRequestAsyncOperationWithCancellationSource()
|
||||
{
|
||||
@@ -1434,7 +1447,8 @@ namespace Cysharp.Threading.Tasks
|
||||
sealed class UnityWebRequestAsyncOperationConfiguredSource : IUniTaskSource<UnityWebRequest>, IPlayerLoopItem, ITaskPoolNode<UnityWebRequestAsyncOperationConfiguredSource>
|
||||
{
|
||||
static TaskPool<UnityWebRequestAsyncOperationConfiguredSource> pool;
|
||||
public UnityWebRequestAsyncOperationConfiguredSource NextNode { get; set; }
|
||||
UnityWebRequestAsyncOperationConfiguredSource nextNode;
|
||||
public ref UnityWebRequestAsyncOperationConfiguredSource NextNode => ref nextNode;
|
||||
|
||||
static UnityWebRequestAsyncOperationConfiguredSource()
|
||||
{
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
Func<string, string> ToUniTaskReturnType = x => (x == "void") ? "UniTask" : $"UniTask<{x}>";
|
||||
Func<string, string> ToIUniTaskSourceReturnType = x => (x == "void") ? "IUniTaskSource" : $"IUniTaskSource<{x}>";
|
||||
Func<(string typeName, string returnType, string returnField), bool> IsUnityWebRequest = x => x.returnType == "UnityWebRequest";
|
||||
Func<(string typeName, string returnType, string returnField), bool> IsAssetBundleModule = x => x.typeName == "AssetBundleRequest" || x.typeName == "AssetBundleCreateRequest";
|
||||
Func<(string typeName, string returnType, string returnField), bool> IsVoid = x => x.returnType == "void";
|
||||
#>
|
||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||
@@ -37,6 +38,8 @@ namespace Cysharp.Threading.Tasks
|
||||
<# foreach(var t in types) { #>
|
||||
<# if(IsUnityWebRequest(t)) { #>
|
||||
#if ENABLE_UNITYWEBREQUEST
|
||||
<# } else if(IsAssetBundleModule(t)) { #>
|
||||
#if UNITASK_ASSETBUNDLE_SUPPORT
|
||||
<# } #>
|
||||
#region <#= t.typeName #>
|
||||
|
||||
@@ -151,7 +154,8 @@ namespace Cysharp.Threading.Tasks
|
||||
sealed class <#= t.typeName #>WithCancellationSource : <#= ToIUniTaskSourceReturnType(t.returnType) #>, IPlayerLoopItem, ITaskPoolNode<<#= t.typeName #>WithCancellationSource>
|
||||
{
|
||||
static TaskPool<<#= t.typeName #>WithCancellationSource> pool;
|
||||
public <#= t.typeName #>WithCancellationSource NextNode { get; set; }
|
||||
<#= t.typeName #>WithCancellationSource nextNode;
|
||||
public ref <#= t.typeName #>WithCancellationSource NextNode => ref nextNode;
|
||||
|
||||
static <#= t.typeName #>WithCancellationSource()
|
||||
{
|
||||
@@ -294,7 +298,8 @@ namespace Cysharp.Threading.Tasks
|
||||
sealed class <#= t.typeName #>ConfiguredSource : <#= ToIUniTaskSourceReturnType(t.returnType) #>, IPlayerLoopItem, ITaskPoolNode<<#= t.typeName #>ConfiguredSource>
|
||||
{
|
||||
static TaskPool<<#= t.typeName #>ConfiguredSource> pool;
|
||||
public <#= t.typeName #>ConfiguredSource NextNode { get; set; }
|
||||
<#= t.typeName #>ConfiguredSource nextNode;
|
||||
public ref <#= t.typeName #>ConfiguredSource NextNode => ref nextNode;
|
||||
|
||||
static <#= t.typeName #>ConfiguredSource()
|
||||
{
|
||||
@@ -422,7 +427,7 @@ namespace Cysharp.Threading.Tasks
|
||||
}
|
||||
|
||||
#endregion
|
||||
<# if(IsUnityWebRequest(t)) { #>
|
||||
<# if(IsUnityWebRequest(t) || IsAssetBundleModule(t)) { #>
|
||||
#endif
|
||||
<# } #>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "com.cysharp.unitask",
|
||||
"displayName": "UniTask",
|
||||
"version": "2.0.27",
|
||||
"version": "2.0.36",
|
||||
"unity": "2018.4",
|
||||
"description": "Provides an efficient async/await integration to Unity.",
|
||||
"keywords": [ "async/await", "async", "Task", "UniTask" ],
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
// using UnityEngine.AddressableAssets;
|
||||
|
||||
/*UNniTastWhenAnyTester*/
|
||||
|
||||
@@ -49,4 +50,9 @@ public class ExceptionExamples : MonoBehaviour
|
||||
await UniTask.Delay(100);
|
||||
return taskIndex;
|
||||
}
|
||||
|
||||
//void AddressablesTest()
|
||||
//{
|
||||
// Addressables.ClearDependencyCacheAsync("key", true);
|
||||
//}
|
||||
}
|
||||
471
src/UniTask/Assets/Scenes/MiddlewareSample.cs
Normal file
471
src/UniTask/Assets/Scenes/MiddlewareSample.cs
Normal file
@@ -0,0 +1,471 @@
|
||||
using Cysharp.Threading.Tasks;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Cysharp.Threading.Tasks.Sample
|
||||
{
|
||||
//public class Sample2
|
||||
//{
|
||||
// public Sample2()
|
||||
// {
|
||||
// // デコレーターの詰まったClientを生成(これは一度作ったらフィールドに保存可)
|
||||
// var client = new NetworkClient("http://localhost", TimeSpan.FromSeconds(10),
|
||||
// new QueueRequestDecorator(),
|
||||
// new LoggingDecorator(),
|
||||
// new AppendTokenDecorator(),
|
||||
// new SetupHeaderDecorator());
|
||||
|
||||
|
||||
// await client.PostAsync("/User/Register", new { Id = 100 });
|
||||
|
||||
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
public class ReturnToTitleDecorator : IAsyncDecorator
|
||||
{
|
||||
public async UniTask<ResponseContext> SendAsync(RequestContext context, CancellationToken cancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>> next)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await next(context, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (ex is OperationCanceledException)
|
||||
{
|
||||
// キャンセルはきっと想定されている処理なのでそのまんまスルー(呼び出し側でOperationCanceledExceptionとして飛んでいく)
|
||||
throw;
|
||||
}
|
||||
|
||||
if (ex is UnityWebRequestException uwe)
|
||||
{
|
||||
// ステータスコードを使って、タイトルに戻す例外です、とかリトライさせる例外です、とかハンドリングさせると便利
|
||||
// if (uwe.ResponseCode) { }...
|
||||
}
|
||||
|
||||
// サーバー例外のMessageを直接出すなんて乱暴なことはデバッグ時だけですよ勿論。
|
||||
var result = await MessageDialog.ShowAsync(ex.Message);
|
||||
|
||||
// OK か Cancelかで分岐するなら。今回はボタン一個、OKのみの想定なので無視
|
||||
// if (result == DialogResult.Ok) { }...
|
||||
|
||||
// シーン呼び出しはawaitしないこと!awaitして正常終了しちゃうと、この通信の呼び出し元に処理が戻って続行してしまいます
|
||||
// のでForget。
|
||||
SceneManager.LoadSceneAsync("TitleScene").ToUniTask().Forget();
|
||||
|
||||
|
||||
// そしてOperationCanceledExceptionを投げて、この通信の呼び出し元の処理はキャンセル扱いにして終了させる
|
||||
throw new OperationCanceledException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum DialogResult
|
||||
{
|
||||
Ok,
|
||||
Cancel
|
||||
}
|
||||
|
||||
public static class MessageDialog
|
||||
{
|
||||
public static async UniTask<DialogResult> ShowAsync(string message)
|
||||
{
|
||||
// (例えば)Prefabで作っておいたダイアログを生成する
|
||||
var view = await Resources.LoadAsync("Prefabs/Dialog");
|
||||
|
||||
// Ok, Cancelボタンのどちらかが押されるのを待機
|
||||
return await (view as GameObject).GetComponent<MessageDialogView>().ClickResult;
|
||||
}
|
||||
}
|
||||
|
||||
public class MessageDialogView : MonoBehaviour
|
||||
{
|
||||
[SerializeField] Button okButton = default;
|
||||
[SerializeField] Button closeButton = default;
|
||||
|
||||
UniTaskCompletionSource<DialogResult> taskCompletion;
|
||||
|
||||
// これでどちらかが押されるまで無限に待つを表現
|
||||
public UniTask<DialogResult> ClickResult => taskCompletion.Task;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
taskCompletion = new UniTaskCompletionSource<DialogResult>();
|
||||
|
||||
okButton.onClick.AddListener(() =>
|
||||
{
|
||||
taskCompletion.TrySetResult(DialogResult.Ok);
|
||||
});
|
||||
|
||||
closeButton.onClick.AddListener(() =>
|
||||
{
|
||||
taskCompletion.TrySetResult(DialogResult.Cancel);
|
||||
});
|
||||
}
|
||||
|
||||
// もしボタンが押されずに消滅した場合にネンノタメ。
|
||||
private void OnDestroy()
|
||||
{
|
||||
taskCompletion.TrySetResult(DialogResult.Cancel);
|
||||
}
|
||||
}
|
||||
|
||||
public class MockDecorator : IAsyncDecorator
|
||||
{
|
||||
Dictionary<string, object> mock;
|
||||
|
||||
// Pathと型を1:1にして事前定義したオブジェクトを返す辞書を渡す
|
||||
public MockDecorator(Dictionary<string, object> mock)
|
||||
{
|
||||
this.mock = mock;
|
||||
}
|
||||
|
||||
public UniTask<ResponseContext> SendAsync(RequestContext context, CancellationToken cancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>> next)
|
||||
{
|
||||
if (mock.TryGetValue(context.Path, out var value))
|
||||
{
|
||||
// 一致したものがあればそれを返す(実際の通信は行わない)
|
||||
return new UniTask<ResponseContext>(new ResponseContext(value));
|
||||
}
|
||||
else
|
||||
{
|
||||
return next(context, cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class LoggingDecorator : IAsyncDecorator
|
||||
{
|
||||
public async UniTask<ResponseContext> SendAsync(RequestContext context, CancellationToken cancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>> next)
|
||||
{
|
||||
var sw = Stopwatch.StartNew();
|
||||
try
|
||||
{
|
||||
UnityEngine.Debug.Log("Start Network Request:" + context.Path);
|
||||
|
||||
var response = await next(context, cancellationToken);
|
||||
|
||||
UnityEngine.Debug.Log($"Complete Network Request: {context.Path} , Elapsed: {sw.Elapsed}, Size: {response.GetRawData().Length}");
|
||||
|
||||
return response;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (ex is OperationCanceledException)
|
||||
{
|
||||
UnityEngine.Debug.Log("Request Canceled:" + context.Path);
|
||||
}
|
||||
else if (ex is TimeoutException)
|
||||
{
|
||||
UnityEngine.Debug.Log("Request Timeout:" + context.Path);
|
||||
}
|
||||
else if (ex is UnityWebRequestException webex)
|
||||
{
|
||||
if (webex.IsHttpError)
|
||||
{
|
||||
UnityEngine.Debug.Log($"Request HttpError: {context.Path} Code:{webex.ResponseCode} Message:{webex.Message}");
|
||||
}
|
||||
else if (webex.IsNetworkError)
|
||||
{
|
||||
UnityEngine.Debug.Log($"Request NetworkError: {context.Path} Code:{webex.ResponseCode} Message:{webex.Message}");
|
||||
}
|
||||
}
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
/* log other */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class SetupHeaderDecorator : IAsyncDecorator
|
||||
{
|
||||
public async UniTask<ResponseContext> SendAsync(RequestContext context, CancellationToken cancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>> next)
|
||||
{
|
||||
context.RequestHeaders["x-app-timestamp"] = context.Timestamp.ToString();
|
||||
context.RequestHeaders["x-user-id"] = "132141411"; // どこかから持ってくる
|
||||
context.RequestHeaders["x-access-token"] = "fafafawfafewaea"; // どこかから持ってくる2
|
||||
|
||||
var respsonse = await next(context, cancellationToken);
|
||||
|
||||
var nextToken = respsonse.ResponseHeaders["token"];
|
||||
// UserProfile.Token = nextToken; // どこかにセットするということにする
|
||||
|
||||
return respsonse;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class AppendTokenDecorator : IAsyncDecorator
|
||||
{
|
||||
public async UniTask<ResponseContext> SendAsync(RequestContext context, CancellationToken cancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>> next)
|
||||
{
|
||||
string token = "token"; // どっかから取ってくるということにする
|
||||
RETRY:
|
||||
try
|
||||
{
|
||||
context.RequestHeaders["x-accesss-token"] = token;
|
||||
return await next(context, cancellationToken);
|
||||
}
|
||||
catch (UnityWebRequestException ex)
|
||||
{
|
||||
// 例えば700はTokenを再取得してください的な意味だったとする
|
||||
if (ex.ResponseCode == 700)
|
||||
{
|
||||
// 別口でTokenを取得します的な処理
|
||||
var newToken = await new NetworkClient(context.BasePath, context.Timeout).PostAsync<string>("/Auth/GetToken", "access_token", cancellationToken);
|
||||
context.Reset(this);
|
||||
goto RETRY;
|
||||
}
|
||||
|
||||
goto RETRY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class QueueRequestDecorator : IAsyncDecorator
|
||||
{
|
||||
readonly Queue<(UniTaskCompletionSource<ResponseContext>, RequestContext, CancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>>)> q = new Queue<(UniTaskCompletionSource<ResponseContext>, RequestContext, CancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>>)>();
|
||||
bool running;
|
||||
|
||||
public async UniTask<ResponseContext> SendAsync(RequestContext context, CancellationToken cancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>> next)
|
||||
{
|
||||
if (q.Count == 0)
|
||||
{
|
||||
return await next(context, cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
var completionSource = new UniTaskCompletionSource<ResponseContext>();
|
||||
q.Enqueue((completionSource, context, cancellationToken, next));
|
||||
if (!running)
|
||||
{
|
||||
Run().Forget();
|
||||
}
|
||||
return await completionSource.Task;
|
||||
}
|
||||
}
|
||||
|
||||
async UniTaskVoid Run()
|
||||
{
|
||||
running = true;
|
||||
try
|
||||
{
|
||||
while (q.Count != 0)
|
||||
{
|
||||
var (tcs, context, cancellationToken, next) = q.Dequeue();
|
||||
try
|
||||
{
|
||||
var response = await next(context, cancellationToken);
|
||||
tcs.TrySetResult(response);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
tcs.TrySetException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
running = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class RequestContext
|
||||
{
|
||||
int decoratorIndex;
|
||||
readonly IAsyncDecorator[] decorators;
|
||||
Dictionary<string, string> headers;
|
||||
|
||||
public string BasePath { get; }
|
||||
public string Path { get; }
|
||||
public object Value { get; }
|
||||
public TimeSpan Timeout { get; }
|
||||
public DateTimeOffset Timestamp { get; private set; }
|
||||
|
||||
public IDictionary<string, string> RequestHeaders
|
||||
{
|
||||
get
|
||||
{
|
||||
if (headers == null)
|
||||
{
|
||||
headers = new Dictionary<string, string>();
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
}
|
||||
|
||||
public RequestContext(string basePath, string path, object value, TimeSpan timeout, IAsyncDecorator[] filters)
|
||||
{
|
||||
this.decoratorIndex = -1;
|
||||
this.decorators = filters;
|
||||
this.BasePath = basePath;
|
||||
this.Path = path;
|
||||
this.Value = value;
|
||||
this.Timeout = timeout;
|
||||
this.Timestamp = DateTimeOffset.UtcNow;
|
||||
}
|
||||
|
||||
internal Dictionary<string, string> GetRawHeaders() => headers;
|
||||
internal IAsyncDecorator GetNextDecorator() => decorators[++decoratorIndex];
|
||||
|
||||
public void Reset(IAsyncDecorator currentFilter)
|
||||
{
|
||||
decoratorIndex = Array.IndexOf(decorators, currentFilter);
|
||||
if (headers != null)
|
||||
{
|
||||
headers.Clear();
|
||||
}
|
||||
Timestamp = DateTimeOffset.UtcNow;
|
||||
}
|
||||
}
|
||||
|
||||
public class ResponseContext
|
||||
{
|
||||
bool hasValue;
|
||||
object value;
|
||||
readonly byte[] bytes;
|
||||
|
||||
public long StatusCode { get; }
|
||||
public Dictionary<string, string> ResponseHeaders { get; }
|
||||
|
||||
public ResponseContext(object value, Dictionary<string, string> header = null)
|
||||
{
|
||||
this.hasValue = true;
|
||||
this.value = value;
|
||||
this.StatusCode = 200;
|
||||
this.ResponseHeaders = (header ?? new Dictionary<string, string>());
|
||||
}
|
||||
|
||||
public ResponseContext(byte[] bytes, long statusCode, Dictionary<string, string> responseHeaders)
|
||||
{
|
||||
this.hasValue = false;
|
||||
this.bytes = bytes;
|
||||
this.StatusCode = statusCode;
|
||||
this.ResponseHeaders = responseHeaders;
|
||||
}
|
||||
|
||||
public byte[] GetRawData() => bytes;
|
||||
|
||||
public T GetResponseAs<T>()
|
||||
{
|
||||
if (hasValue)
|
||||
{
|
||||
return (T)value;
|
||||
}
|
||||
|
||||
value = JsonUtility.FromJson<T>(Encoding.UTF8.GetString(bytes));
|
||||
hasValue = true;
|
||||
return (T)value;
|
||||
}
|
||||
}
|
||||
|
||||
public interface IAsyncDecorator
|
||||
{
|
||||
UniTask<ResponseContext> SendAsync(RequestContext context, CancellationToken cancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>> next);
|
||||
}
|
||||
|
||||
|
||||
public class NetworkClient : IAsyncDecorator
|
||||
{
|
||||
readonly Func<RequestContext, CancellationToken, UniTask<ResponseContext>> next;
|
||||
readonly IAsyncDecorator[] decorators;
|
||||
readonly TimeSpan timeout;
|
||||
readonly IProgress<float> progress;
|
||||
readonly string basePath;
|
||||
|
||||
public NetworkClient(string basePath, TimeSpan timeout, params IAsyncDecorator[] decorators)
|
||||
: this(basePath, timeout, null, decorators)
|
||||
{
|
||||
}
|
||||
|
||||
public NetworkClient(string basePath, TimeSpan timeout, IProgress<float> progress, params IAsyncDecorator[] decorators)
|
||||
{
|
||||
this.next = InvokeRecursive; // setup delegate
|
||||
|
||||
this.basePath = basePath;
|
||||
this.timeout = timeout;
|
||||
this.progress = progress;
|
||||
this.decorators = new IAsyncDecorator[decorators.Length + 1];
|
||||
Array.Copy(decorators, this.decorators, decorators.Length);
|
||||
this.decorators[this.decorators.Length - 1] = this;
|
||||
}
|
||||
|
||||
public async UniTask<T> PostAsync<T>(string path, T value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var request = new RequestContext(basePath, path, value, timeout, decorators);
|
||||
var response = await InvokeRecursive(request, cancellationToken);
|
||||
return response.GetResponseAs<T>();
|
||||
}
|
||||
|
||||
|
||||
UniTask<ResponseContext> InvokeRecursive(RequestContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
return context.GetNextDecorator().SendAsync(context, cancellationToken, next); // マジカル再帰処理
|
||||
}
|
||||
|
||||
async UniTask<ResponseContext> IAsyncDecorator.SendAsync(RequestContext context, CancellationToken cancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>> _)
|
||||
{
|
||||
// Postしか興味ないからPostにしかしないよ!
|
||||
// パフォーマンスを最大限にしたい場合はuploadHandler, downloadHandlerをカスタマイズすること
|
||||
|
||||
// JSONでbodyに送るというパラメータで送るという雑設定。
|
||||
var data = JsonUtility.ToJson(context.Value);
|
||||
var formData = new Dictionary<string, string> { { "body", data } };
|
||||
|
||||
using (var req = UnityWebRequest.Post(basePath + context.Path, formData))
|
||||
{
|
||||
var header = context.GetRawHeaders();
|
||||
if (header != null)
|
||||
{
|
||||
foreach (var item in header)
|
||||
{
|
||||
req.SetRequestHeader(item.Key, item.Value);
|
||||
}
|
||||
}
|
||||
|
||||
// Timeout処理はCancellationTokenSourceのCancelAfterSlim(UniTask拡張)を使ってサクッと処理
|
||||
var linkToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
|
||||
linkToken.CancelAfterSlim(timeout);
|
||||
try
|
||||
{
|
||||
// 完了待ちや終了処理はUniTaskの拡張自体に丸投げ
|
||||
await req.SendWebRequest().ToUniTask(progress: progress, cancellationToken: linkToken.Token);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// 元キャンセレーションソースがキャンセルしてなければTimeoutによるものと判定
|
||||
if (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
throw new TimeoutException();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Timeoutに引っかからなかった場合にてるのでCancelAfterSlimの裏で回ってるループをこれで終わらせとく
|
||||
if (!linkToken.IsCancellationRequested)
|
||||
{
|
||||
linkToken.Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
// UnityWebRequestを先にDisposeしちゃうので先に必要なものを取得しておく(性能的には無駄なのでパフォーマンスを最大限にしたい場合は更に一工夫を)
|
||||
return new ResponseContext(req.downloadHandler.data, req.responseCode, req.GetResponseHeaders());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
src/UniTask/Assets/Scenes/MiddlewareSample.cs.meta
Normal file
11
src/UniTask/Assets/Scenes/MiddlewareSample.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7fc39a4b35a8db44592cddc0b365942f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -17,6 +17,8 @@ using UnityEngine.UI;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.Rendering;
|
||||
using System.IO;
|
||||
using System.Linq.Expressions;
|
||||
using Cysharp.Threading.Tasks.Sample;
|
||||
|
||||
|
||||
// using DG.Tweening;
|
||||
@@ -491,11 +493,48 @@ public class SandboxMain : MonoBehaviour
|
||||
}
|
||||
|
||||
|
||||
async UniTask QuitCheck()
|
||||
{
|
||||
try
|
||||
{
|
||||
await UniTask.Delay(TimeSpan.FromMinutes(1), cancellationToken: quitSource.Token);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Debug.Log("End QuitCheck async");
|
||||
}
|
||||
}
|
||||
|
||||
CancellationTokenSource quitSource = new CancellationTokenSource();
|
||||
|
||||
|
||||
IEnumerator TestCor()
|
||||
{
|
||||
Debug.Log("start cor");
|
||||
yield return null;
|
||||
yield return new WaitForEndOfFrame();
|
||||
Debug.Log("end cor");
|
||||
}
|
||||
|
||||
async UniTaskVoid Start()
|
||||
{
|
||||
RunStandardTaskAsync();
|
||||
await TestCor().ToUniTask(this);
|
||||
|
||||
UnityEngine.Debug.Log("UniTaskPlayerLoop ready? " + PlayerLoopHelper.IsInjectedUniTaskPlayerLoop());
|
||||
Debug.Log("App Start");
|
||||
|
||||
Application.quitting += () =>
|
||||
{
|
||||
Debug.Log("called quitting");
|
||||
quitSource.Cancel();
|
||||
};
|
||||
|
||||
QuitCheck().Forget();
|
||||
|
||||
//Expression.Lambda<Func<int>>(null).Compile(true);
|
||||
|
||||
//RunStandardTaskAsync();
|
||||
|
||||
//UnityEngine.Debug.Log("UniTaskPlayerLoop ready? " + PlayerLoopHelper.IsInjectedUniTaskPlayerLoop());
|
||||
|
||||
//var url = "http://google.com/404";
|
||||
//var webRequestAsyncOperation = UnityWebRequest.Get(url).SendWebRequest();
|
||||
@@ -524,8 +563,23 @@ public class SandboxMain : MonoBehaviour
|
||||
//UniTask.Delay(TimeSpan.FromSeconds(3)).
|
||||
|
||||
|
||||
//okButton.onClick.AddListener(UniTask.UnityAction(async () =>
|
||||
//{
|
||||
|
||||
|
||||
okButton.onClick.AddListener(UniTask.UnityAction(async () =>
|
||||
{
|
||||
|
||||
var client = new NetworkClient("http://localhost:5000", TimeSpan.FromSeconds(2),
|
||||
new QueueRequestDecorator(),
|
||||
new LoggingDecorator());
|
||||
//new AppendTokenDecorator(),
|
||||
//new SetupHeaderDecorator());
|
||||
|
||||
|
||||
await client.PostAsync("", new { Id = 100 });
|
||||
|
||||
|
||||
}));
|
||||
|
||||
// _ = ExecuteAsync();
|
||||
|
||||
// await UniTask.Yield();
|
||||
|
||||
192
src/UniTask/Assets/Tests/CoroutineToUniTaskTest.cs
Normal file
192
src/UniTask/Assets/Tests/CoroutineToUniTaskTest.cs
Normal file
@@ -0,0 +1,192 @@
|
||||
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
|
||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.Scripting;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using Unity.Collections;
|
||||
using System.Threading;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine.TestTools;
|
||||
using FluentAssertions;
|
||||
|
||||
namespace Cysharp.Threading.TasksTests
|
||||
{
|
||||
public class CoroutineToUniTaskTest
|
||||
{
|
||||
[UnityTest]
|
||||
public IEnumerator EarlyUpdate() => UniTask.ToCoroutine(async () =>
|
||||
{
|
||||
await UniTask.Yield(PlayerLoopTiming.EarlyUpdate);
|
||||
|
||||
var l = new List<(int, int)>();
|
||||
var currentFrame = Time.frameCount;
|
||||
var t = Worker(l).ToUniTask();
|
||||
|
||||
l.Count.Should().Be(1);
|
||||
l[0].Should().Be((0, currentFrame));
|
||||
|
||||
await t;
|
||||
|
||||
l[1].Should().Be((1, Time.frameCount));
|
||||
l[1].Item2.Should().NotBe(currentFrame);
|
||||
});
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator LateUpdate() => UniTask.ToCoroutine(async () =>
|
||||
{
|
||||
await UniTask.Yield(PlayerLoopTiming.PostLateUpdate);
|
||||
|
||||
var l = new List<(int, int)>();
|
||||
var currentFrame = Time.frameCount;
|
||||
var t = Worker(l).ToUniTask();
|
||||
|
||||
l.Count.Should().Be(1);
|
||||
l[0].Should().Be((0, currentFrame));
|
||||
|
||||
await t;
|
||||
|
||||
l[1].Should().Be((1, Time.frameCount));
|
||||
l[1].Item2.Should().NotBe(currentFrame);
|
||||
});
|
||||
|
||||
//[UnityTest]
|
||||
//public IEnumerator TestCoroutine()
|
||||
//{
|
||||
// yield return UniTask.Yield(PlayerLoopTiming.EarlyUpdate).ToUniTask().ToCoroutine();
|
||||
|
||||
// var nanika = (UnityEngine.MonoBehaviour)GameObject.FindObjectOfType(typeof(UnityEngine.MonoBehaviour));
|
||||
|
||||
// var l = new List<(int, int)>();
|
||||
// var currentFrame = Time.frameCount;
|
||||
// var t = nanika.StartCoroutine(Worker(l));
|
||||
|
||||
// l.Count.Should().Be(1);
|
||||
// l[0].Should().Be((0, currentFrame));
|
||||
|
||||
// yield return t;
|
||||
|
||||
// l[1].Should().Be((1, Time.frameCount));
|
||||
// l[1].Item2.Should().NotBe(currentFrame);
|
||||
//}
|
||||
|
||||
//[UnityTest]
|
||||
//public IEnumerator TestCoroutine2()
|
||||
//{
|
||||
// yield return UniTask.Yield(PlayerLoopTiming.PostLateUpdate).ToUniTask().ToCoroutine();
|
||||
|
||||
// var nanika = (UnityEngine.MonoBehaviour)GameObject.FindObjectOfType(typeof(UnityEngine.MonoBehaviour));
|
||||
|
||||
// var l = new List<(int, int)>();
|
||||
// var currentFrame = Time.frameCount;
|
||||
// var t = nanika.StartCoroutine(Worker(l));
|
||||
|
||||
// l.Count.Should().Be(1);
|
||||
// l[0].Should().Be((0, currentFrame));
|
||||
|
||||
// yield return t;
|
||||
|
||||
// l[1].Should().Be((1, Time.frameCount));
|
||||
// l[1].Item2.Should().NotBe(currentFrame);
|
||||
//}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator ImmediateRunTest() => UniTask.ToCoroutine(async () =>
|
||||
{
|
||||
var l = new List<int>();
|
||||
var x1 = Immediate(l);
|
||||
var x2 = Immediate(l);
|
||||
var x3 = DelayOne(l);
|
||||
|
||||
var t1 = x1.ToUniTask();
|
||||
CollectionAssert.AreEqual(l, new[] { 1, 2, 3 });
|
||||
await t1;
|
||||
|
||||
var t2 = x2.ToUniTask();
|
||||
CollectionAssert.AreEqual(l, new[] { 1, 2, 3, 1, 2, 3 });
|
||||
|
||||
var t3 = x3.ToUniTask();
|
||||
CollectionAssert.AreEqual(l, new[] { 1, 2, 3, 1, 2, 3, 10 });
|
||||
|
||||
await UniTask.WhenAll(t2, t3);
|
||||
CollectionAssert.AreEqual(l, new[] { 1, 2, 3, 1, 2, 3, 10, 20, 30 });
|
||||
|
||||
});
|
||||
|
||||
IEnumerator Immediate(List<int> l)
|
||||
{
|
||||
l.Add(1);
|
||||
l.Add(2);
|
||||
l.Add(3);
|
||||
yield break;
|
||||
}
|
||||
|
||||
IEnumerator DelayOne(List<int> l)
|
||||
{
|
||||
l.Add(10);
|
||||
yield return null;
|
||||
l.Add(20);
|
||||
l.Add(30);
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator WaitForSecondsTest() => UniTask.ToCoroutine(async () =>
|
||||
{
|
||||
await UniTask.Yield(PlayerLoopTiming.PostLateUpdate);
|
||||
|
||||
Time.timeScale = 0.5f;
|
||||
try
|
||||
{
|
||||
var now = DateTimeOffset.UtcNow;
|
||||
|
||||
await WaitFor();
|
||||
|
||||
var elapsed = DateTimeOffset.UtcNow - now;
|
||||
|
||||
(5.8f <= elapsed.TotalSeconds && elapsed.TotalSeconds <= 6.2f).Should().BeTrue();
|
||||
}
|
||||
finally
|
||||
{
|
||||
Time.timeScale = 1.0f;
|
||||
}
|
||||
});
|
||||
|
||||
IEnumerator WaitFor()
|
||||
{
|
||||
yield return new WaitForSeconds(3.0f);
|
||||
}
|
||||
|
||||
IEnumerator Worker(List<(int, int)> l)
|
||||
{
|
||||
l.Add((0, Time.frameCount));
|
||||
yield return null;
|
||||
l.Add((1, Time.frameCount));
|
||||
}
|
||||
|
||||
public async UniTask Foo()
|
||||
{
|
||||
var tasks = new List<UniTask>();
|
||||
var t = Bar<int>();
|
||||
tasks.Add(t);
|
||||
|
||||
t = Bar<int>();
|
||||
tasks.Add(t);
|
||||
|
||||
await UniTask.WhenAll(tasks);
|
||||
}
|
||||
|
||||
public async UniTask<T> Bar<T>()
|
||||
{
|
||||
await UniTask.Yield();
|
||||
return default(T);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
11
src/UniTask/Assets/Tests/CoroutineToUniTaskTest.cs.meta
Normal file
11
src/UniTask/Assets/Tests/CoroutineToUniTaskTest.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 43ffb719370515746932af3732ce073e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -200,5 +200,16 @@ namespace Cysharp.Threading.TasksTests
|
||||
okay1.Should().Be(true);
|
||||
okay2.Should().Be(true);
|
||||
});
|
||||
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator LoopTest() => UniTask.ToCoroutine(async () =>
|
||||
{
|
||||
for (int i = 0; i < 20; ++i)
|
||||
{
|
||||
UniTask.DelayFrame(100).Forget();
|
||||
await UniTask.DelayFrame(1);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -111,6 +111,8 @@ PlayerSettings:
|
||||
switchNVNShaderPoolsGranularity: 33554432
|
||||
switchNVNDefaultPoolsGranularity: 16777216
|
||||
switchNVNOtherPoolsGranularity: 16777216
|
||||
stadiaPresentMode: 0
|
||||
stadiaTargetFramerate: 0
|
||||
vulkanNumSwapchainBuffers: 3
|
||||
vulkanEnableSetSRGBWrite: 0
|
||||
m_SupportedAspectRatios:
|
||||
@@ -191,22 +193,6 @@ PlayerSettings:
|
||||
uIStatusBarHidden: 1
|
||||
uIExitOnSuspend: 0
|
||||
uIStatusBarStyle: 0
|
||||
iPhoneSplashScreen: {fileID: 0}
|
||||
iPhoneHighResSplashScreen: {fileID: 0}
|
||||
iPhoneTallHighResSplashScreen: {fileID: 0}
|
||||
iPhone47inSplashScreen: {fileID: 0}
|
||||
iPhone55inPortraitSplashScreen: {fileID: 0}
|
||||
iPhone55inLandscapeSplashScreen: {fileID: 0}
|
||||
iPhone58inPortraitSplashScreen: {fileID: 0}
|
||||
iPhone58inLandscapeSplashScreen: {fileID: 0}
|
||||
iPadPortraitSplashScreen: {fileID: 0}
|
||||
iPadHighResPortraitSplashScreen: {fileID: 0}
|
||||
iPadLandscapeSplashScreen: {fileID: 0}
|
||||
iPadHighResLandscapeSplashScreen: {fileID: 0}
|
||||
iPhone65inPortraitSplashScreen: {fileID: 0}
|
||||
iPhone65inLandscapeSplashScreen: {fileID: 0}
|
||||
iPhone61inPortraitSplashScreen: {fileID: 0}
|
||||
iPhone61inLandscapeSplashScreen: {fileID: 0}
|
||||
appleTVSplashScreen: {fileID: 0}
|
||||
appleTVSplashScreen2x: {fileID: 0}
|
||||
tvOSSmallIconLayers: []
|
||||
@@ -557,7 +543,7 @@ PlayerSettings:
|
||||
platformArchitecture: {}
|
||||
scriptingBackend:
|
||||
Android: 1
|
||||
Standalone: 0
|
||||
Standalone: 1
|
||||
il2cppCompilerConfiguration: {}
|
||||
managedStrippingLevel: {}
|
||||
incrementalIl2cppBuild: {}
|
||||
@@ -566,7 +552,8 @@ PlayerSettings:
|
||||
scriptingRuntimeVersion: 1
|
||||
gcIncremental: 0
|
||||
gcWBarrierValidation: 0
|
||||
apiCompatibilityLevelPerPlatform: {}
|
||||
apiCompatibilityLevelPerPlatform:
|
||||
Standalone: 6
|
||||
m_RenderingPath: 1
|
||||
m_MobileRenderingPath: 1
|
||||
metroPackageName: Template_2D
|
||||
@@ -621,6 +608,7 @@ PlayerSettings:
|
||||
XboxOnePersistentLocalStorageSize: 0
|
||||
XboxOneXTitleMemory: 8
|
||||
XboxOneOverrideIdentityName:
|
||||
XboxOneOverrideIdentityPublisher:
|
||||
vrEditorSettings:
|
||||
daydream:
|
||||
daydreamIconForeground: {fileID: 0}
|
||||
|
||||
Reference in New Issue
Block a user