Upgrade to Pro — share decks privately, control downloads, hide ads and more …

三種の神器とMVRPパターン / xrdnk-three-sacred-treasures-and-mvrp-pattern

270b0c7883545117a9a618dc7ca7cc83?s=47 Denik
April 20, 2021

三種の神器とMVRPパターン / xrdnk-three-sacred-treasures-and-mvrp-pattern

クローズドコミュニティ内で行った三種の神器(UniRx, UniTask, Extenject)とMVRPパターンの簡単なハンズオンです.(Bonus Track : VContainer)

270b0c7883545117a9a618dc7ca7cc83?s=128

Denik

April 20, 2021
Tweet

Transcript

  1. Three-Sacred-Treasures and MV(R)P Pattern 三種の神器とMV(R)Pパターン Workshop and Hands-on

  2. 教材サンプルの動画 以下のリポジトリを事前にcloneしてください. https://github.com/xrdnk/Three-Sacred-Treasures-Hands-on

  3. アジェンダ ➢ 軽く自己紹介 ➢ 本ハンズオンの目的 ➢ UniRx (Unity Reactive Extension)

    and MV(R)P Pattern ➢ UniTask (an efficient allocation free async/await integration for Unity) ➢ Extenject (Zenject Dependency Injection IOC / ex: Zenject) and DI Pattern ➢ 終わりに ➢ Bonus Track : VContainer (extra fast Dependency Injection for Unity)
  4. 自己紹介

  5. PERSONAL INFO 😀 Name Denik Hatsushika Twitter XR Account: xrdnk

    GitHub xrdnk Blog デニッキ!
  6. 本ハンズオンの目的

  7. 皆さんは神クラスを 作っちゃっていませんか?

  8. 問題提起 1クラスにロジック処理・入出力処理・リソース処理…. こういうクラスは神クラス (God Classes) と呼ばれます. 実体は悪クラス (Evil Classes) です.

    Unity 初心者本は大方神クラスで説明を済ませることが多く,「密結合」になりがちです. 個人開発ならいいですが,実際のチーム開発では「密結合」である場合は困ることが多いです. ワシに任せろ かかったな アホが ! 神クラスに見えて 実際は悪クラスである
  9. 神クラスのざっとしたサンプル UIコンポーネント群 リソース群 ドメインロジック UIのビジネスロジック

  10. 問題点 ➢1クラスに依存しすぎているため,一部変更しただけで全体に影響を及ぶ. ➢ ビジネスロジック処理の追加・削除がしにくい. ➢ UIを変えたい・切り替えたい時も面倒になる. ➢ チーム開発時にみんな同じクラスに手を入れるとコンフリクトし,解決が面倒. ➢ 拡張・分割しにくい.例えば攻撃・回復・死亡はプレイヤーだけじゃなくて,他のオブジェクトも出来る.

    ➢ 単純にコードが長くなって,コードリーディングする気力を失う. ➢ 単純に汚いコードになりやすい etc.
  11. 本ハンズオンの目的 ➢ 疎結合なコードが書けるようになる ➢ 責務範囲を意識した設計が出来るようになる ➢ 代表的なデザインパターンを習得する ➢ 巷でUnity開発によく利用されるライブラリを習得する

  12. UniRx and MV(R)P Pattern

  13. What is MV(R)P Pattern (1/3) quoted by https://developers.cyberagent.co.jp/blog/archives/4262/

  14. What is MV(R)P Pattern (2/3) quoted by https://developers.cyberagent.co.jp/blog/archives/4262/

  15. What is MV(R)P Pattern (3/3) quoted by https://developers.cyberagent.co.jp/blog/archives/4262/

  16. そこで UniRx

  17. What is UniRx Unity でReactive Extensions(Rx)を実現するためのライブラリ イベントや値の変化を自動で伝播させることができる 作者は neuecc さん.

    C# で言う event をストリーム化した概念のような感じ. Operator (LINQ) が使えるので 中身の加工も容易に出来て柔軟性がある 今回は「使い方」の簡単な説明しかしません. 詳しい機能の中身や概念を深堀したい場合は, 最後に載せる参考資料を読んでください.
  18. UniRxで出来ること(一部) ➢ Method Chain でイベントに対する処理をキレイに書ける ➢ Plain C# Class で

    Update などの MonoBehaviour ライフサイクル処理が実行できる ➢ Scheduler を利用すれば, Coroutine を使わなくても Timer 処理が可能 ➢ ReactiveProperty を利用すれば, 普段の変数感覚でイベントの通知が実装出来る ➢ uGUI のイベント処理が簡潔にキレイに書ける ➢ イベントに対する加工が出来る (Where, First, Select, SelectMany...)
  19. Twitter で覚える UniRx の概念 (1/8) 突然ですがみなさん Twitter を利用していますか? (私はバリバリ仕事中もプライベートもやってます) Twitter

    のフォロー・フォロワー・ツイートの仕組みを思い出してみましょう.
  20. Twitter で覚える UniRx の概念 (2/8) ファン(フォロワー) アイドルのTwitter フォロー フォロー フォロー

  21. Twitter で覚える UniRx の概念 (3/8) ファン(フォロワー) アイドルのTwitter TLに通知される おはよう ^^

    みんな元気~!? Tweet TLに通知される TLに通知される
  22. Twitter で覚える UniRx の概念 (4/8) 流れを整理します. ① アイドルのTwitterアカウントが存在する ② ファンがアイドルをフォローする

    ③ ファンはアイドルのフォロワーになる ④ アイドルがツイートする ⑤ フォロワーはTLにツイート内容が流れてくる この時,アイドルはフォロワーの存在がいる,いないにかかわらず, 「Tweet」というイベントを行うことが出来ますよね ? そして, フォロワーはその「Tweet」内容をTLで拾うことが出来,読むことが出来ます. (ここでアイドルが鍵垢ではないこと,アイドルにブロックされてないことを考慮しない) これを UniRx の用語で当てはめます(アナロジー)
  23. Twitter で覚える UniRx の概念 (5/8) 流れを整理します. ① アイドルのTwitterアカウントが存在する (Observable:観測可能) ②

    ファンがアイドルをフォローする (Subscribe:購読する) ③ ファンはアイドルのフォロワーになる (Observer:観測者) ④ アイドルがツイートする (OnNext:発行する・通知する) ⑤ フォロワーはTLにツイート内容が流れてくる (SubscribeしているのでOnNextを検知出来る)
  24. Twitter で覚える UniRx の概念 (6/8) Observer Observable Subscribe Subscribe おはよう

    ^^ みんな元気~!? Tweet OnNext Subscribe Tweet Message
  25. Twitter で覚える UniRx の概念 (7/8) quoted by https://qiita.com/toRisouP/items/2f1643e344c741dd94f8

  26. Twitter で覚える UniRx の概念 (8/8) quoted by https://qiita.com/toRisouP/items/2f1643e344c741dd94f8

  27. MV(R)P Pattern is quoted by https://developers.cyberagent.co.jp/blog/archives/4262/ view. xxxxAsObservable() Subscribe (model.method)

    Subscribe (view.method) model. xxxxAsObservable()
  28. 例題(ハンズオン)

  29. Subject Subject は IObservable と IObserver を実装するクラスです. 通知側で Subject を作成し,

    IObservable で公開します. 通知を行う際は, OnNext を行います. 購読側は IObservable を参照し, 通知が届いたら Subscribe で購読します. Subscribe は IObserver を引数に持つので, ここで購読時に行う処理を行います. 何言ってるんだコイツは…? となると思うので,例題を出します. 例題1 は私が実演します.例題2 ~ 4 は各自で実装を行ってもらいます.
  30. 事前準備 ハンズオンプロジェクトを開いてください. ➢ ハンズオン用のシーン UniRxExample/Scenes/00_Question ➢ ハンズオン用のスクリプト UniRxExample/Scripts/0X_QuestionX Answer フォルダもありますが,最初は見ないようにしましょう.

    自身で問題を解いて,合っているかどうかの確認のために利用しましょう. どうしても問題がわからない場合は,参照してもかまいません.
  31. 問題1| Subject を利用して Hello World を表示する ボタンを押したら, Debug.Log で Hello

    World ! を表示してみましょう.
  32. 解答1| Subject を利用して Hello World を表示する ボタンを押したら, Debug.Log で Hello

    World ! を表示してみましょう.
  33. 問題2|問題1の責務範囲を分ける 1クラスに Observable と Observer がいることになるので, Observable と Observer を分けましょう.

    Observable でボタン発火のイベントを発行し, Observer でボタン発火の通知を購読し, Debug.Logで Hello World!を表示します.
  34. 解答2|問題1の責務範囲を分ける

  35. Reactive Property Reactive Property は Subject を 通常の変数感覚で行えるようにした変数のようなものです. // int型のReactiveProperty

    var rp = new ReactiveProperty<int>(10); //初期値を指定可能 // Value プロパティを通して,普通に代入したり、値を読み取ることができる rp.Value = 20; var currentValue = rp.Value; //20 // Subscribeもできる(Subscribe時に現在の値も発行される) rp.Subscribe(x => Debug.Log(x)); // 値を書き換えた時にOnNextが飛ぶ rp.Value = 30; quoted by https://qiita.com/toRisouP/items/86fea641982e6e16dac6
  36. 問題3|Reactive Property でカウンタを作る ボタンを押した時に,カウンタがインクリメントする処理を Subject と Reactive Property を組わせて実装してみよう.

  37. 解答3|Reactive Property でカウンタを作る

  38. 問題4|問題3 を MV(R)P パターンで実現する 問題 3 を MV(R)P パターンで実現しましょう.(復習の図) quoted

    by https://developers.cyberagent.co.jp/blog/archives/4262/ view. xxxxAsObservable() Subscribe (model.method) Subscribe (view.method) model. xxxxAsObservable()
  39. 解答4|問題3 を MV(R)P パターンで実現する Model ドメインロジックがあるだけ. ユーザ側が知らなくていい部分. 受け取った入力に色々処理を行い 結果を出力するだけ.

  40. 解答4|問題3 を MV(R)P パターンで実現する View UIのビジネスロジックがあるだけ. UIの表示 入力の発火点 出力の表示 ユーザー側に見せる部分

  41. 解答4|問題3 を MV(R)P パターンで実現する Presenter Model と View の橋渡しをする 橋渡しの際に色々加工をしてもよい.

    (例えば遅延処理,ライフサイクル調整など) UniRx の Operator で 渡ってくる値のフィルタリングも行う.
  42. Model-View-(Reactive)-Presenter Pattern 復習 quoted by https://developers.cyberagent.co.jp/blog/archives/4262/ view. xxxxAsObservable() Subscribe (model.method)

    Subscribe (view.method) model. xxxxAsObservable()
  43. DQEmulation(所要時間15分?) 問題 1: MPの概念を追加し,回復呪文を唱えた時に,MPを減らすようにしよう. コメントアウトしている部分を参考にやってみましょう.

  44. UniTask

  45. What is UniTask Unity C# 用にチューニングされた非同期処理用のライブラリ 最近 Unity C# は

    async/await Task 使えるようになったが,パフォーマンスに問題あり. UniTask を利用することで解決できる. quoted by https://speakerdeck.com/torisoup/unitask2020
  46. Coroutine の問題点 Unity C# で非同期を実装する際に Coroutine を利用することがある. Coroutine の場合,コールバック地獄になりやすい.そして,コード的に汚い. quoted

    by https://speakerdeck.com/torisoup/unitask2020
  47. UniTask Example ➢ 名前空間 (UniTask 2 からの変更) using UniRx.Async; →

    using Cysharp.Threading.Tasks; private async UniTaskVoid Hoge() { // 1秒待つ await UniTask.Delay(TimeSpan.FromSeconds(1)); // 1フレーム待つ await UniTask.DelayFrame(1); // 1フレーム待ってUpdate()のタイミングまで待機 await UniTask.Yield(); var flag = true; // 条件がtrueになるまで待つ await UniTask.WaitUntil(() => flag); flag = false; }
  48. 事前準備 ハンズオンプロジェクトを開いてください. ➢ ハンズオン用のシーン UniTaskExample/Scenes/00_Question ➢ ハンズオン用のスクリプト UniTaskExample/Scripts/0X_QuestionX Answer フォルダもありますが,最初は見ないようにしましょう.

    自身で問題を解いて,合っているかどうかの確認のために利用しましょう. どうしても問題がわからない場合は,参照してもかまいません.
  49. 例題1|Coroutine を UniTask 2 にする

  50. 解答1|Coroutine を UniTask 2 にする

  51. 例題2|UnityWebRequestのダウンロード進捗率の表示をMV(R)Pで実装

  52. 例題2|UnityWebRequestのダウンロード進捗率の表示をMV(R)Pで実装 やること ➢ Presenter View ⇆ Model の橋渡し処理を行う ➢ Model

    ① 取得したいコンテンツのURLを設定する (今回は設定済) ② UnityWebRequest.Get(url) で GET する ③ 受信を待つ (await する) ④ SendWebRequest は AsyncOperation なので, ToUniTask() に変換できる ⑤ UniTaskの Progress.Create<float>(x => _progress.Value = x * 100) を利用して 現在のダウンロード進捗の値を取得する
  53. 解答2|UnityWebRequestのダウンロード進捗率の表示をMV(R)Pで実装

  54. Extenject

  55. What is Extenject Unity C#用の Dependency Injection (依存性注入) ライブラリ. 必要な物を注入してくれるイメージ.

    (Dependency Injection Pattern, Service Locator Pattern については今回説明しません.) FYI : Service LocatorとDependency InjectionパターンとDI Container https://www.nuits.jp/entry/servicelocator-vs-dependencyinjection もともとは Zenject [Zen (禅の心) + ject (Inject) ] だったが, 色々事情(裁判中)があり Extenject と言ったほうがよい. 今回は最低限の部分の簡単な説明しかしません. 詳しい機能の中身や概念を深堀したい場合は, 最後に載せる参考資料を読んでください. (というより多機能すぎて未だに全て把握できていない)
  56. とりあえず簡単な利用方法を説明 Presenter は Model, View の橋渡し役なので,両方知る必要がある(依存している). 現時点では, Model, View を知るために,

    [SerializeField] アトリビュートを加えて, Inspector 上で設定している. この, Presenter に Model, View に参照を与える際に, [SerializeField]を用いずに, Extenject を用いる方法でやってみましょう. Extenject の専門用語があるので,まずは用語整理をします.
  57. 現状 Scene (Hierarchy) Model Presenter View [SerializeField] [SerializeField]

  58. Extenject の基本的な流れ (イメージ) Scene (Hierarchy) Scene Context Installer Model Presenter

    View Bind Bind Model View Inject Inject
  59. Scene Context まずは Scene Context を作ります.Context は 「文脈」という意味ですね. Hierarchy 上で右クリックし,

    Zenject > Scene Context で作成できます.
  60. Installer 次に MonoInstaller を作ります. MonoInstaller は MonoBehaviour を 継承した Installer

    です. よって, Hierarchy 上に実体があります. Projects ウィンドウで右クリック > Create > Zenject > MonoInstaller すると, MonoInstaller.cs を作成できます. InstallBindings() メソッド内で 注入(Inject) したいクラスを Bind します. MonoInstaller を Scene Context に 設定するのを忘れず!(忘れると動きません)
  61. Bind (MonoBehaviour 継承クラス) Fooクラスの依存性注入メソッド Container.Bind<Foo>().AsCashed(); IFoo インタフェースには Fooクラスを注入する Container.Bind<IFoo>().To<Foo>().AsCashed(); Fooインスタンスを注入する

    Container.BindInstance(_Foo).AsCashed(); Bind の仕方については沢山設定方法があるので,ドキュメントを読んでください() 以下,参考. 【Unity】【Zenject】Containerでバインドする際の設定まとめ https://light11.hatenadiary.com/entry/2019/02/22/005845 【Unity】【Zenject】いろんなものを依存性注入する https://light11.hatenadiary.com/entry/2019/02/20/234834
  62. Inject ➢ フィールドインジェクション (循環参照問題により避ける) [Inject] private Bar _bar; [SerializeField] と同じ感じだと思えばよい.

    ➢ プロパティインジェクション (循環参照問題により避ける) [Inject] public Hoge hoge {get; private set;} ➢ メソッドインジェクション (循環参照問題が起きてしまうが… MonoBehaviour クラスはこちらを利用) [Inject] private void Construct(Model model){} ➢ コンストラクタインジェクション (Plain C# クラスはこちらを利用する) [Inject] (一応コンストラクタインジェクションの場合は [Inject]を付けなくてよい) private Boo(Model model){}
  63. Extenject の基本的な流れ (再録) Scene (Hierarchy) Scene Context Installer Model Presenter

    View Bind Bind Model View Inject Inject
  64. 事前準備 ハンズオンプロジェクトを開いてください. ➢ ハンズオン用のシーン ExtenjectExample/Scenes/00_Question ➢ ハンズオン用のスクリプト ExtenjectExample/Scripts/0X_QuestionX Answer フォルダもありますが,最初は見ないようにしましょう.

    自身で問題を解いて,合っているかどうかの確認のために利用しましょう. どうしても問題がわからない場合は,参照してもかまいません. SceneContext, Installer 設定は事前に済ませています.
  65. 例題1|UniRxの例題4にExtenjectを利用しよう Presenter をいじります. Installer を新しく作ります.

  66. 解答1|UniRxの例題4にExtenjectを利用しよう 解答例 (Bind の仕方は色々ありますが,以下が単純)

  67. 例題2| Model の MonoBehaviour をなくそう Model は正直 MonoBehaviour を継承する必要がない. MonoBehaviour

    の継承をなくすことで, Hierarchy 上に実体が必要なくなる. Plain C# クラスの Bind をしてみよう.
  68. 解答2| Model の MonoBehaviour をなくそう

  69. 閑話休題 Model に MonoBehaviour を継承すべきかどうかはプロジェクト次第ですが, ドメインロジックを担当するなら,個人的には継承しないのが責務範囲的に正しいと思います. ただ諸々の事情により,MonoBehaviour を継承してしまっても良い時もあります. ここは個人個人の経験と肌感覚によります. また,Presenter

    はModel と View の橋渡し役なので MonoBehaviour を最終的には継承する必要はありません. ただ今回では MonoBehaviour のライフサイクルに利用される Awake(),Start() メソッドを利用しているため,継承している形です. Extenject には IInitializable のインタフェースがあるので, Presenter に MonoBehaviour を継承させずに, Initializable.Initialize() で実装するのが美しいです. (今回は時間がないので,PresenterもMonoBehaviourを継承させた形で進めます.)
  70. 脳死でMonoBehaviourを継承していませんか? MonoBehaviour を継承しているクラスは,以下の特徴があります. 1. Hierarchy上に実体が必要. 2. MonoBehaviour ライフサイクルを利用することができる. Awake(),Start(),Update() など.

    3. コンストラクタメソッドを作ることができません.なので,new Bar() ができない. MonoBehaviour はコンストラクタメソッドを利用できないので, メソッドインジェクションで疑似的に Inject させる運用になります. Extenject (VContainerも) を利用すれば, MonoBehaviour 継承不要なクラスも 疑似的に Awake(),Start(),Update() のような処理が出来るので,便利です.
  71. Extenject (VContainer) を利用することの個人的な利点 Extenject (VContainerも) を利用すれば, MonoBehaviour 継承不要なクラスも 疑似的に Awake(),Start(),Update()

    のような処理が出来るので,便利です. MonoBehaviour の特徴に合わせて照らし合わせます. ◆ Hierarchy上に実体が必要. → Hierarchy上に実体が不要.よって,いちいち空オブジェクトを生成して, スクリプトをアタッチする手間が省けるし,抜け漏れを防ぐことができる. ◆ MonoBehaviour ライフサイクルを利用することができる. Awake(),Start(),Update() など. → Zenject.IInitializable.Initialize(), Zenject.ITickable.Tick() を利用すればいい. ◆ コンストラクタメソッドを作ることができません.なので,new Bar() ができない. → コンストラクタが利用できるので,コンストラクタインジェクションが出来る. コンストラクタインジェクションの場合,明示的に [Inject] を書く必要がない.
  72. 終わりに

  73. Pros (Personal View) ➢ チーム開発で大いに役に立つ ➢ 設計が疎結合になりやすい ➢ コードの可読性が高い ➢

    採用例が多い (MESON Inc. は採用条件に Extenject の知識が必要とも書かれている) quoted by https://www.wantedly.com/projects/568250
  74. Cons (Personal View) ➢ 学習コストが高い(ただ身に着ければ,その分のリターンは大きい) ➢ フィーリングで UniRx を使ってしまうとリアクティブスパゲッティになりがち ➢

    短期開発のような拡張性を考える必要のない場面では冗長すぎる ➢ 機能が多すぎてどの道具を利用した方がよいかわからなくなる ➢ 三種の神器なしのコードが書けなくなるし,読むスピードも遅くなる チーム開発で UniRx, UniTask, Extenject を利用する場合は チームメンバーのレベル感, 開発納期, 今後の拡張性等を考慮して使うこと バリバリ使う必要はないし,最初は最低限の箇所から利用していくのがよい
  75. まとめ ➢ UniRx, UniTask, Extenject の紹介と軽い使い方の説明 ➢ MV(R)Pパターンの概念の説明 ➢ 実際にハンズオンで三種の神器と

    MV(R)P パターンの効力を実感させた
  76. VContainer (Bonus Track)

  77. What is VContainer HadashiA さんが昨年リリースした Unity用のDIライブラリ. Extenject より 10倍早い. (実は

    Extenject は遅い)
  78. Extenject と VContainer の比較 (1/2) ➢ Code のサイズ quoted by

    https://vcontainer.hadashikick.jp/comparing/comparing-to-zenject
  79. Extenject と VContainer の比較 (2/2) API はだいたい似通っています. quoted by https://vcontainer.hadashikick.jp/comparing/comparing-to-zenject

  80. VContainer の基本的な流れ (イメージ) Scene (Hierarchy) LifetimeScope Model Presenter View Register(Bind)

    Model View Resolve(Inject) Register(Bind) Resolve(Inject)
  81. LifetimeScope LifetimeScope.cs を作る. スクリプト作成の時に,XXXXLifetimeScope と命名するとテンプレートが自動的に当てはめられる. 雑だが,LifetimeScope は SceneContext と Installer

    が合体したようなものだとここでは理解してください.
  82. 事前準備 ハンズオンプロジェクトを開いてください. ➢ ハンズオン用のシーン VContainerExample/Scenes/00_Question ➢ ハンズオン用のスクリプト VContainerExample/Scripts/0X_QuestionX Answer フォルダもありますが,最初は見ないようにしましょう.

    自身で問題を解いて,合っているかどうかの確認のために利用しましょう. どうしても問題がわからない場合は,参照してもかまいません. LifetimeScope 設定は事前に済ませています.
  83. 例題1| ボタンを押したら Hello World Model,View, Presenter は設定済.LifetimeScope を編集しよう.

  84. 解答1| ボタンを押したら Hello World Model,View, Presenter は設定済.LifetimeScope を編集しよう.

  85. 例題2| Extenject 例題 2 を VContainer にする Extenject の Question

    2 のシーンをコピーして, Extenject から VContainer のスクリプトの変更しましょう.
  86. 解答2| Extenject 例題 2 を VContainer にする

  87. 今回のクラス図(参考)|概説 Entity (Scriptable Object) マスターデータ Repository CRUD Model ドメインロジック View

    UIビジネスロジック Presenter 仲介者 Domain Layer Presentation Layer 例えばQuest版,HoloLens2版, Mobile版 のUIを変える場合は Concreate View さえ差し替えればよい Entity, Repository について今回説明せず 他にも Infrastructure Layer があるが,今回は説明せず. たとえば Multiplayer によるネットワーク接続や Database による サーバデータベース接続 など
  88. 今回のクラス図(参考)|詳細 PlantUML でクラス図を作成しています Entity, Repository, Service, Domain の 用語の使い方は他では解釈が異なる場合があります

  89. DQEmulation(所要時間30分?) BGMの実装を参考にして, 問題 2: SFX(効果音)の概念を追加し, 攻撃・回復・被弾時にSFXを鳴らすようにしましょう. 問題 3: SFX の音量を調整する機構を作成しましょう.

  90. 参考資料

  91. 参考資料 ➢ MV(R)P パターン ➢ Web出身のUnityエンジニアによる大規模ゲームの基盤設計 https://developers.cyberagent.co.jp/blog/archives/4262/ ➢ UniRxでMV(R)Pパターンをやってみた https://www.slideshare.net/torisoup/unirxmvrp

    ➢ UniRx ➢ UniRx入門シリーズ (qiita) https://qiita.com/toRisouP/items/00b8a5bb8e7b68e0686c ➢ UniRx/UniTask完全理解 より高度なUnity C#プログラミング (書籍) https://www.amazon.co.jp/dp/B08MNQT86F ➢ UniTask ➢ UniTask2の使い方 https://speakerdeck.com/torisoup/unitask2020 ➢ UniRx/UniTask完全理解 より高度なUnity C#プログラミング (書籍) https://www.amazon.co.jp/dp/B08MNQT86F UniRx, UniTask は neuecc さん, torisoup さんのブログ,qiita,書籍を読めば網羅できる
  92. 参考資料 ➢ Extenject (Zenject) と DI Pattern ➢ Zenject入門その1 疎結合とDI

    Container https://qiita.com/toRisouP/items/b3d3c43db40857ca4ad4 ➢ ZenjectチョットワカルBook https://booth.pm/ja/items/1520608 ➢ 【Unity】依存性注入とは?と、なっているのでZenject(Extenject)を入門してみた https://qiita.com/4_mio_11/items/4306732bc47780802b74 ➢ VContainer ➢ Unity専用最速DIコンテナVContainer と、UnityにおけるDIの勘所 https://learning.unity3d.jp/6297/ ➢ 【Unity】DIコンテナVContainerの使い方まとめ https://light11.hatenadiary.com/entry/2021/02/01/203252 ➢ VContainer入門 – MVPパターンを組んでみる https://gaprot.jp/2021/02/18/vcontainer/ ➢ その他 ➢ Unityにおける設計パターン (必読) https://speakerdeck.com/torisoup/unityniokerushe-ji-patan