Se ha denunciado esta presentación.
Se está descargando tu SlideShare. ×
Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Próximo SlideShare
UniRx完全に理解した
UniRx完全に理解した
Cargando en…3
×

Eche un vistazo a continuación

1 de 95 Anuncio

Más Contenido Relacionado

Presentaciones para usted (20)

Similares a UniTask入門 (20)

Anuncio

Más de torisoup (19)

Más reciente (20)

Anuncio

UniTask入門

  1. 1. UniTask⼊⾨ 2019/07/20 とりすーぷ
  2. 2. ⾃⼰紹介 • とりすーぷ • @toRisouP • バーチャルキャスト社 • Unityエンジニア • 最近はサーバ開発 • MagicOnion, k8s • Microsoft MVP 2018〜 • Developer Technology
  3. 3. 今回の内容「UniTask」 • UniTaskの概要 • UniTaskの使い⽅ • 機能紹介 • キャンセル管理について
  4. 4. UniTaskの概要
  5. 5. UniTaskとは •Unity向けasync/await拡張ライブラリ • Unityの標準機能ではない、⾃分で導⼊が必要な外部ライブラリ • 株式会社Cysharpさんが提供 • 主開発はneuecc⽒(UniRxの作者) • 前はUniRxの⼀部だったが、後に分離したライブラリ化された • その名残で名前空間が「UniRx.Async」のまま
  6. 6. UniTaskでできること • 「async/awaitでなんでもできるようになる」 • コルーチンをasync/awaitに置き換え • Unityイベント関数のawait • UnityEditor上でawait状況の可視化
  7. 7. 例:コルーチンの置き換え
  8. 8. 例:コルーチンの置き換え コルーチンから結果を取りだすためのデリゲート
  9. 9. 例:コルーチン -> UniTask
  10. 10. 例:コルーチン -> UniTask
  11. 11. 例:コルーチン -> UniTask 結果はそのままreturnすればOK 例外もthrowするだけ
  12. 12. UniTaskを使うメリット • コルーチンを使う必要がなくなる • より使いやすいasync/awaitですべてを記述できる • 既存のTaskよりもハイパフォーマンス • Unityに最適化されたTask-likeな機構が使える • UniRxよりはわかりやすい • ⼿続き処理で書ける、は⼗分メリット
  13. 13. 導⼊⽅法 • GitHubからunitypackageをダウンロードしてインポート • https://github.com/Cysharp/UniTask/releases • AssetStoreにはまだ公開されていない
  14. 14. UniTaskが使える条件 • C# 7以降が使えるUnityであること • Unity 2018.3 以降 • Unity 2018.2 以前はIncremental Compilerを導⼊していると使える
  15. 15. UniTaskの機能紹介
  16. 16. UniTaskが提供する機能 • UniTask型、UniTask<T>型 • UniTaskに付随するstaticメソッド群 • Unity機能のAwaiter • UniTaskTracker
  17. 17. UniTaskが提供する機能 • UniTask型、UniTask<T>型 • UniTaskに付随するstaticメソッド群 • Unity機能のAwaiter • UniTaskTracker
  18. 18. UniTask型/UniTask<T>型 UniTaskの機能紹介
  19. 19. UniTask型/UniTask<T>型 • Unity⽤に最適化されたTask-likeオブジェクト • Task/Task<T>のUnity向け実装 • Taskの基本機能はだいたい使える
  20. 20. Task型 vs UniTask型 Task UniTask 機能 Unityでは不要な機能が多い Unityで活⽤できる機能のみ オブジェクトサイズ ムダに⼤きい ⼩さい 実⾏コンテキスト管理 TaskScheduler & SynchronizationContext PlayerLoop 必要なC# version C# 5.0以上 C# 7.0以上 Task Tracker 無 Unity Editor上で利⽤可能
  21. 21. UniTask型の作り⽅ 作り⽅は主に3パターン ・async/awaitの戻り値として使う ・UniTaskCompletionSourceから作る ・Observableから変換する
  22. 22. UniTask型の作り⽅ 作り⽅は主に3パターン ・async/awaitの戻り値として使う ・UniTaskCompletionSourceから作る ・Observableから変換する
  23. 23. 例: async/awaitから作る • async/awaitの戻り値をUniTaskに書き換えるだけでOK • これだけでTask型からUniTask型に変換される
  24. 24. 例: async/awaitから作る • ジェネリック版のときも同様 • Task<T> を UniTask<T> に置き換えるだけ
  25. 25. (補⾜) UniTaskVoid型 • UniTaskの機構に乗った ”async void” • 投げっぱなし(Fire-and-forget)の⾮同期処理として使う
  26. 26. UniTask型の作り⽅ 作り⽅は主に3パターン ・async/awaitの戻り値として使う ・UniTaskCompletionSourceから作る ・Observableから変換する
  27. 27. UniTaskCompletionSource • ⼿続き処理でUniTaskを⽣成するときに使う • UniRxのAsyncSubjectとだいたい同じ
  28. 28. UniTaskCompletionSource
  29. 29. UniTask型の作り⽅ 作り⽅は主に3パターン ・async/awaitの戻り値として使う ・UniTaskCompletionSourceから作る ・Observableから変換する
  30. 30. Observableからの変換 • UniTaskとObservable(UniRx)は相互変換可能
  31. 31. 注意点1 • Observableが必ず完了する状態にすること • useFirstValue=true でTake(1)と同等になる
  32. 32. 注意点2 • UniTask -> Observable 時、 実⾏コンテキストは必ずメインスレッドになる
  33. 33. UniTask/UniTask<T>型 まとめ • 使い勝⼿は標準Taskとほとんど同じ • 既存のasyncメソッドを機械的に置換して問題ない • Observableが絡む時だけちょっと注意が必要
  34. 34. UniTaskが提供する機能 • UniTask型、UniTask<T>型 • UniTaskに付随するstaticメソッド群 • Unity機能のAwaiter • UniTaskTracker
  35. 35. Staticメソッド群 UniTaskの機能紹介
  36. 36. UniTaskに付随するstaticメソッド群 • 特殊な挙動をするUniTaskを⽣成できるメソッド群 • FactoryMethod的なやつ • ほとんどがawaitとの併⽤がメイン
  37. 37. UniTask.Run • デリゲートをThreadPool上で実⾏する • Task.Runと挙動はおなじ • await後はUnityメインスレッドに戻る(configureAwait = true の時)
  38. 38. UniTask.Delay • 指定秒数後に完了するUniTaskを⽣成する • awaitすることで「⼀定時間待つ」ができる • どのタイミングで時間計測するか選べる • デフォルトはUpdate()タイミングで計測
  39. 39. UniTask.DelayFrame • 指定フレーム後に完了するUniTaskを⽣成する • awaitすることで「⼀定フレーム待つ」ができる • どのタイミングで計測するか選べる • デフォルトはUpdate()タイミング
  40. 40. UniTask.Yield() • 指定のタイミングで1フレーム待機する • 処理をメインスレッドに戻すことにも使える • 引数なしの場合はUpdateタイミングで1フレーム待機になる
  41. 41. UniTask.Yield
  42. 42. UniTask.SwitchToThreadPool • 実⾏コンテキストをThreadPoolに切り替える • awaitするとそれ以降がThreadPool上での処理になる • 似たものでSwitchToTaskPoolがあるが、こっちは⾮推奨
  43. 43. UniTask.SwitchToThreadPool
  44. 44. UniTask.SwitchToMainThread • 実⾏コンテキストをメインスレッドに切り替える • awaitするとそれ以降がメインスレッド上での処理になる • UniTask.Yield(PlayerLoopTiming.Update)と微妙に挙動が異なる
  45. 45. UniTask.WaitUntil / UniTask.WaitWhile • 条件を満たすまで/満たさなくなるまで待機する • コルーチンのWaitUntil/WaitWhileと同等 • どのPlayerLoopタイミングでチェックするかも指定できる
  46. 46. UniTask.WaitUntil / UniTask.WaitWhile
  47. 47. UniTask.WaitUntilValueChanged • 指定のオブジェクトのパラメータが変動するまで待機する • UniRxのObserveEveryValueChangedと同じ • 対象は弱参照で保持され、GCされるとawaitはキャンセルされる
  48. 48. UniTask.WhenAll • 指定のUniTaskがすべて完了するまで待機する • UniTask<T>の型がすべて⼀致していなくてもOK
  49. 49. UniTask.WhenAll
  50. 50. UniTask.WhenAny • 複数のUniTaskのうちどれか1つが先に完了するまで待機する
  51. 51. Staticメソッド群 まとめ • Unity向けに調整された機能が多くて便利 • 標準Taskとくらべて使いやすくなってたりもする • まだまだあるけど量が多いので省略
  52. 52. UniTaskが提供する機能 • UniTask型、UniTask<T>型 • UniTaskに付随するstaticメソッド群 • Unity機能のAwaiter • UniTaskTracker
  53. 53. Awaiter UniTaskの機能紹介
  54. 54. Awaiterって何 • オブジェクトのawaitに必要なヤツ • あるオブジェクトにGetAwaiter()メソッドが実装されており、 そこからAwaiterが取得できるならそのオブジェクトはawaitができる
  55. 55. 補⾜:GetAwaiter() • Awaiterを取得するためのメソッド • クラスメソッドだけでなく、拡張メソッドでもOK • ⾃前で実装すればなんでもawaitできるようになる awaitにカーソルを合わせて定義元を参照するとどのGetAwaiter()が呼ばれるかわかる
  56. 56. UniTaskとAwaiter • UniTaskはUnityのあらゆるオブジェクトの Awaiterを提供してくれる
  57. 57. UniTaskが提供するAwaiter • コルーチン • AsyncOperation • uGUI Event • Unityコールバック • JobHandle • UnityEvent
  58. 58. コルーチンのAwaiter • IEnumeratorをawaitするとコルーチンとして実⾏&待機する
  59. 59. コルーチンのAwaiter
  60. 60. (補⾜)コルーチン上でUniTask • ToCoroutine()でUniTaskをコルーチン化もできる
  61. 61. AsyncOperationのAwaiter
  62. 62. AsyncOperationのAwaiter • ConfigureAwaitで進⾏状況取得可能
  63. 63. uGUI EventのAwaiter ※using UniRx.Async.Triggers が必要
  64. 64. UnityコールバックのAwaiter • MonoBehaviourに⾶んでくるイベントコールバックのこと ※using UniRx.Async.Triggers が必要
  65. 65. Awaiter まとめ • Unityのあらゆる要素がawait可能になる • コルーチンの上位互換としてasync/awaitが利⽤可能になる
  66. 66. UniTaskが提供する機能 • UniTask型、UniTask<T>型 • UniTaskに付随するstaticメソッド群 • Unity機能のAwaiter • UniTaskTracker
  67. 67. UniTaskTracker UniTaskの機能紹介
  68. 68. UniTaskTracker • await中のUniTaskを可視化するEditor拡張 • Unity Editorの [Window] -> [UniRx] -> [UniTask Tracker] • UniTaskがリークしていないか確認できる
  69. 69. UniTaskとキャンセル
  70. 70. ⾮同期処理とキャンセル • ⾮同期処理はキャンセルを常に考慮しなくてはいけない • もろもろの理由で不要になった時に 実⾏中の処理を⽌めないといけない
  71. 71. UniTaskとキャンセル • UniTaskを使う上でも当然キャンセルの実装が必要 • リソースの解放、適切なタイミングでの停⽌、漏れのない中断、 これらは⼈間が考えて実装する必要がある
  72. 72. 適切にキャンセルするために • CancellationToken • OperationCanceledException
  73. 73. 適切にキャンセルするために • CancellationToken • OperationCanceledException
  74. 74. CancellationToken • ⾮同期処理にキャンセルを通知するためのC#標準機能 • 「キャンセル要求されたか?」のフラグを持つオブジェクト
  75. 75. CancellationToken
  76. 76. CancellationToken CanellationTokenSourceから⽣成
  77. 77. CancellationToken if⽂で判定 if( IsCancellationRequested ) throw new OperationCanceledException(); の省略記法
  78. 78. 補⾜: GetCancellationTokenOnDestroy()
  79. 79. UniTaskとCancellationToken • UniTaskはCancellationTokenを使ってキャンセル判定を⾏う • キャンセル要求がくるとUniTaskはキャンセル状態になる • await中の場合はそこで処理が終了しawait以降は実⾏されない
  80. 80. CancellationTokenは省略しない • 「めんどくさいからキャンセル処理を書かない」はNG
  81. 81. Tokenが渡せない処理の場合のキャンセル • CancellationTokenの状態を⼿動で確認する • どのタイミングで処理を⽌めるのか、は⾃分で考える • キャンセル時はOperationCanceledExceptionを発⾏すればOK
  82. 82. ⼿動でキャンセルチェックする例
  83. 83. 適切にキャンセルするために • CancellationToken • OperationCanceledException
  84. 84. OperationCanceledException • UniTaskをキャンセル状態にするための特殊扱いな例外 • この例外が投げられるとUniTaskは「キャンセル状態」になる • この例外はエラーログに出ない
  85. 85. Throwするタイミング • キャンセル要求が外部からされた時にthrowする • 外から「処理を⽌めてね」って⾔われた時に投げる例外 • ⾃⼰判断で勝⼿に投げてよい例外ではない
  86. 86. キャンセル要求 • キャンセル要求はCancellationTokenを通じて送られる • ThrowIfCancellationRequested()が便利
  87. 87. キャンセルを上流まで伝播させる • この例外は上流まで“貫通”させる • try-catchを書くときはOperationCanceledExceptionだけ 素通りするようにしておく
  88. 88. キャンセルを上流まで伝播させる • この例外は上流まで“貫通”させる • try-catchを書くときはOperationCanceledExceptionだけ 素通りするようにしておく
  89. 89. 悪⽤しない • キャンセル⽤途以外では利⽤しないこと • 本来の⽤途とは別の使い⽅をすると、そこから負債になる • 「処理に失敗したときにエラーログに出したくないから、 OperationCanceledException使っちゃおう」みたいなのはNG
  90. 90. UniTaskとキャンセル まとめ • CancellationTokenは可能な限り指定する • OperationCanceledExceptionは特殊なので扱いに注意
  91. 91. 最後のまとめ
  92. 92. UniTask、結局何に使えばいいの? • 深く考えず使えそうなところでどんどん使おう • コルーチンの代替として使える • 他のコンポーネントが処理を終えるのを待つ、とかにも使える • むしろUniTaskが使えないことがストレスになるくらいには便利
  93. 93. 他の⾮同期処理との使い分けは? • async/awaitを使うなら、UniTaskをまず使う • 理由が無い限り標準Taskは使わない • UniRx(Observable)は⽤途に応じて使う • Observableはイベント処理や、結果が複数になる⾮同期処理向け • Observableもawait可能だし、UniTaskとの相互変換もできる
  94. 94. まとめ • UniTaskめっちゃ便利だから使おう!!!! • あと今回の話の補⾜的なのをUniBook11に書きました • さらにUniRx+UniTask本、マダカイテルカラマッテネ…

×