Zenject Example SubContainer

1d1580fb0945b0ffadff18e28bead3c5?s=47 いも
September 23, 2019

Zenject Example SubContainer

Unite Tokyo 2019 Eve2 LT Fes の資料です

1d1580fb0945b0ffadff18e28bead3c5?s=128

いも

September 23, 2019
Tweet

Transcript

  1. Zenject Example ~Container の分割編~ @ いも 2019/09/23 Unite Tokyo 2019

    Eve2 LT Fes
  2. いも twitter: @adarapata ゲーム作ったりしてます 2019/09/23 Unite Tokyo 2019 Eve2 LT

    Fes
  3. 宣伝 「Zenject チョットワカルBook 」を書きました ↓Booth 2019/09/23 Unite Tokyo 2019 Eve2

    LT Fes
  4. 今日話すこと Installer 肥大化問題 Zenject のSubContainer について Zenject チョット触り始めてる人向け 2019/09/23 Unite

    Tokyo 2019 Eve2 LT Fes
  5. Installer 肥大化問題 public class SomeInstaller : MonoInstaller { public override

    void InstallBindings() { // Player 関連のBind Container.Bind<Player>().AsCached(); Container.Bind<PlayerDependentA>().AsCached(); // Player しか依存してない Container.Bind<PlayerDependentB>().AsCached(); // Player しか依存してない ~~~ Container.Bind<PlayerDependentN>().AsCached(); // Player しか依存してない // Enemy 関連のBind Container.Bind<Enemy>().AsCached(); Container.Bind<EnemyDependentA>().AsCached(); // Enemy しか依存してない } } 2019/09/23 Unite Tokyo 2019 Eve2 LT Fes
  6. Installer 肥大化問題 1 シーンに必要なものがそれなりに大きくなると起きる問題 あらゆる依存関係が1 シーンに刻まれる Scene のInsaller が細かい依存関係を知ることになる 不要な衝突も発生する可能性が出てくる

    2019/09/23 Unite Tokyo 2019 Eve2 LT Fes
  7. 不要な衝突が発生する public class SomeInstaller : MonoInstaller { public override void

    InstallBindings() { // Player 関連のBind Container.Bind<Player>().AsCached(); Container.Bind<PlayerDependentA>().AsCached(); // Player しか依存してない Container.Bind<Life>().AsCached(); // Player のLife を表現したい // Enemy 関連のBind Container.Bind<Enemy>().AsCached(); Container.Bind<EnemyDependentA>().AsCached(); // Enemy しか依存してない Container.Bind<Life>().AsCached(); // Enemy のLife を表現したい } } 2019/09/23 Unite Tokyo 2019 Eve2 LT Fes
  8. 不要な衝突が発生する 回避できないことはないがちょっと厳しい Container を分けてスマートにしたい 2019/09/23 Unite Tokyo 2019 Eve2 LT

    Fes
  9. やること SubContainer の利用 2019/09/23 Unite Tokyo 2019 Eve2 LT Fes

  10. Container の階層関係 Container は階層関係を持つことができる まず自身のContainer を探して、解決できないなら親のContainer を 探す 親のContainer で見つからなかったらその親を~を繰り返す

    ProjectContext がどこでもInject できるのは、このContainer の最上 位にいるから 2019/09/23 Unite Tokyo 2019 Eve2 LT Fes
  11. Container の階層関係(Parent Contract の場合) Context を境界にContainer が繋がっている 2019/09/23 Unite Tokyo

    2019 Eve2 LT Fes
  12. 1Context の内部だけでContainer の階層関係を作ることもできる 子にあたるContainer のことをSubContainer と呼ぶ 2019/09/23 Unite Tokyo 2019

    Eve2 LT Fes
  13. SubContainer にPlayer が必要とする要素をまとめてしまえば、 Container 内部で衝突しない 2019/09/23 Unite Tokyo 2019 Eve2

    LT Fes
  14. FromSubContainerResolve public class SomeInstaller : MonoInstaller { public override void

    InstallBindings() { // SubContainer から解決する Container.Bind<Player>().FromSubContainerResolve() .ByMethod(InstallSubContainer); // Enemy 関連のBind } // SubContainer にInstall させる public void InstallSubContainer(DiContainer subContainer) { subContainer.Bind<Player>().AsCached(); subContainer.Bind<PlayerDependentA>().AsCached(); subContainer.Bind<Life>().AsCached(); } } 2019/09/23 Unite Tokyo 2019 Eve2 LT Fes
  15. FromSubContainerResolve Bind するオブジェクトをSubContainer から探して解決する 今回だとSubContainer からPlayer を探して解決する このメソッドの後には「何でSubContainer を作るか」のBy~~ メソッ

    ドを定義する ByMethod メソッドを呼んでInstall する ByInstaller Installer<T> なクラスを呼んでInstall する ほかにもいっぱいある 2019/09/23 Unite Tokyo 2019 Eve2 LT Fes
  16. Installer で解決する場合 public class SomeInstaller : MonoInstaller { public override

    void InstallBindings() { // SubContainer にInstaller でInstall して解決する Container.Bind<Player>().FromSubContainerResolve() .ByInstaller<PlayerInstaller>().AsCached(); // Enemy 関連のBind } } public class PlayerInstaller : Installer<PlayerInstaller> { public override void InstallBindings() { Container.Bind<Player>().AsCached(); Container.Bind<PlayerDependentA>().AsCached(); Container.Bind<Life>().AsCached(); } } 2019/09/23 Unite Tokyo 2019 Eve2 LT Fes
  17. Player をSubContainer から引っ張って解決する Life PlayerDependentA はContainer からは見えない Container 単位で役割をグルーピングしやすい 2019/09/23

    Unite Tokyo 2019 Eve2 LT Fes
  18. GameObjectContext public class PlayerBehaviour : MonoBehaviour { [Inject] PlayerDependentA depA;

    [Inject] Life life; } ↑ こういうのをSubContainer でBind したいとする SubContainer にMonoBehavior なオブジェクトをBind する場合、 GameObjectContext をアタッチする必要がある 2019/09/23 Unite Tokyo 2019 Eve2 LT Fes
  19. GameObjectContext SceneContext ProjectContext と同じContext の一種 Context はInstall を行うエントリポイント それぞれInjection のスコープが違う

    ProjectContext: ゲーム全体 SceneContext: シーン内 GameObjectContext: アタッチされたGameObject 以下 SceneContext のContainer にBind するとシーン全体にInject されるの で、GameObjectContext をSubContainer として狭い範囲へのInject を 行える 2019/09/23 Unite Tokyo 2019 Eve2 LT Fes
  20. MonoBehavior でない場合 public class SomeInstaller : MonoInstaller { public override

    void InstallBindings() { // SubContainer にInstaller でInstall して解決する Container.Bind<Player>().FromSubContainerResolve() .ByInstaller<PlayerInstaller>().AsCached(); } } public class PlayerInstaller : Installer<PlayerInstaller> { public override void InstallBindings() { Container.Bind<Player>().AsCached(); Container.Bind<PlayerDependentA>().AsCached(); Container.Bind<Life>().AsCached(); } } SubContainer の作り方が、直接Installer を指定する形になる 2019/09/23 Unite Tokyo 2019 Eve2 LT Fes
  21. MonoBehaviour の場合 いつものSceneContext のノリで対象のPrefab にアタッチする 2019/09/23 Unite Tokyo 2019 Eve2

    LT Fes
  22. MonoBehaviour の場合 public class SomeInstaller : MonoInstaller { [SerializeField] private

    GameObject _playerPrefab; public override void InstallBindings() { // GameObjectContext のついたPrefab を生成してInstall する Container.Bind<PlayerBehaviour>().FromSubContainerResolve() .ByNewContextPrefab(_playerPrefab).AsCached(); } } public class SubInstaller : MonoInstaller { public override void InstallBindings() { // Zenject Binding をアタッチするのもアリ Container.Bind<PlayerBehavior>().FromComponentOnRoot(); Container.Bind<PlayerDependentA>().AsCached(); Container.Bind<Life>().AsCached(); } } 2019/09/23 Unite Tokyo 2019 Eve2 LT Fes
  23. Context を跨いで同じことが行われる 2019/09/23 Unite Tokyo 2019 Eve2 LT Fes

  24. まとめ 1 つのContainer にどんどんBind していくと衝突や可読性の問題が現 れる SubContaienr に分離してスコープを狭めよう MonoBehaviour の場合はGameObjectContext

    を使おう MonoBehaviour でもPureClass でもSubContainer の考え方は変わら ない。 Context があるかどうかだけ 2019/09/23 Unite Tokyo 2019 Eve2 LT Fes
  25. おわり 2019/09/23 Unite Tokyo 2019 Eve2 LT Fes