如何在 Unity 中重构 InputActionMaps 之间的共性

How to refactor commonalities among InputActionMaps in Unity

假设我有 2 种(或更多)类型的用户可以控制的对象:

public class Runner : MonoBehaviour
{
    //...
    public void Run() { //... }
}

public class Jumper : Runner
{
    //...
    public void Jump() { //... }
}

此外,我们的 InputActionAsset 中有以下 InputActionMap:

runner action map

jumper action map

我当前的解决方案使用单独的“控件”classes 来定义控件到操作的映射。

Controls.cs:

public abstract class Controls<T>
{
    protected T controlled;

    public Controls(InputActionMap actionMap, T controlled)
    {
        SetupInputCallbacks(actionMap);
        this.controlled = controlled;
    }

    protected abstract void SetupInputCallbacks(InputActionMap actionMap);
 }

亚军Controls.cs

public class RunnerControls : Controls<Runner>
{
    public RunnerControls(InputActionMap actionMap, Runner controlled)
        : base(actionMap, controlled) { }

    protected override void SetupInputCallbacks(InputActionMap actionMap)
    {
        InputAction runAction = actionMap.FindAction("Run");
        runAction.perform += controlled.Run();
    }
}

Jumper.cs

public class JumperControls : Controls<Jumper>
{
    public JumperControls(InputActionMap actionMap, Runner controlled)
        : base(actionMap, controlled) { }

    protected override void SetupInputCallbacks(InputActionMap actionMap)
    {
        InputAction runAction = actionMap.FindAction("Run");
        runAction.perform += controlled.Run();

        InputAction jumpAction = actionMap.FindAction("Jump");
        jumpAction.perform += controlled.Jump();
    }
}

“运行 操作”的代码是重复的,虽然这在这里看起来很小,但我的实际代码在更大程度上做到了这一点。我尝试了类似 public class JumperControls : RunnerControls 的操作,但是 controlled.Jump() 会失败,因为 Controls class 中的 T 计算结果为 Runner。如果有人能帮我想出一个解决方案,那将是一个巨大的帮助,即使这意味着改变架构。谢谢!

您可以使用各自的 RunJump 方法使 RunnerJumper 单独的接口。实际的单一行为将实现接口并拥有自己的 RunJump 逻辑。所以在 Controls<T> 你可以检查 T 是否实现了相应的接口:

public class Controls<T>
{
    protected T controlled;

    public Controls(InputActionMap actionMap, T controlled)
    {
        SetupInputCallbacks(actionMap);
        this.controlled = controlled;
    }

    protected virtual void SetupInputCallbacks(InputActionMap actionMap)
    {
        if (T is Runner) ....
        if (T is Jumper) ....
    }
 }