読者です 読者をやめる 読者になる 読者になる

ADBTools

Unity のプロジェクトフォルダ以下にあるapkをリストアップし、
インストール/アンインストールを容易にできるようにしたエディタ拡張を作った。
github.com

昔、Processを呼び出してインストールするようなものは作ったけど
AndroidでビルドはもういいRunしたいってとき - kurihara-nの日記
もう少し整えて、
apkをリストアップして、
それぞれにインストール/アンインストール操作ができるようにした。

Windowsでしか確認してないのは引き続き。

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を適切に設定する。
ここら辺は、普段のプロジェクト構成に合うもので良いのではないかな。

バイオハザード7 resident evil

CERO Dバージョン

プレイしていたのは先月だけども。

とても素晴らしいゲームだったが、
このゲームの感想として「面白い」が適切なのかというと、
そうではないと思う。
もっといろいろな感情を刺激してくる。

最初は恐怖であり、次に怒りへと感情が誘導される。
どちらかと言うとネガティブな感情だけど、
それによってゲーム作品に引き込まれていく。

ゲームには色々な感情を受け入れられる良さがある。

PSVRを手に入れたらVRでも試してみたい。
ただ今までのシリーズの流れをストーリー・世界観的にあまり引き継いでないので、
これまでのシリーズのファンとしては、
そっちも楽しみにしてます。
ジェイクが主人公のシリーズをまたやってみたい。

人工知能の作り方 ――「おもしろい」ゲームAIはいかにして動くのか

人工知能の作り方 ――「おもしろい」ゲームAIはいかにして動くのか

人工知能の作り方 ――「おもしろい」ゲームAIはいかにして動くのか

kindle版にて。

ゲームAI研究の第一人者で、CEDEC等でも多く講演をされている三宅さんの本。
現在のゲームAIの分野を広く網羅されている。
実装の細かいところをコードも含めて見たい・知りたいと思っているプログラマからすると
やや概念によっているものになるかもしれない。
ただ、資料へのリンクも多く含まれているので
もっとより知りたい人でも大丈夫。
もし、もっと実装についての興味があるのであれば
Game AI proを読んでみるといいだろう。(英語だが)

ゲームAIについて丁寧に、周辺から近づいていく構成になっている。
コアの話の箇所でも、
具体的なコードまでは出てこない。
出てこないが、
技術的な仕様はわかるような説明はされている。

ゲームAIの本というと、
基本的にはプログラマ向けという印象もあるけれども、
ゲームデザイナーや、アーティストが読んでもよいと思う。
というかプログラマ以外が読むほうが良いのかもしれない。
そこまで実際のコーディングなど出てこないので、
そういう意味でも読んでほしい。

三宅さんのCEDECの講演で聞いた話も含まれていたので、
そういった三宅さんのリサーチを集めた本ともいえるだろう。
参考資料へのリンクも充実している。
紙の本だとどうだかわからないが(読んだのはkindle版)
kindleだとリンクから直接アクセスできるので便利。
電子書籍向けに合わせて作られているのはありがたい。

特に8章の集団の知能を表現するテクニックなどは興味のある章で、すばらしいと思う。
8章 集団の知能を表現するテクニック ~群衆AI の技術

ゲームのAIについて話す場合、
まず単体のAIに関する話題が優先されるが、
実際にある規模のゲームAIを作っていくと、
マルチエージェント間の連携や、
チームとしての制御が必要になり、
また 負荷対策が実際の問題として生じてくる。
この章はゲームの開発に基づいた資料として機能するし、参考になると思う。
ここで触れられているということにより、
さらに踏み込んだ議論や話しが、
マルチエージェント、群集の表現において
出来ていけると良いなと思う。

ゲーム分野ゆえの問題でもあり、
そのことに触れられているが、(一部引用)

このような組織のシミュレーションが通常、ゲーム産業でしか必要なく、ゲーム産業自身が先導して研究を推進する必要があるからです。アカデミックでは「 マルチエージェント」と呼ばれる分野ですが、この分野自体が広く、 必ずしもキャラクターの協調シミュレーションだけにフォーカスしているわけではないので、こういった技術を吸収しながらも今後発展が必要とされる分野です。

