3. UniTask<T> / UniTask
• Lightweight alternative of Task<T>, zero allocation and fast excution
for zero overhead async/await integrate with Unity
• .WithCancellation enables Cancel, GetCancellationTokenOnDestroy
synchornizes with lifetime of GameObject
• .ToUniTask accepts progress callback(and all options), Progress.Create
is a lightweight alternative of IProgress<T>
var asset2 = await Resources.LoadAsync<TextAsset>("bar")
.WithCancellation(this.GetCancellationTokenOnDestroy());
var asset3 = await Resources.LoadAsync<TextAsset>("baz")
.ToUniTask(Progress.Create<float>(x => Debug.Log(x)));
4. • Delay
• Yield
• WaitFor series
await UniTask.DelayFrame(100);
// replacement of yield return new WaitForSeconds/WaitForSecondsRealtime
await UniTask.Delay(TimeSpan.FromSeconds(10), ignoreTimeScale: false);
// (PreUpdate, Update, LateUpdate, etc...)
await UniTask.Yield(PlayerLoopTiming.PreLateUpdate);
// replacement of yield return null
await UniTask.Yield();
await UniTask.NextFrame();
await UniTask.WaitForEndOfFrame(this); // this is MonoBehaviour
await UniTask.WaitForFixedUpdate();
await UniTask.WaitUntil(() => isActive == false);
await UniTask.WaitUntilValueChanged(this, x => x.isActive);
5. • Coroutine & Task
• Switch Thread
• WhenAll
// You can await IEnumerator coroutines
await FooCoroutineEnumerator();
// You can await a standard task
await Task.Run(() => 100);
// Multithreading, run on ThreadPool under this code
await UniTask.SwitchToThreadPool();
/* work on ThreadPool */
// return to MainThread
await UniTask.SwitchToMainThread();
/* work on main thread */
// concurrent async-wait and get results easily by tuple syntax
var (google, bing, yahoo) = await UniTask.WhenAll(task1, task2, task3);
// shorthand of WhenAll, tuple can await directly
var (google2, bing2, yahoo2) = await (task1, task2, task3);
6. • Timeout
• TimeoutController (optimized)
var cts = new CancellationTokenSource();
cts.CancelAfterSlim(TimeSpan.FromSeconds(5)); // 5sec timeout.
try
{
await UnityWebRequest.Get("http://foo").SendWebRequest().WithCancellation(cts.Token);
}
catch (OperationCanceledException ex)
{
if (ex.CancellationToken == cts.Token) { ... } // 5sec timeout
}
TimeoutController timeoutController = new TimeoutController(); // setup to field for reuse.
async UniTask FooAsync()
{
try
{
// you can pass timeoutController.Timeout(TimeSpan) to cancellationToken.
await UnityWebRequest.Get("http://foo").SendWebRequest()
.WithCancellation(timeoutController.Timeout(TimeSpan.FromSeconds(5)));
timeoutController.Reset(); // call Reset(Stop timeout timer and ready for reuse) when succeed.
}
catch (OperationCanceledException ex)
{
if (timeoutController.IsTimeout()) { ... } // timeout
}
}
7. • Progress (.Create(), IProgress<>)
• Better than System.Progress
var progress = Progress.Create<float>(x => Debug.Log(x));
var request = await UnityWebRequest.Get("http://google.co.jp").SendWebRequest()
.ToUniTask(progress: progress);
public class Foo : MonoBehaviour, IProgress<float>
{
public void Report(float value)
{
UnityEngine.Debug.Log(value);
}
public async UniTaskVoid WebRequest()
{
var request = await UnityWebRequest.Get("http://google.co.jp").SendWebRequest()
.ToUniTask(progress: this); // pass this
}
}
11. AsyncEnumerable and Async LINQ
• UniTaskAsyncEnumerable implements asynchronous LINQ, similar to
LINQ in IEnumerable<T> or Rx in IObservable<T>. All standard LINQ
query operators can be applied to asynchronous streams.
12. Awaitable Events
• All UGUI implements ***AsAsyncEnumerable
• All MonoBehaviour message events can convert async-streams
13. • AsyncReactiveProperty, AsyncReadOnlyReactiveProperty
• ReactiveProperty.
• BindTo extension method: binding asynchronous stream values to Unity
components(Text/Selectable/TMP/Text).
var rp = new AsyncReactiveProperty<int>(99);
// AsyncReactiveProperty itself is IUniTaskAsyncEnumerable, you can query by LINQ
rp.ForEachAsync(x => { Debug.Log(x); },
this.GetCancellationTokenOnDestroy())
.Forget();
rp.Value = 10; // push 10 to all subscriber
rp.Value = 11; // push 11 to all subscriber
// WithoutCurrent ignore initial value; BindTo bind stream value to unity components.
rp.WithoutCurrent().BindTo(this.textComponent);
await rp.WaitAsync(); // wait until next value set
14. Channel
• 取代 System.Threading.Tasks.Channels,類似 GoLang Channel
• Currently it only supports multiple-producer, single-consumer
unbounded channels.
• For producer(.Writer), use TryWrite to push value and TryComplete to
complete channel.
• For consumer(.Reader), use TryRead, WaitToReadAsync, ReadAsync,
Completion and ReadAllAsync to read queued messages