【Unity】【Zenject】非MonoBehaviourをDIする際にMonoBehaviourのように振舞わせる

Zenjectには非MonoBehaviourをDIする際にMonoBehaviourのように振舞わせる仕組みがあります。
つまり、Start()Update()OnDestroy()のようなメソッドを非MonoBehaviourに実装できます。
この記事ではその実装方法を紹介します。

Unity2018.2
Zenject7.3.1

IInitializable

まず、IInitializableというインタフェースを紹介します。
これを実装すると非MonoBehaviourにMonoBehaviourのStart()と同じような働きをさせることができます。

使い方としてはまずIInitializableを実装したクラスを適当に作ります。

using UnityEngine;
using Zenject;

public class Example : IInitializable
{
    public void Initialize()
    {
        Debug.Log("initialize.");
    }
}

そしてこれをDIします。
この際にBind()の引数にIInitializableの型を渡す必要があります。

using System;
using Zenject;

public class ExampleInstaller : MonoInstaller
{
    public override void InstallBindings()
    {
        Container
            .Bind(typeof(Example), typeof(IInitializable)) // 引数にIInitializableの型を渡す
            .To<Example>()
            .AsTransient();
    }
}

以上で、初期化時にInitialize()が呼ばれることになります。

その他のインタフェース

IInitialize以外にも下記のようなインタフェースが使えます。

名前 実装するメソッド 対応するMonoBehaviourのメソッド
IInitializable() Initialize() Start()
ITickable Tick Update()
ILateTickable LateTick LateUpdate()
IFixedTickable FixedTick FixedUpdate()
IDisposable() Dispose() OnDestroy()

全て実装したクラスはこんな感じです。

using UnityEngine;
using Zenject;
using System;

public class Example : IInitializable, IDisposable, ITickable, ILateTickable, IFixedTickable
{
    public void Initialize()
    {
        Debug.Log("initialize.");
    }

    public void Tick()
    {
        Debug.Log("Tick.");
    }

    public void LateTick()
    {
        Debug.Log("LateTick.");
    }

    public void FixedTick()
    {
        Debug.Log("FixedTick.");
    }
    
    public void Dispose()
    {
        Debug.Log("dispose.");
    }
}

Installerはこんな感じになります。

using System;
using Zenject;

public class ExampleInstaller : MonoInstaller
{
    public override void InstallBindings()
    {
        Container
            .Bind
            (
                typeof(Example),
                typeof(IInitializable),
                typeof(IDisposable),
                typeof(ITickable),
                typeof(ILateTickable),
                typeof(IFixedTickable)
            )
            .To<Example>()
            .AsTransient();
    }
}

Bind()を短く書く

前節の最後のソースコードではインタフェースが増えたことによりInstallerの記述が冗長になっています。
これは次のように書くことで簡易化できます。

using Zenject;

public class ExampleInstaller : MonoInstaller
{
    public override void InstallBindings()
    {
        Container
            .BindInterfacesAndSelfTo<Example>()
            .AsTransient();
    }
}

参考

github.com

関連

light11.hatenadiary.com

light11.hatenadiary.com

light11.hatenadiary.com

light11.hatenadiary.com

light11.hatenadiary.com

light11.hatenadiary.com