2

我有一个softozor由玩家控制的游戏对象组成的“主要”场景。这是一只飞扬的恐龙。作为该softozor游戏对象的子对象,我设置了另一个游戏对象 ,Installer它由一个 Transform 组件和一个PlayerInstaller (Script)组件组成:

图片

PlayerInstaller安装了我的播放器逻辑所需的一切。最后,在softozor游戏对象中,我添加了一个Game Object Context (Script)我注册的位置PlayerInstaller

图片

除了softozor游戏对象,我还定义了一个SceneContext

图片

您会注意到所有安装程序列表都是空的SceneContext。但是,如果没有任何SceneContext注册,PlayerInstaller 则不会触发。使用该设置玩游戏效果很好,即被PlayerInstaller调用,我可以控制我的恐龙在我的游戏中做任何我想做的事情。

到现在为止还挺好。现在,考虑以下场景测试:

public class PlayerTests : SceneTestFixture
{
  [Inject]
  private IPlayer _player;

  [UnityTest]
  public IEnumerator TestScene()
  {
    yield return LoadScene("Main");

    _player.Flap();
    yield return new WaitForSeconds(0.01f);
    [...]
  }
}

在该测试中,_player成员变量没有注入满足IPlayer合同的对象。事实上,PlayerInstaller.InstallBindings()不叫。

相反,如果我摆脱我的游戏对象中的Game Object Context (Script)组件,并在以下位置注册:softozorPlayerInstallerSceneContext

图片

然后我也可以像以前一样玩游戏,并且我的测试正在运行,即PlayerInstaller.InstallBindings()在我的场景测试期间调用该方法。

PlayerInstaller我在softozor游戏对象上下文中注册的第一次尝试有什么问题?

我正在与

  • Zenject 版本。7.3.1
  • Unity 2019.1.8f1 PC、Mac 和 Linux 独立版
4

2 回答 2

2

所以你有两个容器, theSceneContext和 a GameObjectContext

我认为这里发生的情况是它们都已安装,但您GameObjectContext没有添加到SceneContext- 它一直有效,直到SceneContext实际需要了解GameObjectContext(在您的场景测试中就是这种情况)。

很难给出更精确的指示,不知道什么是IPlayer什么以及你期望在那里注射什么,但它没有被注射到你SceneContextGameObjectContext.

通过将 放入PlayerInstallerMonoInstallersSceneContext列表,您从技术上解决了该问题,但这显然不是您想要的,因为它使子容器无用并破坏了您想要的任何类型的分离。

相反,您需要使用外观来连接两个上下文子容器和外观:使用 GameObjectContexts (解释由一个示例组成,因此我引用其中的一部分没有意义,但它很详细且很有帮助)

于 2019-07-31T10:57:41.960 回答
0

感谢雨果,我开始了解如何让它运行。我目前的游戏组件设置如下:

UML 图

PlayerInstaller的定义如下:

public class PlayerInstaller : MonoInstaller
{
  [SerializeField]
  Settings _settings;

  public override void InstallBindings()
  {
    Container.BindInterfacesTo<Softozor>()
      .AsSingle()
      .WithArguments(_settings.Rigidbody);
    Container.BindInterfacesTo<InputController>().AsSingle();
    Container.Bind<InputState>().AsSingle();
    Container.BindInterfacesTo<PlayerInputHandler>().AsSingle();
    Container.BindInterfacesTo<PlayerMoveHandler>().AsSingle();
  }

  [Serializable]
  public class Settings
  {
    public Rigidbody2D Rigidbody;
  }
}

在阅读了 hugo 建议的文档后,我检查了在我的场景测试期间创建了哪些上下文。我能够看到PlayerInstaller.InstallBindings在我的场景测试中调用了该方法。另外,我Softozor实现IPlayer接口的对象也被注入到了PlayerMoveHandler类中。这意味着Game Object Context在现场测试期间已成功构建。但是,在该上下文中注册的对象不能从 中获得Scene Context,这是我可以在我的场景测试中访问的对象。我天真地假设我在游戏对象上下文中注册的任何内容都可以在我的场景测试中检索到。然而,很明显,我只能访问在场景上下文中注册的对象。

那时,如果我真的想访问实现的实例IPlayer,我有一个选择:或者我在softozor游戏对象上创建一个外观并在其上IPlayer公开可用,或者我找到一种从游戏对象上下文中解析实例的方法。后者有可能吗?

最后,我想我会以不需要访问 type 实例的方式重新设计我的场景测试IPlayer,这在我的情况下是完全可能的。但我很想知道是否可以在场景测试中从游戏对象上下文中解析对象。我怎么做?

于 2019-08-02T13:30:38.703 回答