zenject

一,Unity Zenject 框架基础使用

1,前言

前段时间做的项目中有用到 Zenject + UniTask + UniRx + Localization + GoogleSheet,后续文章中会挨个说明,本期先来介绍一下Zenject。
在Unity开发中,依赖注入(Dependency Injection, DI)是一种非常有用的设计模式,它可以帮助我们更好地管理代码的依赖关系,提高代码的可维护性和可测试性。Zenject是Unity中一个非常流行的依赖注入框架,它提供了强大的功能和灵活的配置方式。本文将详细介绍如何在Unity项目中使用Zenject,并通过一些示例代码来帮助大家更好地理解和应用这个框架。

2,安装Zenject

首先,我们需要在Unity项目中安装Zenject。可以通过以下几种方式来安装:

通过Unity Package Manager安装步骤如下:

  • 1,打开Unity Editor,选择 Window -> Package Manager。
  • 2,点击左上角的 + 按钮,选择 Add package from git URL…。
  • 3,输入Zenject的GitHub地址:https://github.com/modesttree/Zenject.git,然后点击 Add。
  • 4,通过Unity Asset Store安装:
  • 5,打开Unity Editor,选择 Window -> Asset Store。搜索 Zenject,找到并导入到项目中。

3,基本使用

Zenject的核心概念是 Container 和 Binding。Container 用于管理对象的创建和生命周期,而 Binding 则用于定义对象之间的依赖关系。

3.1,创建Installer

Installer是Zenject中用于配置依赖关系的类。我们可以通过继承 MonoInstaller 或 Installer 来创建自己的Installer。

using Zenject;

public class GameInstaller : MonoInstaller
{
    public override void InstallBindings()
    {
        // 在这里配置依赖关系
        Container.Bind<IPlayer>().To<Player>().AsSingle();
        Container.Bind<IGameManager>().To<GameManager>().AsSingle();
    }
}

在上面的示例中,我们创建了一个 GameInstaller 类,并在 InstallBindings 方法中配置了依赖关系。Container.Bind().To().AsSingle(); 表示将 IPlayer 接口绑定到 Player 类,并且使用单例模式。

3.2,使用依赖注入

在需要使用依赖的类中,我们可以通过构造函数注入的方式来获取依赖对象。

public class GameController : MonoBehaviour
{
    private IPlayer _player;
    private IGameManager _gameManager;

    [Inject]
    public void Construct(IPlayer player, IGameManager gameManager)
    {
        _player = player;
        _gameManager = gameManager;
    }

    void Start()
    {
        _player.Move();
        _gameManager.StartGame();
    }
}

在上面的示例中,我们通过 [Inject] 属性标记了 Construct 方法,表示需要通过依赖注入来获取 IPlayer 和 IGameManager 的实例。

3.3,配置场景

最后,我们需要在场景中添加Installer。可以通过以下步骤来完成:

在场景中创建一个空的GameObject,并命名为 GameInstaller。
在 GameInstaller 上添加 GameInstaller 脚本。
进阶使用
Zenject还提供了许多高级功能,如子容器、信号、工厂等。下面我们将介绍一些常用的高级功能。

3.3.1.子容器

子容器可以用于管理局部的依赖关系,特别适用于复杂的场景。

public class SubContainerInstaller : MonoInstaller
{
    public override void InstallBindings()
    {
        Container.Bind<IEnemy>().To<Enemy>().AsTransient();
    }
}

在上面的示例中,我们创建了一个 SubContainerInstaller 类,并在其中配置了 IEnemy 的依赖关系。

3.3.2. 信号

信号是一种用于解耦事件系统的机制,可以帮助我们更好地管理事件的订阅和发布。

public class GameSignals : Signal<GameSignals, string> { }

public class SignalInstaller : MonoInstaller
{
    public override void InstallBindings()
    {
        Container.DeclareSignal<GameSignals>();
    }
}

public class SignalPublisher : MonoBehaviour
{
    [Inject]
    GameSignals _gameSignals;

    void Start()
    {
        _gameSignals.Fire("Game Started");
    }
}

public class SignalSubscriber : MonoBehaviour
{
    [Inject]
    void OnEnable(GameSignals gameSignals)
    {
        gameSignals += OnGameStarted;
    }

    void OnDisable(GameSignals gameSignals)
    {
        gameSignals -= OnGameStarted;
    }

    void OnGameStarted(string message)
    {
        Debug.Log(message);
    }
}

在上面的示例中,我们创建了一个 GameSignals 类,并在 SignalInstaller 中声明了这个信号。然后,我们在 SignalPublisher 中发布信号,在 SignalSubscriber 中订阅信号。

3.3.3,工厂

工厂模式可以用于动态创建对象,特别适用于需要频繁创建和销毁的对象。ru

public class EnemyFactory : PlaceholderFactory<Enemy>
{
}

public class FactoryInstaller : MonoInstaller
{
    public override void InstallBindings()
    {
        Container.BindFactory<Enemy, EnemyFactory>()
            .FromComponentInNewPrefabResource("EnemyPrefab");
    }
}

public class GameController : MonoBehaviour
{
    [Inject]
    EnemyFactory _enemyFactory;

    void Start()
    {
        var enemy = _enemyFactory.Create();
        enemy.Initialize();
    }
}

在上面的示例中,我们创建了一个 EnemyFactory 类,并在 FactoryInstaller 中配置了工厂绑定。然后,我们在 GameController 中使用工厂来创建 Enemy 对象。

3.3.4,IDisposable

Zenject支持 IDisposable 接口,可以用于在对象销毁时执行一些清理操作。

public class GameManager : IGameManager, IDisposable
{
    public void StartGame()
    {
        // 游戏开始逻辑
    }

    public void Dispose()
    {
        // 清理资源
    }
}

public class GameInstaller : MonoInstaller
{
    public override void InstallBindings()
    {
        Container.Bind<IGameManager>().To<GameManager>().AsSingle();
    }
}

在上面的示例中,我们实现了 IGameManager 接口,并在 Dispose 方法中执行清理操作。Zenject会在对象销毁时自动调用 Dispose 方法。

4,注意事项

生命周期管理:Zenject提供了多种生命周期管理方式,如 AsSingle、AsTransient、AsCached 等。需要根据具体情况选择合适的生命周期管理方式。
调试:可以通过 Container.Resolve 方法来手动获取依赖对象,方便调试。
性能:在大型项目中,过多的依赖注入可能会影响性能,需要注意优化。
循环依赖:避免循环依赖,循环依赖会导致依赖注入失败。

5,总结

通过本文的介绍,对Zenject有了一个基本的了解。依赖注入是一种非常强大的设计模式,可以帮助我们更好地管理代码的依赖关系,提高代码的可维护性和可测试性。新人写作不易,谢谢支持。

  • 27
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值