UnityにおけるInputAction管理とアクションマップ切り替え方法
本資料では、Unityの新Input SystemにおけるInputActionの取得方法および管理方法、さらにコードによるアクションマップの切り替え手法について、以下の内容をまとめています。
- コード内で直接InputActionを取得する方法(FindActionを使用)
- インスペクターからInputActionReferenceで割り当てる方法
- コードでのアクションマップ切り替えサンプル
- 使用目的に応じた選択のポイント
1. 現状のコードと課題
1.1 現状のコード(FindActionを使用する方法)
以下のコードは、PlayerInputコンポーネントからcurrentActionMap.FindAction("Move")
やFindAction("Jump")
を用いて、InputActionをスクリプト内で直接取得する方法です。
using UnityEngine;
using UnityEngine.InputSystem;
[RequireComponent(typeof(CharacterController))]
[RequireComponent(typeof(PlayerInput))]
public class PlayerController : MonoBehaviour
{
[SerializeField] private Animator animator; // Animatorのキャッシュ
[SerializeField] private float moveSpeed = 3; // 移動速度
[SerializeField] private float jumpPower = 3; // ジャンプ力
[SerializeField] private float rotationSpeed = 10f; // 回転速度
private CharacterController _characterController; // CharacterControllerのキャッシュ
private Transform _transform; // Transformのキャッシュ
private Vector3 _moveVelocity; // キャラの移動速度情報
private InputAction _move; // Moveアクションのキャッシュ
private InputAction _jump; // Jumpアクションのキャッシュ
private void Start()
{
_characterController = GetComponent<CharacterController>(); // 毎フレームアクセスするので、負荷を下げるためにキャッシュしておく
_transform = transform; // Transformもキャッシュすると少しだけ負荷が下がる
var input = GetComponent<PlayerInput>();
// PlayerInputの「Default Map」で指定されているアクションマップを有効化
input.currentActionMap.Enable();
// アクションマップからアクションを取得するには FindAction() を使う
_move = input.currentActionMap.FindAction("Move");
_jump = input.currentActionMap.FindAction("Jump");
}
private void Update()
{
Debug.Log(_characterController.isGrounded ? "地上にいます" : "空中です");
// Moveアクションを使った移動処理(慣性を無視しているので、キビキビ動く)
var moveValue = _move.ReadValue<Vector2>();
_moveVelocity.x = moveValue.x * moveSpeed;
_moveVelocity.z = moveValue.y * moveSpeed;
// 移動スピードを animator に反映する
animator.SetFloat("MoveSpeed", new Vector3(_moveVelocity.x, 0, _moveVelocity.z).magnitude);
// 移動方向が存在する場合にのみ回転処理を実行
Vector3 moveDirection = new Vector3(_moveVelocity.x, 0, _moveVelocity.z);
if (moveDirection != Vector3.zero)
{
// 目標の回転を計算
Quaternion targetRotation = Quaternion.LookRotation(moveDirection);
// 現在の回転から目標の回転に向かって補間
_transform.rotation = Quaternion.Slerp(_transform.rotation, targetRotation, Time.deltaTime * rotationSpeed);
}
if (_characterController.isGrounded)
{
if (_jump.WasPressedThisFrame())
{
// ジャンプ処理
Debug.Log("ジャンプ!");
_moveVelocity.y = jumpPower; // ジャンプの際は上方向に移動させる
}
}
else
{
// 重力による加速
_moveVelocity.y += Physics.gravity.y * Time.deltaTime;
}
// オブジェクトを動かす
_characterController.Move(_moveVelocity * Time.deltaTime);
}
}

1.2 課題
- コード上でInputActionを取得する方法は、エディタ上で直感的に設定(アウトレット接続)できないため、設定変更やチーム内での共有が難しい場合があります。
2. インスペクターからの割り当て:InputActionReferenceの利用
2.1 修正後のコード例
InputActionReferenceを用いることで、インスペクター上で直接InputActionをドラッグ&ドロップして割り当てられるようになります。
using UnityEngine;
using UnityEngine.InputSystem;
[RequireComponent(typeof(CharacterController))]
public class PlayerController : MonoBehaviour
{
[SerializeField] private Animator animator;
[SerializeField] private float moveSpeed = 3;
[SerializeField] private float jumpPower = 3;
[SerializeField] private float rotationSpeed = 10f;
[SerializeField] private InputActionReference moveReference;
[SerializeField] private InputActionReference jumpReference;
private CharacterController _characterController;
private Transform _transform;
private Vector3 _moveVelocity;
private void OnEnable()
{
_characterController = GetComponent<CharacterController>();
_transform = transform;
moveReference.action.Enable();
jumpReference.action.Enable();
}
private void OnDisable()
{
moveReference.action.Disable();
jumpReference.action.Disable();
}
private void Update()
{
var moveValue = moveReference.action.ReadValue<Vector2>();
_moveVelocity.x = moveValue.x * moveSpeed;
_moveVelocity.z = moveValue.y * moveSpeed;
animator.SetFloat("MoveSpeed", new Vector3(_moveVelocity.x, 0, _moveVelocity.z).magnitude);
Vector3 moveDirection = new Vector3(_moveVelocity.x, 0, _moveVelocity.z);
if (moveDirection != Vector3.zero)
{
Quaternion targetRotation = Quaternion.LookRotation(moveDirection);
_transform.rotation = Quaternion.Slerp(_transform.rotation, targetRotation, Time.deltaTime * rotationSpeed);
}
if (_characterController.isGrounded)
{
if (jumpReference.action.WasPressedThisFrame())
{
Debug.Log("ジャンプ!");
_moveVelocity.y = jumpPower;
}
}
else
{
_moveVelocity.y += Physics.gravity.y * Time.deltaTime;
}
_characterController.Move(_moveVelocity * Time.deltaTime);
}
}
2.2 インスペクターでの設定手順
- InputActionsアセットの作成
デフォルトで定義されているのをそのまま使うか、InputActionsアセット内で、必要なアクション(例:Move、Jump)を定義する。


