有一个界面:
public interface IUpdatable
{
public void Awake();
public void Start();
public void Update();
public void FixedUpdate();
public void LateUpdate();
}
该接口旨在从不继承自的类中提取 Unity 方法MonoBehaviour
。我有一个PlayerController
实现该接口的类。
这是装饰器本身。我试图使用接口将所有调用集中在一个地方,但是当我运行它时,它至少List<IUpdatable> updatable
有一个后继者。Count = 0;
IUpdatable
public class UpdatableDecorator : MonoBehaviour
{
private List<IUpdatable> _updatables = new();
[Inject]
public void Construct(List<IUpdatable> updatable)
{
_updatables.AddRange(updatable);
Debug.Log(_updatables.Count);
}
private void Awake()
{
foreach (var awake in _updatables)
{
awake.Awake();
}
}
void Start()
{
foreach (var start in _updatables)
{
start.Start();
}
}
void Update()
{
foreach (var update in _updatables)
{
update.Update();
}
}
private void FixedUpdate()
{
foreach (var fixedUpdate in _updatables)
{
fixedUpdate.FixedUpdate();
}
}
private void LateUpdate()
{
foreach (var lateUpdate in _updatables)
{
lateUpdate.LateUpdate();
}
}
}
绑定如下所示SceneInstaller
:
private void BindDicorator()
{
Container.Bind<List<IUpdatable>>().AsSingle();
Container.BindInterfacesAndSelfTo<UpdatableDecorator>().FromComponentInHierarchy().AsSingle();
}
我不知道我做错了什么。我将非常感激您的指导。
你不需要这个:
Container.Bind<List<IUpdatable>>().AsSingle();
您只需要安装类本身,它实现
IUpdatable
:Zenject非常智能,会自动将所有实现注入
IUpdatable
到您的List
.[Inject]
Zenject 保证在调用该方法之前会调用标记的方法Start
,但对 不作这样的保证Awake
。也就是说,Awake
它可以早于 被调用Construct
。由此可见,人们Awake
无法访问注入的对象。所以,就你的情况而言,就是这样
或者您需要将其完全删除,或者从方法中调用它
Construct
。我建议将其全部删除,如第 4 点所示。原则上,这并不需要这样做,因为一切都已经在 Zenject 中实现。
我们创建一个这样的类:
让我们像这样安装它:
传说是这样的:
Start
->IInitializable
Update
->ITickable
FixedUpdate
->IFixedTickable
LateUpdate
->ILateTickable
OnDestroy
->IDisposable
很容易注意到,前面提到的要点已经消失
Awake
。然而,这并不完全正确:对于常规类来说,类似物Awake
只是它的构造函数。或者更确切地说,相反,我们被迫使用组合和MonoBehaviour
而不是普通的构造函数。因此,您可以认为您尝试做的事情已经在 Zenject 中完全实现。好吧,也许您可以创建一个将所有这些单独的接口组合在一起的接口:Awake
Construct
IUpdatable
WithId()
、WhenInjectedInto()
和When()
绑定时要小心。通过这些,您将限制 Zenject 尝试注入的位置。因此,为了使这些接口能够工作,您必须为它们创建相关的绑定,而不受这些限制。