この章の内容だけでも、
ここをさらにもっと広げて、もっと深めていけるともっと表現の追求ができそう。
まだここはやれることがあるところ。
この章を書いていただいたことを感謝したい。

あと、GDやプログラマ以外の方も
ゲームAIへの理解深めておいたほうがよいのかについての補足をもう少し書いておく。
イマイチに観えるAIの、なんでAIがビミョウに思えるのかの原因は
実装が良くないことによるよりも、
ゲームデザインからくることがしばしばある。
開発していてというよりも、ゲームプレイをしていて感じることがある。

例えば、キャンディクラッシュゼリー、
悪い例で挙げて申し訳ないけど、
充分にヒットしている、とても魅力のあるゲームだという前提で。

このパズルゲームシリーズの中の一つの作品は、
敵のAIと対戦を行うステージが出てくる。
いくつか対戦内容はあり、例えば相手より先に自陣のゼリーの色を全体に広げよう、
などというものである。
ポイントとして、対戦以外の面と共通するルールとして、
手数の制限があり、
これはプレイヤー側にのみ課される制限となっているのである。
まず、この点でAI戦で公平ではない印象をプレイヤーに与えてしまう。
また4つ以上のピースを消したときはボーナスとしてスペシャルピースが生成されたうえ、
引き続きターンが継続するというルールになっている。
理屈でいえばAI側は、スペシャルピースを作れる盤面が続く限り、手数の制限がないため、
デメリットもなくターンを続けることができてしまう。
その対策としておそらく組み込まれている挙動なのだと思うが、
スペシャルピースを2つほど生成したあとは、
AIはなるべくただの3つピース消しを選択し、
ターンをプレイヤーに返す行動を選択するようだ。
スペシャルピースを作ってターンを継続出来る場合だったとしても、それに関わらず。

これはプレイヤーからみたら、AIが不可解な手をとったバカなAIと映るかもしれないし、
人によってはワザと手加減されたと感じるかもしれない。
またそれ以前にアンフェアなルールにモヤモヤしているだろう。
これはゲームAIとゲームデザインがうまく機能してない例だと思う。
もっとフェアなルールを設定出来さえすれば良かったと思う。

他のゲームでも、
いろいろな要素が高いレベルで実装されているにも関わらず、
AIが不可解な行動をとるゲームというのはどうしてもある。
問題の解決方法をどこに着地させて解決していくのかは、それぞれの状況による。
そのため各担当パートの垣根を越えてAIへの理解というのは持っておいて損はないはず。
ゲームの絶対的な仕様による制限でAIがおばかに見えてしまうとしたら、
AIプログラマが実装をどんなに改善しても解消は難しいということはある。
そういったさいにゲームデザイナーやほかのスタッフとの対話で
ベストな解決を見つけていくことになるので、
お互いに共有する知識があることは役に立つと思う。

The Last of Us Remastered

年明けにPlaystationStoreでセールになっていて2500円くらいで買えたので
The Last of Us を買った。

The Last of Us Remastered 【CEROレーティング「Z」】 - PS4

The Last of Us Remastered 【CEROレーティング「Z」】 - PS4


進行型のゲームとして、
様々な面でクオリティが高い。

グラフィック、
アニメーション、
カットシーン、
音楽、
吹き替えだったがセリフの雰囲気まで含めて
なにからなにまで
素晴らしいので、
こんなゲームの開発もあるんだなーと。

バッテリーから伸びてる電源ケーブルなんかも
グニョングニョンしてる。
そんなところも粗さがない。

ストーリーも、プロローグでパンデミックが起こって
主人公の一人、ジョエルに悲劇が起こって、
これが可哀そうでね・・

そのあと、もう一人の主人公の少女エリーと行動をともにするようになって、
あー、まあ、どうせ先々こういう展開になるのかなーなんて予測しつつ、
最後まで、あまりだれずに進められた。
(そして、それほど予測したような安易な展開はそれほど描かれなかった)

