如何在 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
。如果有人能帮我想出一个解决方案,那将是一个巨大的帮助,即使这意味着改变架构。谢谢!
您可以使用各自的 Run
和 Jump
方法使 Runner
和 Jumper
单独的接口。实际的单一行为将实现接口并拥有自己的 Run
和 Jump
逻辑。所以在 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) ....
}
}
假设我有 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
。如果有人能帮我想出一个解决方案,那将是一个巨大的帮助,即使这意味着改变架构。谢谢!
您可以使用各自的 Run
和 Jump
方法使 Runner
和 Jumper
单独的接口。实际的单一行为将实现接口并拥有自己的 Run
和 Jump
逻辑。所以在 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) ....
}
}