Zenjectとマルチシーン

Zenjectを採用したプロジェクトにおいて、
マルチシーンへ対応する場合にはいくつかの方法があります。

Zenjectのベーシックな使い方は、
シーンにSceneContextを配置して、
そのオブジェクトにInstallerを配置していくことで、
シーンごとの構成を用意していくというものです。

そのままだとUnityでシーンの変更をしたときに
関連性が持てず、それぞれ参照できなくなるので、
前のシーンでBindしたオブジェクトを、
次のシーンで参照するということができません。

方法としては、

  1. ProjectContext というグローバルなコンテキストを用意する
  2. Sceneの親子つけを行いマルチシーン構成にする
  3. DecoratorContext

Project Context

https://github.com/modesttree/Zenject#global-bindings-using-project-context

Projectビューの右クリック -> Create -> Zenject -> Project context
でプレハブを作成する。
場所はResourcesフォルダ以下である必要がある。

これをいったんHierarchyに配置し編集してApplyすることで構成していく。
インスペクタの情報としてはSceneContextと大差なく、
MonoInstallerをアタッチしたり、ScriptableObjectInstallerをアタッチしたりできる。

編集がすんだらApplyをしてシーンからは削除しておくのがポイント。
このプレハブをもとにしたオブジェクトは、シーンに配置しておいて動作するのではなく、
いずれかのSceneContextがシーンオブジェクトに配置されていると、
実行時にDontDestroyOnLoadなオブジェクトとしてシーンに生成される。

Scene Parenting

グローバルに存在するProjectContextはプロジェクト全体を範囲としてしまうので、
ときに問題となる。
指定のシーンとシーンを意図したように関連づける手段として
Contract Name を使用したScene Parentingが存在する。
https://github.com/modesttree/Zenject#scene-parenting-using-contract-names
この場合、シーン同士は並列ではなく主従・親子としての関係を持つ。
親となるシーンのScene Contextのインスペクタ、
Contract Namesというフィールドがあるので、ここに親としての名前を指定する。
(このフィールドは配列になっており複数していできる。
子からみた親はひとつだが、親シーンは全く別の子の親としても、みなされることができる)
子シーンのほうは、インスペクタのParent Contract Nameに、
親の名前を指定する。
Contract Nameはシーン名とは関係ない名前で構わない。

まず親シーンを開き、Hierarchyに子シーンをドロップして、複数のシーンがある状態にし、
Ctrl + Shift + V でValidationが通ることを確認してみるとよい。
この状態は、実際には親シーンからAdditiveで子シーンを読み込んだ状態に等しい。
ちなみに子シーンが先に読まれている状況でValidationを行うとエラーとなる。

DecoratorContext

もうひとつのマルチシーン対応としてDecoratorContextを配置したシーンを用意するというもの。
https://github.com/modesttree/Zenject#scene-decorators
まずDecoratorContextを配置するシーンを用意し、
SceneContextの代わりにDecoratorContextを配置。
Decorated ContractにContract nameとする文字列を指定。
もう一つのシーンを用意して、
こちらには通常のSceneContextを配置。
Contract Namesに先ほどのDecorated nameのと同じ文字列を指定。
2つのシーンを読み込んだ状態で、
DecoratorContextで行ったバインディングが、
あとから読み込んだシーンにもInjectできる。



個人的にはParenting での運用が多い。
エントリシーンを用意し、それを親とした状態で、
モードごとに子シーンを読みかえる構成。
親となるシーン、子になるシーンにそれぞれContractNamesを適切に設定する。
ここら辺は、普段のプロジェクト構成に合うもので良いのではないかな。