- InputActionReferenceへの割り当て
次のいずれかの方法で登録します
(登録方法1)ドラッグ&ドロップで登録
作成したInputActionsアセットから、各アクションをドラッグ&ドロップして、PlayerControllerのmoveReference
およびjumpReference
フィールドに設定する。

(登録方法2)ファイル選択で登録
⚪︎をクリックして、開いたファイル選択画面から登録します

3. アクションマップの切り替え方法(コードによる実装)
PlayerInputコンポーネントを使用して、コード内でアクションマップを切り替えることも可能です。以下はそのサンプルコードです。
using UnityEngine;
using UnityEngine.InputSystem;
public class ActionMapSwitcher : MonoBehaviour
{
private PlayerInput playerInput;
private void Awake()
{
// PlayerInputコンポーネントをキャッシュ
playerInput = GetComponent<PlayerInput>();
}
private void Update()
{
// 数字キー1を押すと「Gameplay」マップに切り替え
if (Keyboard.current.digit1Key.wasPressedThisFrame)
{
playerInput.SwitchCurrentActionMap("Gameplay");
Debug.Log("Gameplayマップに切り替えました");
}
// 数字キー2を押すと「UI」マップに切り替え
else if (Keyboard.current.digit2Key.wasPressedThisFrame)
{
playerInput.SwitchCurrentActionMap("UI");
Debug.Log("UIマップに切り替えました");
}
}
}
3.1 説明
- PlayerInputコンポーネントの利用:
GetComponent<PlayerInput>()
でPlayerInputコンポーネントを取得し、キャッシュします。 - 入力に基づくマップ切り替え:
Keyboard.current
を利用して、特定のキー入力(ここでは数字キー1および2)に応じ、SwitchCurrentActionMap()
メソッドでアクションマップを切り替えます。 - 利点:
アクションマップの切り替えが簡潔なAPIで実装でき、シーン内で複数の入力コンテキストを管理する際に有効です。
3.2 アクションマップの切り替え用途
アクションマップの切り替えは、ゲーム内の異なる入力コンテキストを管理するために非常に有効です。具体的な用途は以下の通りです。
- ゲームプレイとUIの切り替え:
ゲームプレイ中はキャラクターの移動や攻撃などの操作が有効ですが、メニューやポーズ画面などのUI操作中は、カーソル移動や選択操作に切り替えることで、不要な操作ミスを防ぎます。 - 状態やシーンに応じた入力管理:
ゲーム中の通常の操作、カットシーン、対話シーンなど、シーンや状態ごとに必要な入力セットを定義し、適切なアクションマップを有効化することで、各シーンにおいて適切な入力が反映されるようにします。 - 誤操作防止:
プレイヤーが意図しない操作を行わないよう、必要な入力だけを有効にすることで、誤操作を防止する役割も果たします。 - 柔軟な入力切り替え:
ゲーム内イベントやモードの変更に合わせて、動的に入力設定を変更できるため、シーン遷移や特殊イベントの際にも柔軟に対応できます。
以上のように、アクションマップの切り替えを活用することで、ゲーム全体の操作性やユーザー体験を向上させることが可能です。
4. 使用目的に応じた選択
4.1 コード管理による柔軟な制御が必要な場合
- メリット:
- スクリプト内で直接InputActionを取得(FindAction)し、動作をプログラム的に制御できる。
- アクションマップの切り替えもPlayerInputのAPIでシンプルに実装可能。
- 用途:
プログラマーが細かく動作を管理したい場合や、動的にアクションを切り替える必要がある場合。
4.2 インスペクターから直感的に設定したい場合
- メリット:
- InputActionReferenceを使用することで、インスペクター上でドラッグ&ドロップによる設定が可能。
- デザイナーや非プログラマーとの協働が容易になり、設定変更も直感的に行える。
- 用途:
チーム開発や、設定の変更が頻繁に発生するプロジェクトに適している。
5. まとめ
本資料では、以下の点について解説しました。
- InputActionの取得方法:
コード内でFindAction()
を使用する方法と、InputActionReferenceを利用してインスペクターから設定する方法の違いを理解する。 - アクションマップの切り替え:
PlayerInputのSwitchCurrentActionMap()
を使用して、コード上でアクションマップを動的に切り替える実装例を示した。 - 使用目的に応じた選択:
完全にコードで管理し柔軟に制御したい場合は、FindActionを使用する方法が有効であり、エディタ上で直感的に設定や変更を行いたい場合はInputActionReferenceを使用する方法が適している。
プロジェクトの運用方法や開発フローに合わせ、最適な方法を選択してください。
ディスカッション
コメント一覧
まだ、コメントがありません