Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
UniTask入門
Search
torisoup
July 20, 2019
Technology
6
21k
UniTask入門
Unity++ 〜ショートセッション勉強会 presented by Unity部〜
https://meetup.unity3d.jp/jp/events/1112
torisoup
July 20, 2019
Tweet
Share
More Decks by torisoup
See All by torisoup
もうつまらないとは言わせない!「わかりやすい」プレゼンを作るために気をつけたいこと
torisoup
8
2.6k
Unityの本を出した話
torisoup
3
780
VRMの紹介&VRM勉強会
torisoup
0
140
Unityにおける設計パターン
torisoup
17
50k
Unity 1week でつくったゲームにAIを実装してみる
torisoup
1
3.8k
PUN2をasync/awaitで使えるライブラリつくってみた「Pun2Task」
torisoup
0
1.3k
UniTaskの使い方2020 / UniTask2020
torisoup
43
23k
ARでVRアバターを表示するシステムを構築しよう
torisoup
2
580
Unity講習資料
torisoup
8
9.2k
Other Decks in Technology
See All in Technology
MCP認可の現在地と自律型エージェント対応に向けた課題 / MCP Authorization Today and Challenges to Support Autonomous Agents
yokawasa
5
2.5k
Engineering Failure-Resilient Systems
infraplumber0
0
120
JAWS AI/ML #30 AI コーディング IDE "Kiro" を触ってみよう
inariku
3
390
Amazon Inspector コードセキュリティで手軽に実現するシフトレフト
maimyyym
0
130
ファッションコーディネートアプリ「WEAR」における、Vertex AI Vector Searchを利用したレコメンド機能の開発・運用で得られたノウハウの紹介
zozotech
PRO
0
560
形式手法特論:位相空間としての並行プログラミング #kernelvm / Kernel VM Study Tokyo 18th
ytaka23
3
1.5k
Claude Codeは仕様駆動の夢を見ない
gotalab555
23
7k
いかにして命令の入れ替わりについて心配するのをやめ、メモリモデルを愛するようになったか(改)
nullpo_head
7
2.7k
React Server ComponentsでAPI不要の開発体験
polidog
PRO
0
330
Google Cloud で学ぶデータエンジニアリング入門 2025年版 #GoogleCloudNext / 20250805
kazaneya
PRO
24
5.9k
Amazon GuardDuty での脅威検出:脅威検出の実例から学ぶ
kintotechdev
0
120
オブザーバビリティ文化を組織に浸透させるには / install observability culture
mackerelio
0
150
Featured
See All Featured
KATA
mclloyd
32
14k
Why You Should Never Use an ORM
jnunemaker
PRO
58
9.5k
Rails Girls Zürich Keynote
gr2m
95
14k
The Straight Up "How To Draw Better" Workshop
denniskardys
236
140k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
667
120k
Faster Mobile Websites
deanohume
309
31k
Done Done
chrislema
185
16k
Agile that works and the tools we love
rasmusluckow
329
21k
Raft: Consensus for Rubyists
vanstee
140
7.1k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
8
880
The Art of Programming - Codeland 2020
erikaheidi
54
13k
Testing 201, or: Great Expectations
jmmastey
45
7.6k
Transcript
UniTask⼊⾨ 2019/07/20 とりすーぷ
⾃⼰紹介 • とりすーぷ • @toRisouP • バーチャルキャスト社 • Unityエンジニア •
最近はサーバ開発 • MagicOnion, k8s • Microsoft MVP 2018〜 • Developer Technology
今回の内容「UniTask」 • UniTaskの概要 • UniTaskの使い⽅ • 機能紹介 • キャンセル管理について
UniTaskの概要
UniTaskとは •Unity向けasync/await拡張ライブラリ • Unityの標準機能ではない、⾃分で導⼊が必要な外部ライブラリ • 株式会社Cysharpさんが提供 • 主開発はneuecc⽒(UniRxの作者) • 前はUniRxの⼀部だったが、後に分離したライブラリ化された
• その名残で名前空間が「UniRx.Async」のまま
UniTaskでできること • 「async/awaitでなんでもできるようになる」 • コルーチンをasync/awaitに置き換え • Unityイベント関数のawait • UnityEditor上でawait状況の可視化
例:コルーチンの置き換え
例:コルーチンの置き換え コルーチンから結果を取りだすためのデリゲート
例:コルーチン -> UniTask
例:コルーチン -> UniTask
例:コルーチン -> UniTask 結果はそのままreturnすればOK 例外もthrowするだけ
UniTaskを使うメリット • コルーチンを使う必要がなくなる • より使いやすいasync/awaitですべてを記述できる • 既存のTaskよりもハイパフォーマンス • Unityに最適化されたTask-likeな機構が使える •
UniRxよりはわかりやすい • ⼿続き処理で書ける、は⼗分メリット
導⼊⽅法 • GitHubからunitypackageをダウンロードしてインポート • https://github.com/Cysharp/UniTask/releases • AssetStoreにはまだ公開されていない
UniTaskが使える条件 • C# 7以降が使えるUnityであること • Unity 2018.3 以降 • Unity
2018.2 以前はIncremental Compilerを導⼊していると使える
UniTaskの機能紹介
UniTaskが提供する機能 • UniTask型、UniTask<T>型 • UniTaskに付随するstaticメソッド群 • Unity機能のAwaiter • UniTaskTracker
UniTaskが提供する機能 • UniTask型、UniTask<T>型 • UniTaskに付随するstaticメソッド群 • Unity機能のAwaiter • UniTaskTracker
UniTask型/UniTask<T>型 UniTaskの機能紹介
UniTask型/UniTask<T>型 • Unity⽤に最適化されたTask-likeオブジェクト • Task/Task<T>のUnity向け実装 • Taskの基本機能はだいたい使える
Task型 vs UniTask型 Task UniTask 機能 Unityでは不要な機能が多い Unityで活⽤できる機能のみ オブジェクトサイズ ムダに⼤きい
⼩さい 実⾏コンテキスト管理 TaskScheduler & SynchronizationContext PlayerLoop 必要なC# version C# 5.0以上 C# 7.0以上 Task Tracker 無 Unity Editor上で利⽤可能
UniTask型の作り⽅ 作り⽅は主に3パターン ・async/awaitの戻り値として使う ・UniTaskCompletionSourceから作る ・Observableから変換する
UniTask型の作り⽅ 作り⽅は主に3パターン ・async/awaitの戻り値として使う ・UniTaskCompletionSourceから作る ・Observableから変換する
例: async/awaitから作る • async/awaitの戻り値をUniTaskに書き換えるだけでOK • これだけでTask型からUniTask型に変換される
例: async/awaitから作る • ジェネリック版のときも同様 • Task<T> を UniTask<T> に置き換えるだけ
(補⾜) UniTaskVoid型 • UniTaskの機構に乗った ”async void” • 投げっぱなし(Fire-and-forget)の⾮同期処理として使う
UniTask型の作り⽅ 作り⽅は主に3パターン ・async/awaitの戻り値として使う ・UniTaskCompletionSourceから作る ・Observableから変換する
UniTaskCompletionSource • ⼿続き処理でUniTaskを⽣成するときに使う • UniRxのAsyncSubjectとだいたい同じ
UniTaskCompletionSource
UniTask型の作り⽅ 作り⽅は主に3パターン ・async/awaitの戻り値として使う ・UniTaskCompletionSourceから作る ・Observableから変換する
Observableからの変換 • UniTaskとObservable(UniRx)は相互変換可能
注意点1 • Observableが必ず完了する状態にすること • useFirstValue=true でTake(1)と同等になる
注意点2 • UniTask -> Observable 時、 実⾏コンテキストは必ずメインスレッドになる
UniTask/UniTask<T>型 まとめ • 使い勝⼿は標準Taskとほとんど同じ • 既存のasyncメソッドを機械的に置換して問題ない • Observableが絡む時だけちょっと注意が必要
UniTaskが提供する機能 • UniTask型、UniTask<T>型 • UniTaskに付随するstaticメソッド群 • Unity機能のAwaiter • UniTaskTracker
Staticメソッド群 UniTaskの機能紹介
UniTaskに付随するstaticメソッド群 • 特殊な挙動をするUniTaskを⽣成できるメソッド群 • FactoryMethod的なやつ • ほとんどがawaitとの併⽤がメイン
UniTask.Run • デリゲートをThreadPool上で実⾏する • Task.Runと挙動はおなじ • await後はUnityメインスレッドに戻る(configureAwait = true の時)
UniTask.Delay • 指定秒数後に完了するUniTaskを⽣成する • awaitすることで「⼀定時間待つ」ができる • どのタイミングで時間計測するか選べる • デフォルトはUpdate()タイミングで計測
UniTask.DelayFrame • 指定フレーム後に完了するUniTaskを⽣成する • awaitすることで「⼀定フレーム待つ」ができる • どのタイミングで計測するか選べる • デフォルトはUpdate()タイミング
UniTask.Yield() • 指定のタイミングで1フレーム待機する • 処理をメインスレッドに戻すことにも使える • 引数なしの場合はUpdateタイミングで1フレーム待機になる
UniTask.Yield
UniTask.SwitchToThreadPool • 実⾏コンテキストをThreadPoolに切り替える • awaitするとそれ以降がThreadPool上での処理になる • 似たものでSwitchToTaskPoolがあるが、こっちは⾮推奨
UniTask.SwitchToThreadPool
UniTask.SwitchToMainThread • 実⾏コンテキストをメインスレッドに切り替える • awaitするとそれ以降がメインスレッド上での処理になる • UniTask.Yield(PlayerLoopTiming.Update)と微妙に挙動が異なる
UniTask.WaitUntil / UniTask.WaitWhile • 条件を満たすまで/満たさなくなるまで待機する • コルーチンのWaitUntil/WaitWhileと同等 • どのPlayerLoopタイミングでチェックするかも指定できる
UniTask.WaitUntil / UniTask.WaitWhile
UniTask.WaitUntilValueChanged • 指定のオブジェクトのパラメータが変動するまで待機する • UniRxのObserveEveryValueChangedと同じ • 対象は弱参照で保持され、GCされるとawaitはキャンセルされる
UniTask.WhenAll • 指定のUniTaskがすべて完了するまで待機する • UniTask<T>の型がすべて⼀致していなくてもOK
UniTask.WhenAll
UniTask.WhenAny • 複数のUniTaskのうちどれか1つが先に完了するまで待機する
Staticメソッド群 まとめ • Unity向けに調整された機能が多くて便利 • 標準Taskとくらべて使いやすくなってたりもする • まだまだあるけど量が多いので省略
UniTaskが提供する機能 • UniTask型、UniTask<T>型 • UniTaskに付随するstaticメソッド群 • Unity機能のAwaiter • UniTaskTracker
Awaiter UniTaskの機能紹介
Awaiterって何 • オブジェクトのawaitに必要なヤツ • あるオブジェクトにGetAwaiter()メソッドが実装されており、 そこからAwaiterが取得できるならそのオブジェクトはawaitができる
補⾜:GetAwaiter() • Awaiterを取得するためのメソッド • クラスメソッドだけでなく、拡張メソッドでもOK • ⾃前で実装すればなんでもawaitできるようになる awaitにカーソルを合わせて定義元を参照するとどのGetAwaiter()が呼ばれるかわかる
UniTaskとAwaiter • UniTaskはUnityのあらゆるオブジェクトの Awaiterを提供してくれる
UniTaskが提供するAwaiter • コルーチン • AsyncOperation • uGUI Event • Unityコールバック
• JobHandle • UnityEvent
コルーチンのAwaiter • IEnumeratorをawaitするとコルーチンとして実⾏&待機する
コルーチンのAwaiter
(補⾜)コルーチン上でUniTask • ToCoroutine()でUniTaskをコルーチン化もできる
AsyncOperationのAwaiter
AsyncOperationのAwaiter • ConfigureAwaitで進⾏状況取得可能
uGUI EventのAwaiter ※using UniRx.Async.Triggers が必要
UnityコールバックのAwaiter • MonoBehaviourに⾶んでくるイベントコールバックのこと ※using UniRx.Async.Triggers が必要
Awaiter まとめ • Unityのあらゆる要素がawait可能になる • コルーチンの上位互換としてasync/awaitが利⽤可能になる
UniTaskが提供する機能 • UniTask型、UniTask<T>型 • UniTaskに付随するstaticメソッド群 • Unity機能のAwaiter • UniTaskTracker
UniTaskTracker UniTaskの機能紹介
UniTaskTracker • await中のUniTaskを可視化するEditor拡張 • Unity Editorの [Window] -> [UniRx] ->
[UniTask Tracker] • UniTaskがリークしていないか確認できる
UniTaskとキャンセル
⾮同期処理とキャンセル • ⾮同期処理はキャンセルを常に考慮しなくてはいけない • もろもろの理由で不要になった時に 実⾏中の処理を⽌めないといけない
UniTaskとキャンセル • UniTaskを使う上でも当然キャンセルの実装が必要 • リソースの解放、適切なタイミングでの停⽌、漏れのない中断、 これらは⼈間が考えて実装する必要がある
適切にキャンセルするために • CancellationToken • OperationCanceledException
適切にキャンセルするために • CancellationToken • OperationCanceledException
CancellationToken • ⾮同期処理にキャンセルを通知するためのC#標準機能 • 「キャンセル要求されたか?」のフラグを持つオブジェクト
CancellationToken
CancellationToken CanellationTokenSourceから⽣成
CancellationToken if⽂で判定 if( IsCancellationRequested ) throw new OperationCanceledException(); の省略記法
補⾜: GetCancellationTokenOnDestroy()
UniTaskとCancellationToken • UniTaskはCancellationTokenを使ってキャンセル判定を⾏う • キャンセル要求がくるとUniTaskはキャンセル状態になる • await中の場合はそこで処理が終了しawait以降は実⾏されない
CancellationTokenは省略しない • 「めんどくさいからキャンセル処理を書かない」はNG
Tokenが渡せない処理の場合のキャンセル • CancellationTokenの状態を⼿動で確認する • どのタイミングで処理を⽌めるのか、は⾃分で考える • キャンセル時はOperationCanceledExceptionを発⾏すればOK
⼿動でキャンセルチェックする例
適切にキャンセルするために • CancellationToken • OperationCanceledException
OperationCanceledException • UniTaskをキャンセル状態にするための特殊扱いな例外 • この例外が投げられるとUniTaskは「キャンセル状態」になる • この例外はエラーログに出ない
Throwするタイミング • キャンセル要求が外部からされた時にthrowする • 外から「処理を⽌めてね」って⾔われた時に投げる例外 • ⾃⼰判断で勝⼿に投げてよい例外ではない
キャンセル要求 • キャンセル要求はCancellationTokenを通じて送られる • ThrowIfCancellationRequested()が便利
キャンセルを上流まで伝播させる • この例外は上流まで“貫通”させる • try-catchを書くときはOperationCanceledExceptionだけ 素通りするようにしておく
キャンセルを上流まで伝播させる • この例外は上流まで“貫通”させる • try-catchを書くときはOperationCanceledExceptionだけ 素通りするようにしておく
悪⽤しない • キャンセル⽤途以外では利⽤しないこと • 本来の⽤途とは別の使い⽅をすると、そこから負債になる • 「処理に失敗したときにエラーログに出したくないから、 OperationCanceledException使っちゃおう」みたいなのはNG
None
UniTaskとキャンセル まとめ • CancellationTokenは可能な限り指定する • OperationCanceledExceptionは特殊なので扱いに注意
最後のまとめ
UniTask、結局何に使えばいいの? • 深く考えず使えそうなところでどんどん使おう • コルーチンの代替として使える • 他のコンポーネントが処理を終えるのを待つ、とかにも使える • むしろUniTaskが使えないことがストレスになるくらいには便利
他の⾮同期処理との使い分けは? • async/awaitを使うなら、UniTaskをまず使う • 理由が無い限り標準Taskは使わない • UniRx(Observable)は⽤途に応じて使う • Observableはイベント処理や、結果が複数になる⾮同期処理向け •
Observableもawait可能だし、UniTaskとの相互変換もできる
まとめ • UniTaskめっちゃ便利だから使おう!!!! • あと今回の話の補⾜的なのをUniBook11に書きました • さらにUniRx+UniTask本、マダカイテルカラマッテネ…