Unity Input Systemを使った移動システムの実装方法

UnityのNew Input Systemを使ってキャラクターの移動システムを実装する方法を解説します。従来のInput Managerと比べて、より柔軟で拡張性の高い入力システムを構築できます。

Input Systemの導入

パッケージのインストール

  1. Window → Package Manager を開く
  2. 左上のドロップダウンから “Unity Registry" を選択
  3. “Input System" を検索してインストール
  4. プロジェクトの再起動が必要な場合があります

Input Actions Assetの作成

Project ウィンドウで右クリック → Create → Input Actions

作成したAssetを開き、以下のActionを設定:

  • Move: Action Type を “Value"、Control Type を “Vector2" に設定
  • Jump: Action Type を “Button" に設定

基本的な2D移動の実装

PlayerMovementスクリプト

using UnityEngine;
using UnityEngine.InputSystem;

public class PlayerMovement : MonoBehaviour
{
    [Header("移動設定")]
    public float moveSpeed = 5f;
    public float jumpForce = 10f;

    private Rigidbody2D rb;
    private bool isGrounded;
    private Vector2 moveInput;
    private bool jumpInput;

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
    }

    void Update()
    {
        // 物理移動を実行
        rb.velocity = new Vector2(moveInput.x * moveSpeed, rb.velocity.y);

        // ジャンプ処理
        if (jumpInput && isGrounded)
        {
            rb.velocity = new Vector2(rb.velocity.x, jumpForce);
            jumpInput = false;
        }
    }

    // Input Systemからの入力を受け取る
    public void OnMove(InputAction.CallbackContext context)
    {
        moveInput = context.ReadValue<Vector2>();
    }

    public void OnJump(InputAction.CallbackContext context)
    {
        if (context.performed)
        {
            jumpInput = true;
        }
    }

    // 地面判定
    void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.gameObject.CompareTag("Ground"))
        {
            isGrounded = true;
        }
    }

    void OnCollisionExit2D(Collision2D collision)
    {
        if (collision.gameObject.CompareTag("Ground"))
        {
            isGrounded = false;
        }
    }
}

セットアップ手順

  1. PlayerオブジェクトにRigidbody2Dを追加
  2. PlayerInputコンポーネントを追加
  3. 作成したInput Actions Assetを設定
  4. BehaviorをSend Messagesに設定

3D移動システムの構築

3D環境でのFPS風移動システムの実装例:

using UnityEngine;
using UnityEngine.InputSystem;

public class Player3DMovement : MonoBehaviour
{
    [Header("3D移動設定")]
    public float moveSpeed = 5f;
    public float mouseSensitivity = 2f;

    private CharacterController controller;
    private Camera playerCamera;
    private Vector2 moveInput;
    private Vector2 lookInput;
    private float verticalRotation = 0f;

    void Start()
    {
        controller = GetComponent<CharacterController>();
        playerCamera = GetComponentInChildren<Camera>();
        Cursor.lockState = CursorLockMode.Locked;
    }

    void Update()
    {
        HandleMovement();
        HandleLook();
    }

    public void OnMove(InputAction.CallbackContext context)
    {
        moveInput = context.ReadValue<Vector2>();
    }

    public void OnLook(InputAction.CallbackContext context)
    {
        lookInput = context.ReadValue<Vector2>();
    }

    void HandleMovement()
    {
        Vector3 direction = transform.right * moveInput.x + transform.forward * moveInput.y;
        controller.Move(direction * moveSpeed * Time.deltaTime);
    }

    void HandleLook()
    {
        // 水平回転
        transform.Rotate(Vector3.up * lookInput.x * mouseSensitivity);

        // 垂直回転(カメラのみ)
        verticalRotation -= lookInput.y * mouseSensitivity;
        verticalRotation = Mathf.Clamp(verticalRotation, -90f, 90f);
        playerCamera.transform.localRotation = Quaternion.Euler(verticalRotation, 0f, 0f);
    }
}

滑らかな移動の実装

加速・減速を含む、より自然な移動感を実現:

public class SmoothInputMovement : MonoBehaviour
{
    [Header("滑らかな移動")]
    public float moveSpeed = 5f;
    public float acceleration = 10f;

    private Vector2 currentVelocity;
    private Vector2 targetVelocity;
    private Rigidbody2D rb;
    private Vector2 moveInput;

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
    }

    void Update()
    {
        // 目標速度を設定
        targetVelocity = moveInput * moveSpeed;

        // 滑らかに目標速度に近づける
        currentVelocity = Vector2.Lerp(currentVelocity, targetVelocity, acceleration * Time.deltaTime);

        // 物理に適用
        rb.velocity = new Vector2(currentVelocity.x, rb.velocity.y);
    }

    public void OnMove(InputAction.CallbackContext context)
    {
        moveInput = context.ReadValue<Vector2>();
    }
}

マルチプレイヤー対応

Input Systemは複数プレイヤーの入力を簡単に管理できます:

public class MultiPlayerMovement : MonoBehaviour
{
    [Header("移動設定")]
    public float moveSpeed = 5f;
    public int playerIndex = 0;

    private Rigidbody2D rb;
    private PlayerInput playerInput;

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        playerInput = GetComponent<PlayerInput>();
        playerInput.playerIndex = playerIndex;
    }

    public void OnMove(InputAction.CallbackContext context)
    {
        Vector2 moveValue = context.ReadValue<Vector2>();
        rb.velocity = new Vector2(moveValue.x * moveSpeed, rb.velocity.y);
    }

    public void OnJump(InputAction.CallbackContext context)
    {
        if (context.performed)
        {
            rb.velocity = new Vector2(rb.velocity.x, 10f);
        }
    }
}

Input Systemの主な利点

1. マルチプラットフォーム対応

  • キーボード、ゲームパッド、タッチスクリーンを統一的に扱える
  • デバイス固有の処理を意識する必要がない

2. 柔軟なキーバインド

  • ランタイムでのキー設定変更が簡単
  • 複数の入力デバイスから同じアクションを実行可能

3. パフォーマンス向上

  • ポーリングベースからイベントベースへの変更
  • 必要な時のみ処理が実行される

4. デバッグ機能

  • Input Debuggerでリアルタイムの入力状況を確認可能
  • 入力の遅延やドロップを視覚的に確認

まとめ

Unity Input Systemを使用することで、従来のInput Managerでは難しかった柔軟で拡張性の高い入力システムを構築できます。特にマルチプレイヤーゲームやクロスプラットフォーム対応を考慮している場合は、Input Systemの導入を強く推奨します。

実装時のポイント:

  • Player Inputコンポーネントの設定を忘れずに
  • Input Actions AssetのAction Typeを適切に設定
  • context.performedとcontext.canceledの使い分けを理解する

訪問数 33 回, 今日の訪問数 3回