勉強不足で至らんブログ

勉強不足ですが色々と書いていきます。

StateMachineBehaviourにInjectする

StateMachineBehaviourにInjectする方法

ZenjectでStateMachineBehaviourを使ってみたいと思ったのが発端で

検索すると自動的にInjectできるようになったそう…だがMonoBehaviourと同じように[Inject]を付けても実行されない…

調べると

ZenjectStateMachineBehaviourAutoInjecter というのがある

中身をみるとシンプルで

using ModestTree;
using UnityEngine;

namespace Zenject
{
    public class ZenjectStateMachineBehaviourAutoInjecter : MonoBehaviour
    {
        DiContainer _container;
        Animator _animator;

        [Inject]
        public void Construct(DiContainer container)
        {
            _container = container;
            _animator = GetComponent<Animator>();
            Assert.IsNotNull(_animator);
        }

        // The unity docs (https://unity3d.com/learn/tutorials/modules/beginner/5-pre-order-beta/state-machine-behaviours)
        // mention that StateMachineBehaviour's should only be retrieved in the Start method
        // which is why we do it here
        public void Start()
        {
            // Animator can be null when users create GameObjects directly so in that case
            // Just don't bother attempting to inject the behaviour classes
            if (_animator != null)
            {
                var behaviours = _animator.GetBehaviours<StateMachineBehaviour>();

                if (behaviours != null)
                {
                    foreach (var behaviour in behaviours)
                    {
                        _container.Inject(behaviour);
                    }
                }
            }
        }
    }
}

となっており手動でComponent追加すればStateMachineBehaviourにInjectする感じぽい

ただ前提として 最初からSceneにあること なので動的にやるとき用に少しだけ変えて

using UnityEngine;
using Zenject;

namespace Hoge.Components
{
    public class StateMachineBehaviourInjector : MonoBehaviour
    {
        public void InjectionTo(Animator animator)
        {
            var behaviours = animator.GetBehaviours<UnityEngine.StateMachineBehaviour>();

            if (behaviours == null) return;
            foreach (var behaviour in behaviours)
            {
                // DiContainerがProjectContextでいい場合
                ProjectContext.Instance.Container.Inject(behaviour);
            }
        }
    }
}

って感じで外から呼べるようにして使うようにした

ちゃんとInjectされたのでめでたしメモ