Unity3DのDIフレームワーク、Zenjectの紹介
- 2016.12.07
- Unity
はじめまして。エンジニアの石井と申します。
今回は現在担当プロジェクトで使用しているUnity(ゲームエンジン)用DIフレームワーク、Zenjectを紹介させていただきます。
Zenjectとは
https://github.com/modesttree/Zenject
ZenjectはUnity3D向けに作成された、DI(依存性の注入)フレームワークです。
Zenjectを使うことでオブジェクト間の依存関係を外部から解決することができます。
簡単になにが良いかを説明しますと、
依存オブジェクトを別の入れ物(コンテナ)に格納しておきコンテナ経由で使うことで、
コンストラクタやメソッドの引数で渡していたり、自身でnewしていたり、FindObjectしていた部分をなくすことができます。
Zenjectサンプル
Zenjectを使ってのUIイベント処理の簡単なサンプルを作っていきます。
今回はボタンが押された時のイベントを処理するサンプルです。
1.インストール
AssetStoreからか、
https://github.com/modesttree/Zenject/releases
からダウンロードしてUnityのプロジェクトにインポートしてください。
2.Contextの作成
シーン上にContextを作成します。
右クリックからScene Contextを選んでください。

3.Installerの作成
コンテナへの格納(Bind)にZenjectはInstallerというスクリプトを使用します。
今回はSingletonとしてオブジェクトをBindしていきます。
シーン上にGameObjectを作成して、
下記スクリプトをAdd Componentしてください。
※直接SceneContextでも問題ありません。

using System;
using Zenject;
public class InstallerSample : MonoInstaller<InstallerSample>
{
public override void InstallBindings()
{
Container.Bind<ZenjectSample>().AsSingle();
Container.Bind<IInitializable>().To<ZenjectSample>().AsSingle();
Container.Bind<IDisposable>().To<ZenjectSample>().AsSingle();
}
}
4.ContextにInstallerをアタッチ
ContextにInstallerをアタッチすることでInstallerが機能します。
SceneContextのInstallersに、作成したInstallerSampleをアタッチしてください。

5.UIの作成
UIを作成していきます。
下記のようにボタンを2つ作成し、


それぞれ下記のようにスクリプトをAdd Componentします。
Zenject Bindingスクリプトにより、Installerに定義しなくてもBindすることができます。
Identifierを使うことで、個別にInjectすることもできます。

using UnityEngine;
using UnityEngine.UI;
using UniRx;
public class UIView : MonoBehaviour
{
[SerializeField]
Button button;
[SerializeField]
Text text;
public IObservable<string> OnClickObservable()
{
return button.OnClickAsObservable().Select(_ => text.text);
}
}
イベントの変換はUniRxを使い、Textをstringで送出します。
6.サンプルクラスの作成
サンプルクラスを作成します。
[Inject]アトリビュートにより先ほど作成したUIViewが注入されます。
IInitializable.Initializeメソッドにより初期化され、
各ボタンのClickイベント購読し、押されたらOnClickメソッドが呼ばれるようになっています。
Sceneの切り替えやゲームの終了などでContextが破棄されるタイミングでIDisposable.Disposeメソッドが呼ばれ、
購読を停止しています。
using System;
using System.Collections.Generic;
using UniRx;
using Zenject;
public class ZenjectSample : IInitializable, IDisposable
{
[Inject]
List<UIView> buttons;
List<IDisposable> subscriptions = new List<IDisposable>();
void IInitializable.Initialize()
{
UnityEngine.Debug.Log("Initialize");
buttons.ForEach(button =>
{
subscriptions.Add(button.OnClickObservable().Subscribe(text => OnClick(text)));
});
}
void OnClick(string buttonText)
{
UnityEngine.Debug.Log(buttonText);
}
public void Dispose()
{
subscriptions.ForEach(subscription => subscription.Dispose());
subscriptions.Clear();
UnityEngine.Debug.Log("Dispose");
}
}
7.動作確認
Sceneが読み込まれる際に、Initializeメソッドが呼ばれ、
ボタンが押されるたびにボタンのTextがログに表示され、
最後にDisposeが呼ばれていることがわかります。

おわりに
簡単に紹介させていただきましたが、
他にもZenjectには様々なContext、Installerが用意されていますので、
依存関係の解決でお困りの方はぜひ一度試してみてください。
-
前の記事
Aimingインフラチームを支え(てくれてい)る技術と設計(1/3) 2016.11.25
-
次の記事
Aiming飲み会 #5 グラフィックエンジニア新年会 を開催します! 2017.01.13