Input Systemを利用して、シューティングゲームを作ってみる

# はじめに
最近、Input Systemをさわってみたので、備忘録として簡易的なシューティングゲームを作ってみました。
この記事は、Input Systemを利用した部分にフォーカスして記載します。

# Input Systemのインストール
1. Unity ProjectにInput Systemをインストールします。
![スクリーンショット 2023-09-18 133106.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2729904/fa1adbab-b9eb-0413-e2bf-0cb543e54074.png)

1. Unity Editorを再起動します
![スクリーンショット 2023-09-18 133152.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2729904/1db5ea01-549a-5bef-d0ce-30d6b6666f00.png)

# Projectビューで、Input Actionsを作成
Create > Input Actions
ここでは、「InputActions」という名称で作成しています
![スクリーンショット 2023-09-18 192313.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2729904/4c0bde0f-7574-5ba0-61f5-400bee89ff37.png)

# Input Actions の設定
1. 作成したInput Actions をダブルクリック
![スクリーンショット 2023-09-18 133829.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2729904/7a0e11d7-afa7-3e1b-5724-271f0d310f9e.png)

1. Action Maps の右のプラスボタンをクリックして、「PlayerController」という名称でAction Mapを作成します
![スクリーンショット 2023-09-18 134004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2729904/94749dbc-7c54-ba3d-c10e-db9ef4e430d0.png)

1. 自動作成された「New action」というActionの名称を「Move」に変更します
![スクリーンショット 2023-09-18 193131.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2729904/900f6395-dd80-b9ce-d829-6d43f3ec5828.png)

1. 「Move」Action のAction Typeを「Value」、Control Typeを「Vector2」に変更します
![スクリーンショット 2023-09-18 193219.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2729904/805b2142-089c-25eb-789b-6a9c77de96b0.png)

1. 「Move」Actionの下の No Bindings というBindingを削除します。そして、「Move」Actioinの右のプラスボタンから「Add Up\Down\Left\Right Composite」を選択します
![スクリーンショット 2023-09-18 193730.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2729904/bf7f19a5-7cc6-6192-9d45-6520cb7cd4c4.png)

1. Up/Down/Left/Right それぞれのBinding PropertiesのBinding Pathに以下を設定します
Up : Keybord > By Location of Key > Up Arrow
Down : Keybord > By Location of Key > Down Arrow
Left : Keybord > By Location of Key > Left Arrow
Right : Keybord > By Location of Key > Right Arrow
![スクリーンショット 2023-09-18 194254.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2729904/37f9b0eb-1fe1-1d1c-1f31-358916a784bc.png)

1. Actions の右のプラスボタンをクリックして「Fire」アクションを作成します
![スクリーンショット 2023-09-18 194541.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2729904/222274a3-8900-ce9b-5769-5a3074b159ef.png)

1. 「Fire」Actionの下の No Binding をクリックします。Binding PropertiesのBinding Path に以下を設定します
Keybord > By Location of Key > Space
![スクリーンショット 2023-09-18 194955.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2729904/163a4b1f-d12c-b15c-87ac-605a1814618c.png)

1. 「Save Asset」ボタンをクリックします

# Playerとなる機体オブジェクトの設定
1. 機体オブジェクトに「Player Input」コンポーネントをアタッチします。あわせて、Actions に上で作成した「InputActions」を設置します
![スクリーンショット 2023-09-18 195718.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2729904/fe1eeb72-d8b7-0c46-9f02-8e9b99404840.png)

1. PlayerMove　スクリプトを以下のように作成して、機体オブジェクトにアタッチする
![スクリーンショット 2023-09-18 201751.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2729904/4c82c4f6-8ba0-7d9f-084f-3fa6489fd105.png)


```c#:PlayerMove.cs
using UnityEngine;
using UnityEngine.InputSystem;

namespace UnitySkillTest
{
    [RequireComponent(typeof(PlayerInput))]
    public class PlayerMove : MonoBehaviour
    {
        [Header("ミサイルPrefab"), SerializeField] private GameObject _missilePrefab;
        [Header("ミサイルの射出位置"),SerializeField] private Transform _missileSpawnPoint;
        
        [Header("機体のスピード"), SerializeField] private float _speed = 10f;
        private float _rotateAngle = 30f;   // プレイヤーの傾き角度

        private PlayerInput _playerInput;   // PlayerInputコンポーネント
        private InputAction _moveAction;    // Moveアクション
        
        private void Awake()
        {
            // PlayerInputコンポーネントを取得
            _playerInput = GetComponent<PlayerInput>();
        }

        // Start is called before the first frame update
        void Start()
        {
            // Moveアクションを取得
            _moveAction = _playerInput.actions["Move"];
            
            // Moveアクションが取得できなかった場合はゲームを終了
            if (_moveAction is null)
            {
               Application.Quit(); 
            }
        }

        // Update is called once per frame
        void Update()
        {
            // Moveアクションが押されている場合
            if (_moveAction.IsPressed())
            {
                // Moveアクションは、Vector2の値を設定しているため、Vector2を取得できる
                // 以下の値が取得できる
                // UP: (0, 1)
                // DOWN: (0, -1)
                // LEFT: (-1, 0)
                // RIGHT: (1, 0)
                Vector2 direction = _moveAction.ReadValue<Vector2>();
                Vector3 moveDelta = new Vector3(direction.x, direction.y, 0) 
                                    * (_speed * Time.deltaTime);
                transform.position += moveDelta;
            }
        }
        
        /// <summary>
        /// Moveアクションが押された時、Player Input コンポーネントによって、自動的に呼び出される
        /// 名称は、On + アクション名 とする必要がある
        /// </summary>
        /// <param name="value"></param>
        private void OnMove(InputValue value)
        {
            // LEFT、RIGHTのみ傾けるため、xの値のみ利用
            transform.rotation = Quaternion.Euler(
                0, 
                0, 
                value.Get<Vector2>().x * (-1) * _rotateAngle);
        }

        /// <summary>
        /// Fireアクションが押された時、Player Input コンポーネントによって、自動的に呼び出される
        /// 名称は、On + アクション名 とする必要がある
        /// </summary>
        /// <param name="value"></param>
        private void OnFire(InputValue value)
        {
            Instantiate(_missilePrefab, _missileSpawnPoint.position, Quaternion.identity);
        }
    }
}
```