バトルは、時々強制的なシューティングパートがあってストレスを感じることもあったけど、(下手だから)
ほとんどのケースは、
上手くステルスしていくスタイルも許容されているので楽しい。
特に弓矢は他の敵に気づかれずに使える飛び道具で、
使った矢も折れなければ回収できるので、
上手いプレイをしているという感覚があって良い。

ただ、ストーリー的に、
終盤からラストまでで、
うーん?っていう展開があり。

エリーを助ける助けるためにジョエルが人を殺しまくるという。
いや、それまでも強盗の類いは散々殺してきたんだけど、
一応人類のために活動してる組織の人たちだし、
ほぼ無防備の人なんかも殺しちゃって、
オイオイ…っていう。
ま、描写としては、そこに至るまでにも、
エリーに対する執着が変化していくのは描かれていたんだけど。
うーん、なんか最後のほうは感情移入としては微妙だったかなーっていう。
嫌な気分になって、さしてハッピーエンドでもないし、
もうちょい別の終わらせかた無かったのかねーなんて、
思ってしまった。

が、そんなことをぼんやり考えていたのだが。
1、2日ぼんやり考えていて、
ふと、あれって敢えてそうなんじゃないかって気がしてきた。
いや、敢えてなのは、敢えてなんだろうけど、
ストーリーのために、ああいうジョエルの行動になっていたのではなくて、
ゲームの、プレイヤーの気持ちを、
ジョエルから引き離すのが、
意図的だったのではなかろうか。

ジョエルとプレイヤーのリンクをブチ切って、
どこへプレイヤーを投影させるのか、
気持ちのリンク先を、
最後にエリーに持っていったのでは・・。

ラストシーンで、エリーはジョエルの話を疑って、
そしておそらく嘘を見破って、
言葉にはしないが、失望したようなそんな様子を見せる。
それと、ジョエルないわーっていう、
プレイヤー側の気持ちとが重なることを意図してるのでは。

もうちょい言うと、
ラストシーンの直前、
最後のプレイアブルシーンで、2人で山道を歩くのだけど、
このときの操作対象がエリーになっているのだよね。
それまで、2人が分かれている場面でエリーを操作することはあったけど、
2人一緒のときは、
ジョエルを操作することになっていた。
(おかげでこのシーンが始まったとき、あれ?ってなった)
これも意図的に設計されたことなのではないかな。

これ、ストーリーの流れと、
プレイ対象のスイッチというシステムとしての効果を、
重ね合わせるという、高度な、ゲームでしかできないことを表現しようと
トライしているのじゃないだろうか。
すごい。

うーん、どうだろ。
ちょっと好意的に深読みしているかもしれない。
2も作ってるようだし。(ジョエルも続投なようだし)

Zenjectに含まれてるサンプル その1

kurihara-n.hatenablog.com

Zenjectについて前に書いたが、
アセットのパッケージ自体にサンプルが含まれているので、
それを見ていこうと思う。

サンプルは2種類あり、アセットをインポートしたままの状態であれば
Assets/Zenject/OptionalExtras
の下に
SampleGame1 (Beginner)
SampleGame2 (Advanced)
というフォルダがそれぞれある。

まず、SampleGame1(Beginner)から見ていく。
フォルダの中に、Asteroidsというシーンがあるので
このシーンを開く。

Runするとゲームが動きタイトル画面でクリックでゲームが始まる。
マウスで自機を動かし隕石を避けるゲーム。
f:id:kurihara-n:20170104223309p:plain

シーン構成

シーンの構成を見ていくと、
SceneContextがあり、ここにGameInstallerというInstallerスクリプトがあり、
Installersのリストに追加されている。
また、このSceneContextはScriptableObjectInstallerとして、
ゲームの設定が定義されているGameSettingsInstallerも設定してある。

Guiというオブジェクトからは、
GuiHandlerというコンポーネントがZenjectBindingsでBindされている。

Sceneというオブジェクトは、
背景と、ライト、カメラを持っている。特に触れることはない。

Shipというオブジェクトからは、
ShipというコンポーネントがBindされている。

Scriptable Object Installer

