动态设置操作映射

更新页 :
页面创建日期 :

验证环境

窗户
  • 视窗 11
统一编辑器
  • 2020.3.25f1
输入系统包
  • 1.2.0

此提示的先决条件

作为此提示描述的前提,已预先进行了以下设置。

您还应该熟悉以下提示:

关于动态操作映射配置

通常提前为项目添加和设置操作图, 在这种情况下,控制器按钮分配在游戏执行期间是固定的,用户在游戏过程中无法自由更改。 这主要是需要密钥配置的游戏。

此提示介绍如何任意更改脚本中操作映射的键分配。

动态操作图更改处理

这一次,初始动作图也是由脚本设置的,中间的动作图更改也是在脚本中完成的。 我认为在加载和设置游戏启动时保存的密钥配置时使用此方法。

示例的内容是在按下按钮时更改操作映射的键分配,以及将操作的内容显示为文本。 按钮位置和显示文本如图所示排列,但它们不是很重要,因此请自由放置它们。

操作映射初始配置过程

创建脚本。 名称是任意的,但在这种情况下 InputActionMap 是. 这次,所有的过程都会在这里描述,但在实际生产中,请根据项目的创建进行划分。

脚本如下所示: 首先,在启动时创建默认操作映射。

using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;

public class InputActionMap : MonoBehaviour
{
  /// <summary>情報を表示させるテキストオブジェクト。</summary>
  [SerializeField] private Text TextObject;

  /// <summary>Move アクション用の定義。</summary>
  public InputAction MoveAction { get; set; }

  /// <summary>Attack アクション用の定義。</summary>
  public InputAction AttackAction { get; set; }

  private void Awake()
  {
    // Move アクションの作成
    MoveAction = new InputAction("Move");

    // バインド(キー割り当て)の追加
    // 設定する文字列の形式はアクションマップ設定画面の Path に表示される文字列となる
    MoveAction.AddBinding("<Gamepad>/leftStick");

    // キーボードに上下左右を割り当てるにはコンポジットの 2DVector を設定する
    MoveAction.AddCompositeBinding("2DVector")
        .With("Up", "<Keyboard>/upArrow")
        .With("Down", "<Keyboard>/downArrow")
        .With("Left", "<Keyboard>/leftArrow")
        .With("Right", "<Keyboard>/rightArrow");

    // Attack アクションの作成
    AttackAction = new InputAction("Attack");

    // バインド(キー割り当て)の追加
    AttackAction.AddBinding("<Gamepad>/buttonSouth");
    AttackAction.AddBinding("<Keyboard>/z");

    // 操作時のイベントを設定
    MoveAction.performed += context => OnMove(context);
    MoveAction.canceled += context => OnMove(context);
    AttackAction.performed += context => OnAttack(context);
    AttackAction.canceled += context => OnAttack(context);
  }

  private void OnEnable()
  {
    // オブジェクトが有効になったときにアクションマップを有効にする
    MoveAction.Enable();
    AttackAction.Enable();
  }

  private void OnDisable()
  {
    // アクションマップが誤動作しないようにオブジェクト終了時に無効にする
    MoveAction.Disable();
    AttackAction.Disable();
  }

  /// <summary>
  /// Move 操作を行ったときに呼ばれる。
  /// </summary>
  /// <param name="context">コールバック内容。</param>
  public void OnMove(InputAction.CallbackContext context)
  {
    var vec = context.ReadValue<Vector2>();
    TextObject.text = $"Move:({vec.x:f2}, {vec.y:f2})\n{TextObject.text}";
  }

  /// <summary>
  /// Move 操作を行ったときに呼ばれる。
  /// </summary>
  /// <param name="context">コールバック内容。</param>
  public void OnAttack(InputAction.CallbackContext context)
  {
    var value = context.ReadValueAsButton();
    TextObject.text = $"Attack:{value}\n{TextObject.text}";
  }
}

首先,在类中定义要在字段中实现的任意InputAction数量的操作。 在这里,我们将准备“移动”和“攻击”的字段,它们在前面的操作地图说明中也使用过。 如果操作数量增加,则需要声明该数字,但如果操作ListDictionary数量很多,则可以使用 、、等来管理它们。 这里不使用它,但是如果您有自己的InputActionMap类,则可以在那里管理它。

