You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardexpand all lines: README.MD
+12-10
Original file line number
Diff line number
Diff line change
@@ -6,21 +6,24 @@ With this library you can:
6
6
* Seamlessly integrate with Task-based and async APIs
7
7
* Integrate with IEnumerator-based coroutines and YieldInstructions
8
8
* Easily switch sync contexts (main to background and vice-versa)
9
-
* Define your own custom await instructions (allocation free)
9
+
* Define your own custom await instructions (allocation free, no boxing!)
10
10
* Return results at the end of your coroutine
11
11
# Performance
12
-
Rest assured; UnityAsync coroutines will generally always perform better than Unity's built-in coroutines because:
12
+
Rest assured; UnityAsync coroutines will generally perform better than Unity's built-in coroutines because:
13
13
* They rarely cause heap allocations
14
14
* They don't weave in and out of native code
15
15
* They don't rely on a monolithic state machine
16
16
17
-
Benchmarks with 100,000 simultaneous update loop coroutines show a performance increase of over 150% (that's 2.5x), and this doesn't test against `YieldInstructions`. A test with uncached `WaitForSeconds`using a random number as input yields a performance increase of over 290% (3.9x). The benchmarks included the time it took to instantiate the coroutines.
17
+
Comparing with standard `yield return null` update loops, performance is 150% improved. Uncached `WaitForSeconds`loops yield a performance increase of over 290%. The benchmarks included the time it took to instantiate the coroutines.
18
18
19
-
The single downside is that if you want to nest multiple coroutines inside each other, you must store a reference to them, which means returning a `Task` object. This causes a 336 byte heap allocation, whereas Unity's coroutines allocate less memory (but they still allocate on the heap). This often isn't a problem because nested coroutines rarely execute in their entirety every frame and these allocations are still tiny.
19
+
The one caveat is, in order to store the coroutine, a `Task` object must be allocated. A `Task` object is a bigger allocation compared to a `Coroutine` object. No way around it, if you want to integrate with `Task`-based APIs, you need to use `Tasks`. Often, you just need to fire the coroutine and forget about it, and in such cases, simply use `void` return type to avoid allocations altogether.
20
20
21
21
# Usage
22
+
## Installation
23
+
Clone the repo into your assets folder or download the [latest release](https://github.com/muckSponge/UnityAsync/releases/latest) and open the .unitypackage.
24
+
22
25
## Replacing existing coroutines
23
-
Let's say we want to replace a pretty straight-forward update loop IEnumerator coroutine:
26
+
Let's say we want to replace a pretty straight-forward update loop `IEnumerator` coroutine:
24
27
```c#
25
28
usingUnityEngine;
26
29
usingSystem.Collections;
@@ -41,7 +44,7 @@ void Start()
41
44
...
42
45
43
46
```
44
-
UnityAsync coroutines are defined by async methods, which can return void, `Task`, or `Task<TResult>`:
47
+
UnityAsync coroutines are defined by async methods, which can return `void`, `Task`, or `Task<TResult>`:
45
48
```c#
46
49
usingUnityEngine;
47
50
usingUnityAsync;
@@ -100,10 +103,10 @@ async void Start()
100
103
101
104
...
102
105
```
103
-
We are awaiting the result in Start so it needs to be an async method (this doesn't impact on how Unity calls it). We now return `Task<int>` and the result is available after 10 frames.
106
+
We are awaiting the result in `Start()` so it needs to be an async method (this doesn't impact on how Unity calls it). We now return `Task<int>` and the result is available after 10 frames.
104
107
105
108
## Switching contexts
106
-
Sometimes you'll want to perform some task on the thread pool and return to the main thread once this is completed without blocking. This could be done via `Task.ConfigureAwait` but now you can await directly on a `SynchronizationContext` which makes it super easy to swap back and forth:
109
+
Sometimes you'll want to perform some task on the thread pool and return to the main thread once this is completed without blocking. This could be done via `Task.ConfigureAwait()` but now you can await directly on a `SynchronizationContext` which makes it super easy to swap back and forth:
107
110
```c#
108
111
usingUnityAsync;
109
112
@@ -161,6 +164,7 @@ async void Start()
161
164
...
162
165
163
166
```
167
+
164
168
## Yielding a task
165
169
You may run into a situation where some of your coroutine code is async, but it is called from an `IEnumerator`. In such a situation you can use `Task.AsYieldInstruction` or `Task<TResult>.AsYieldInstruction`.
166
170
```c#
@@ -190,7 +194,6 @@ async Task WaitForMouse()
190
194
```
191
195
192
196
# Await instructions / awaitables
193
-
194
197
Built-in:
195
198
*`WaitForFrames`
196
199
*`WaitForSeconds`
@@ -246,7 +249,6 @@ public struct WaitForTimeSpan : IAwaitInstruction
246
249
```
247
250
248
251
# Usage with Unity EditorTests (unit tests with NUnit)
249
-
250
252
When running unit tests, `AsyncManager` is not automatically initialized. Call `AsyncManager.InitializeForEditorTests()` in your test OneTimeSetUp method, for example like this:
0 commit comments