まず、
SceneContextのScriptable Object Installersに設定されているGameSettingsInstallerは、
ゲームの各種設定や、プレハブを持っているScriptableObjectになっている。
GameSettingsInstaller.csを見てみると
InstallBindings()にてそれぞれのインスタンスをBindingしている。
Container.BindInstance(****)というとこ。
これにより他の参照をしたいクラスで使うことができる。

Scriptable Object Installerのドキュメント
https://github.com/modesttree/Zenject#scriptableobject-installer

MonoInstaller

Bindingを行っているMonoInstallerであるGameInstaller.csを見ていく。
最初に、

        [Inject]
        Settings _settings = null;

という箇所があるが、
これがさっきのScriptableObjectInstallerでBindingした設定のインスタンスをとれるようにしているところ。
GameInstallerのSettingsはプレハブを持っている。

プレハブはBindFactoryでファクトリをBnidしており、よそでインスタンスを生成できるようにしている。

InstallAsteroids

            Container.Bind<ITickable>().To<AsteroidManager>().AsSingle();
            Container.Bind<IFixedTickable>().To<AsteroidManager>().AsSingle();
            Container.Bind<AsteroidManager>().AsSingle();

はAsteroidManagerをBindしている。
コメントにもあるが、

Container.BindAllInterfacesAndSelf<AsteroidManager>().To<AsteroidManager>();

と書くのとも一緒になる。

BindFactoryはScriptableObjectからプレハブを受けて、
Asteroidを生成できるようにわたしている。
WithGameObjectNameをつけると生成されるオブジェクトの名前を設定できる。
UnderTransformGroupは設定された名前のオブジェクトの子に設定していく。

InstallShip

最初に自機がクラッシュした時のSignalをバインドしている。

            Container.BindSignal<Signals.ShipCrashed>();

Signalはイベントと同じように使える。
https://github.com/modesttree/Zenject/blob/master/Documentation/CommandsAndSignals.md#signals

ちなみに、SignalのListenを残している状態でSignal自体のDisposeが走ると
Assertになってしまう。
Assertが書いてあるSignal1.csからSignal6.csというファイルに、
要らないならコメントアウトしてね、って書いてあるので気になるならコメントアウトしよう。

他にはStateFactoryと、各ステートのfactoryがBindFactoryされてる。
ステートは
ShipStateWaitingToStart
ShipStateDead
ShipStateMoving
Stateを使っているのはShipオブジェクトだが、
これはシーンに配置されていて、ZenjectBindingによってBindingされている。

InstallMisc

GameControllerをはじめ、
もろもろのクラスのバインディングを行っている。
爆発などのプレハブもBindFactoryしていて、
Ship死亡時のステートからcreateが呼ばれている。

InitExecutionOrder

処理順の制御を行っている。
これはUnityのExecution Orderと同じように使えるものと思っておけばいい。
https://github.com/modesttree/Zenject#update--initialization-order

Zenjectの導入

UnityのためのDependency Injection フレームワークにZenjectというものがある。
つい最近知ったものだけれども、
使えるシーンが多いと思うので現状把握している範囲でまとめておこうと思う。

Github
GitHub - modesttree/Zenject: Dependency Injection Framework for Unity3D

Asset store
https://www.assetstore.unity3d.com/jp/#!/content/17758

知ったきっかけはこちらのAmingさんの開発者ブログ
Unity3DのDIフレームワーク、Zenjectの紹介 | Aiming 開発者ブログ
via Unityまとめ

Unityを日頃使っていて、
なんとなく感じている痒いところの解決の助けになりそうに思っていて、
例えば、どうしてもシングルトンを使ってしまっているところであるとか、
管理用のゲームオブジェクトがシーンに配置されていて、
SerializeFieldに必要なオブジェクトを配置していて、それがいつの間にか外れていて
実行時にExceptionで発覚してギャフン、みたいなのを
軽減させる手段に成りえるかと感じた。

Introduction

GithubのIntroductionのおおまかな訳。

