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.4k
Unityの本を出した話
torisoup
3
740
VRMの紹介&VRM勉強会
torisoup
0
120
Unityにおける設計パターン
torisoup
17
48k
Unity 1week でつくったゲームにAIを実装してみる
torisoup
2
3.7k
PUN2をasync/awaitで使えるライブラリつくってみた「Pun2Task」
torisoup
0
1.2k
UniTaskの使い方2020 / UniTask2020
torisoup
38
22k
ARでVRアバターを表示するシステムを構築しよう
torisoup
2
540
Unity講習資料
torisoup
8
9.1k
Other Decks in Technology
See All in Technology
飲食店予約台帳を支えるインタラクティブ UI 設計と実装
siropaca
7
1.7k
2/18/25: Java meets AI: Build LLM-Powered Apps with LangChain4j
edeandrea
PRO
0
110
エンジニアの育成を支える爆速フィードバック文化
sansantech
PRO
3
1.1k
Oracle Base Database Service 技術詳細
oracle4engineer
PRO
6
57k
速くて安いWebサイトを作る
nishiharatsubasa
10
12k
30分でわかる『アジャイルデータモデリング』
hanon52_
9
2.6k
リアルタイム分析データベースで実現する SQLベースのオブザーバビリティ
mikimatsumoto
0
1.3k
Developer Summit 2025 [14-D-1] Yuki Hattori
yuhattor
19
6.2k
インフラをつくるとはどういうことなのか、 あるいはPlatform Engineeringについて
nwiizo
5
2.6k
Larkご案内資料
customercloud
PRO
0
650
N=1から解き明かすAWS ソリューションアーキテクトの魅力
kiiwami
0
130
Oracle Cloud Infrastructure:2025年2月度サービス・アップデート
oracle4engineer
PRO
1
200
Featured
See All Featured
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
30
2.2k
How to Think Like a Performance Engineer
csswizardry
22
1.3k
The World Runs on Bad Software
bkeepers
PRO
67
11k
Git: the NoSQL Database
bkeepers
PRO
427
64k
[RailsConf 2023] Rails as a piece of cake
palkan
53
5.2k
Code Reviewing Like a Champion
maltzj
521
39k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
248
1.3M
Build The Right Thing And Hit Your Dates
maggiecrowley
34
2.5k
Bash Introduction
62gerente
611
210k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
120k
The Cult of Friendly URLs
andyhume
78
6.2k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
21
2.5k
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本、マダカイテルカラマッテネ…