在初始化时调用 Awake 的方法 InputAction 中执行实例化和密钥分配 AddBinding 。 您可以将您正在执行的操作视为在操作映射设置屏幕上添加绑定的程序。 AddBinding 为方法等指定的字符串与操作映射设置屏幕上的 Path 中显示的字符串相同。 要显示字符串,请按右侧的“T”按钮。

操作按钮时调用的事件处理与正常操作图的脚本版本的处理相同。 回调过程也会按原样转移。

// 操作時のイベントを設定
MoveAction.performed += context => OnMove(context);
MoveAction.canceled += context => OnMove(context);
AttackAction.performed += context => OnAttack(context);
AttackAction.canceled += context => OnAttack(context);
/// <summary>
/// Move 操作を行ったときに呼ばれる。
/// </summary>
/// <param name="context">コールバック内容。</param>
public void OnMove(InputAction.CallbackContext context)
{
  var vec = context.ReadValue<Vector2>();
  TextObject.text = $"Move:({vec.x:f2}, {vec.y:f2})\n{TextObject.text}";
}

启用,禁用是一个 InputAction 单元,因此请根据需要描述任意数量的操作。 如果很麻烦,你可以用等来管理它 List

private void OnEnable()
{
  // オブジェクトが有効になったときにアクションマップを有効にする
  MoveAction.Enable();
  AttackAction.Enable();
}

保存脚本后 EventSystem ,将其附加到文本对象并配置要显示的文本对象。

运行游戏并查看是否显示输入信息。 结果应与操作映射静态进程的脚本版本相同。

操作映射动态更改处理

由于操作映射的动态更改是在按下按钮时完成的,因此定义在按下按钮时将调用的方法。 OnClickButton 现在,我们将它保留为 .

// 省略

public class InputActionMap : MonoBehaviour
{
  // 省略

  /// <summary>
  /// ボタンをクリックしたときに呼ばれる。
  /// </summary>
  public void OnClickButton()
  {
  }
}

设置按钮的单击事件。

操作映射重写过程如下:

/// <summary>
/// ボタンをクリックしたときに呼ばれる。
/// </summary>
public void OnClickButton()
{
  TextObject.text = "アクションマップを変更しました。";

  // Move アクションのキーを置き換える
  MoveAction.ApplyBindingOverride(new InputBinding { path = "<Gamepad>/leftStick", overridePath = "<Gamepad>/dpad" } );
  MoveAction.ApplyBindingOverride(new InputBinding { path = "<Keyboard>/upArrow", overridePath = "<Keyboard>/w" });
  MoveAction.ApplyBindingOverride(new InputBinding { path = "<Keyboard>/downArrow", overridePath = "<Keyboard>/s" });
  MoveAction.ApplyBindingOverride(new InputBinding { path = "<Keyboard>/leftArrow", overridePath = "<Keyboard>/a" });
  MoveAction.ApplyBindingOverride(new InputBinding { path = "<Keyboard>/rightArrow", overridePath = "<Keyboard>/d" });

  // Attack アクションのキーを置き換える
  AttackAction.ApplyBindingOverride(new InputBinding { path = "<Gamepad>/buttonSouth", overridePath = "<Gamepad>/buttonEast" });
  AttackAction.ApplyBindingOverride(new InputBinding { path = "<Keyboard>/z", overridePath = "<Keyboard>/space" });
}

由于为每个操作提供了一个 ApplyBindingOverride 方法, path 因此初始化为 的键或按钮的路径 , overridePath 写入要覆盖的键或按钮的路径。

顺便说一下,这只是设置覆盖路径,因此原始路径保持原样。 例如,在攻击操作中,将 z 键更改为空格键。 此外,如果要从空格更改为x键,则将覆盖z键的描述,而不是基于空格,如下所示。

AttackAction.ApplyBindingOverride(new InputBinding { path = "<Keyboard>/z", overridePath = "<Keyboard>/x" });

保存后,运行游戏并单击按钮以查看与您交互的键或按钮是否更改。

InputAction这一次,我们将更改创建 , 的实例的操作映射 还有一个InputAction由GUI的动作图设置生成的脚本,因此请在易于操作的脚本中实现它。