ZenjectはUnityのための、軽量なDependency Injectionフレームワークです。
(ただUnity以外で使うこともできます)
これは貴方のアプリケーションを、
とても分断されたレスポンシビリティをもつ疎結合なパーツの集合にすることができます。
Zenjectは、スケーラブルで最高にフレキシブルな方法で、
容易に書けて、再利用でき、リファクタ、テストできる多くのコンフィグレーションにより、
各パーツをのりづけ(関連付け)できます。

すごそうな雰囲気だが、
まだこれだけだと良く分からないかも。

Dependency Injection

そもそもの話として、
僕はDIコンテナというものは使ったことがなく、今回初めて触れた。
なので、Zenjectの機能の範囲でDIの領域からはみ出ている部分に触れていることもあるかもしれない。
また、DIとしてのベストプラクティスを踏み外している部分や、
やや的を外しているかも。

DIについて調べた確認したページなども書いておく。
DIコンテナの本当の使いどころ | 技術トピックス | ウルシステムズ株式会社
2005年なので随分前の記事。DIの適さない使い方などにも触れられている。
分野によっては前から普通に使われていたのだなと、
自分は不勉強だったなと思った。

c# - DIコンテナを使うメリットが分からない - スタック・オーバーフロー
StackOverflowで、回答がわかりやすいなと。

依存性の注入 - Wikipedia
Wikipedia
上記のStackOverflowにもリンクがあった。
DIという用語を作りだしたのはMartin Fowler、そうだったのか。

Inversion of Control Containers and the Dependency Injection pattern
Martin Fowlerのブログ。
検索したらちゃんと出てきた。
2004年の記事。


ある程度見ていくと、既存のDIについてはJavaphp
C#もあるけど、
Unityというゲームエンジンで動作するフレームワークとは
少し前提条件が違うようにも思うが、
パターンとして考え方を整えるために色々読んでおくのは良いかと。

また、ZenjectのReadmeにも、
DIを使う理由については行数を割いて書かれていて、
https://github.com/modesttree/Zenject#theory
https://github.com/modesttree/Zenject#misconceptions
のあたりで書かれている。

サービスを使うにあたって、
直に生成するよりかはコンストラクタなどでインターフェースを受けるほうが柔軟で、
それをさらに推し進めると、その依存性の解決は最初にやっちゃえばいいよね、
という感じだろうか。ざっくり言うと。

Pokémon Goでの事例

ZenjectはポケモンGoでも採用されている。
Unite LA 2016でのトークの動画が上がっていて、
全般的にDIを採用したアーキテクチャについて話している。
www.youtube.com

  • Unityを長く使っていて、いつもとっ散らかっちゃうけど今回はすごくきれいにできた
  • 既存のゲームデザインとは異なるため多くのイテレーションを必要とし、柔軟なアーキテクチャが必要だった
  • Testについて。
  • ゲームステートごとにInstallerがある。
  • InstallPrefabというAttributeを別途作成・使用している
  • Q&Aにて、パフォーマンスに関してはキャッシングが効いてるから大丈夫と思う、みたいなことを言っている

英語なので、少し怪しいが。

サンプル

まず Hello World Exampleを試してみる。

https://github.com/modesttree/Zenject#hello-world-example

ヒエラルキービューで右クリック 
Zenject -> Scene Context
でSceneContextオブジェクトを生成、配置する。
f:id:kurihara-n:20161227000604g:plain

Projectビューの右クリックからCreate -> Zenject -> MonoInstaller
でInstallerとなるスクリプトを作成する。
ファイルダイアログが開くので、TestInstaller.csという名前で保存する。
f:id:kurihara-n:20161227001830g:plain
この作ったTestInstaller.csに、
ZenjectのReadmeに載っているコードをコピペか、同じように記述する。

TestInstallerをシーンに配置する。(ここではSceneContextにAddComponentしちゃう)
Scene ContextのInstallerプロパティに、
TestInstallerを追加する。
f:id:kurihara-n:20161227001853g:plain

エディタ実行をすると、ログにHello Worldと出力される。
また、Ctrl + Shift + Vで、バリデーションがされて、
問題があればエラーを出してくれる。

