You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Zenjection的绑定问题:代码阐述多单位类型架构需求

Got it, let's break down how to handle binding your custom unit classes with their respective Settings using Zenjection. The key here is to make sure each derived unit gets its specific settings injected correctly, while keeping things scalable as you add more unit types.

First, let's start with a small refactor to make dependency injection cleaner (you can skip this if you really want to stick with public fields, but constructor injection is much more aligned with DI best practices):

// Update your Archer class to use constructor injection instead of public fields
public class Archer : BaseUnit 
{
    public readonly ArcherSettings Settings;

    // Let Zenjection inject the settings via constructor
    public Archer(ArcherSettings settings)
    {
        Settings = settings;
    }

    [System.Serializable]
    public class ArcherSettings : Settings 
    {
        public CanWalk.WalkSettings WalkSettings;
    }
}

Now, let's cover two common scenarios for binding these units and their settings:


1. Binding Settings Created in Code

If you're initializing your settings directly in code (not using ScriptableObjects), you can set this up in a standard MonoInstaller:

public class UnitsInstaller : MonoInstaller
{
    public override void InstallBindings()
    {
        // 1. Bind the specific settings for Archer
        var archerSettings = new Archer.ArcherSettings()
        {
            WalkSettings = new CanWalk.WalkSettings()
            {
                // Initialize your walk settings here (e.g., speed = 5f)
            }
        };
        Container.Bind<Archer.ArcherSettings>().FromInstance(archerSettings);

        // 2. Bind Archer as a BaseUnit (transient means a new instance each time it's resolved)
        Container.Bind<BaseUnit>().To<Archer>().AsTransient();

        // If you need to create multiple Archer instances dynamically, use a Factory
        Container.BindFactory<Archer.ArcherSettings, Archer, Archer.Factory>();
    }
}

Since your Settings classes are [Serializable], it's likely you'll want to store them as ScriptableObjects for easy editing in the Unity Inspector. Here's how to set that up:

First, create a ScriptableObject installer for your Archer settings:

[CreateAssetMenu(fileName = "ArcherSettings", menuName = "Settings/Units/Archer")]
public class ArcherSettingsSO : ScriptableObjectInstaller<ArcherSettingsSO>
{
    [SerializeField] private Archer.ArcherSettings _settings;

    public override void InstallBindings()
    {
        Container.Bind<Archer.ArcherSettings>().FromInstance(_settings);
    }
}

Then, reference this ScriptableObject in your main units installer:

public class UnitsInstaller : MonoInstaller
{
    [SerializeField] private ArcherSettingsSO _archerSettingsSO;

    public override void InstallBindings()
    {
        // Install the settings from the ScriptableObject
        _archerSettingsSO.Install(Container);

        // Bind the Archer unit
        Container.Bind<BaseUnit>().To<Archer>().AsTransient();

        // Optional: Factory for dynamic instance creation
        Container.BindFactory<Archer.ArcherSettings, Archer, Archer.Factory>();
    }
}

Scaling for Multiple Unit Types

To avoid repeating code as you add more units (like Warrior, Mage, etc.), create a generic base installer:

public abstract class UnitInstaller<TUnit, TSettings> : MonoInstaller 
    where TUnit : BaseUnit
    where TSettings : BaseUnit.Settings
{
    [SerializeField] private TSettings _settings;

    public override void InstallBindings()
    {
        Container.Bind<TSettings>().FromInstance(_settings);
        Container.Bind<BaseUnit>().To<TUnit>().AsTransient();
    }
}

Then, for each new unit, just create a simple installer that inherits from this:

public class ArcherInstaller : UnitInstaller<Archer, Archer.ArcherSettings>
{
    // Your settings will show up in the Inspector automatically
}

Quick Note on Public Fields

If you absolutely need to keep the public Settings field instead of using constructor injection, make sure to tell Zenjection to inject fields when binding:

Container.Bind<Archer>().AsTransient().InjectFields();

But again, constructor injection is the better approach—it makes dependencies explicit and avoids hidden dependencies.

内容的提问来源于stack exchange,提问作者Argus Kos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:02:16