オブジェクトの生成

いくつかシンプルなケースをいくつか試してみる。
プレハブをもとにオブジェクトを生成したい場合、
従来であればInstantiateを呼び出すことになるが、
ZenjectではFactoryをBindすることができる。

ここではSceneContextにSerializeFieldでプレハブを受けるInstallerを用意する。
f:id:kurihara-n:20161228012822p:plain

サンプル同様にInstallerをSceneContetのプロパティに設定しておく。
Installerのコードは以下のようになっている。

using UnityEngine;
using Zenject;

public class InstancingInstaller : MonoInstaller<InstancingInstaller>
{
    [SerializeField]
    GameObject cubePrefab;

    public override void InstallBindings()
    {
        Container.BindFactory<Cube, Cube.Factory>().FromPrefab(cubePrefab);
        Container.Bind<ITickable>().To<InstancingManager>().AsSingle();
        Container.Bind<InstancingManager>().AsSingle();
    }
}

FromPrefabからFactoryをBindしている。

cubePrefabはCubeコンポーネントを持っていて、そのなかでFactoryを定義している

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Zenject;

public class Cube : MonoBehaviour
{
    public class Factory : Factory<Cube>
    {
    }
    
	void Start () {
        //...
	}
	
	void Update () {
		//...
	}
}

ITickableを実装したInstancingManagerというクラスからFactoryを使う。
Instancingmanagerは以下。

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Zenject;

public class InstancingManager : ITickable
{
    Cube.Factory factory;

    public InstancingManager(Cube.Factory factory)
    {
        this.factory = factory;
    }

    void ITickable.Tick()
    {
        //if(someCondition)
        //{
        //factory.Create();
        //}
    }
}

factory.Create()を呼べば、オブジェクトが生成される。

ScriptableObjectInstaller

Readmeに書いてあるものからスクリプタブルオブジェクトの利用について。
https://github.com/modesttree/Zenject#scriptable-object-installer

Scriptable Object InstallerでScriptable Objectを利用できる。
右クリックからCreate -> Zenject -> Scriptable Object Installer
ファイル保存ダイアログがでるので、任意の名前をつける。(この例だとGameSettingsInstaller)
このScriptableObjectInstallerはScriptableObjectを継承しているので、
エディタで設定したいプロパティはここに持たせる。
エディタスクリプトにより、このScriptableObjectが生成できるようになっており、
Create -> Installers -> ScriptableObjectInstaller
で作る。
これをSceneContextに追加れば使用できる。
BindはContainer.BindInstance()で行う。

Scene Bindings

これもReadmeにあるものから。
https://github.com/modesttree/Zenject#scene-bindings

すでにシーンに配置してあるオブジェクト/MonoBehaviourを、Bindingさせる方法。
Unityだとシーンに配置させるケースは多々あるので、
それをBindingして受けれるようにする方法。

オブジェクトにZenject Bindingコンポーネントをアタッチし、
Componentsに、そのオブジェクトが持っているBindしたいコンポーネントを追加。

これだけで、[Inject]であったり,ITickableのコンストラクタなりで受けることができる。
[Inject]はListで受けることもできるので、
Amingさんの開発ブログの例もそうだが、
シーンに配置したいくつかのオブジェクトにZenjectBindingを設定しておくと、
オブジェクトのリストが実行時に作られている状態になる。

これは便利。
同じようなことをやるときにオブジェクトのStartなりでマネージャに渡したりしていたのが手間が省けるし、
場合によってはGameObject.FindObjectsOfTypeなどで取得をしたりしていたものが、
このリストでとれるようになる。
まあ、動的にも生成されるようなものはPrefabから生成したさいに別途登録するような使い方にはなると思う。



いくつかのケースを書いてみた。
ITickableなどを用いていると、
Unityの標準のUpdateと別にタスクが回るようなものなので、
従来の使いかたに慣れ切っていると、
少し導入に障害を感じるかもともおもう。
ただ、色々とスッキリかけるので利点は感じる。
もっと使っていきたいと思う。

利用者が増えて日本語でも情報が増えるとうれしい。