【Unity】ゲームの操作入力の判定方法

Unity-キーボードなどの入力を判定するには? Unity
スポンサーリンク

ゲームの操作方法にはいろいろな種類があります。
例えばPCゲームならマウスやコントローラー・キーボードで操作しますし、スマホゲームならタップやフリックして操作すると思います。

この記事ではUnityで以下の入力を判定する方法について紹介します。
・マウス操作
・キーボードの入力
・ゲームパッドの入力
・モバイル端末の操作

マウス操作の判定

1.マウスカーソルの座標

マウスカーソルの座標は「Input.mousePosition」で取得できます。
以下はマウスにオブジェクトを追従させるスクリプトの例です。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MouseScript : MonoBehaviour
{
    private Camera cam;
    void Start()
    {
        // MainCameraタグのついているカメラを取得
        cam = Camera.main;
    }
    void Update()
    {
        // ScreenToWorldPointでスクリーン座標からワールド座標へ変換
        gameObject.transform.position = cam.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, 10));
    }
    /// <summary>
    /// ラベル表示
    /// </summary>
    void OnGUI()
    {
        GUILayout.BeginArea(new Rect(20, 20, 250, 120));
        GUILayout.Label("Screen pixels: " + cam.pixelWidth + ":" + cam.pixelHeight);
        GUILayout.Label("スクリーン座標: " + Input.mousePosition);
        GUILayout.Label("ワールド座標: " + gameObject.transform.position);
        GUILayout.EndArea();
    }
}

「Input.mousePosition」はスクリーン座標で取得されるので、「ScreenToWorldPoint」でワールド座標に変換してからオブジェクトの座標に設定しています。
Z座標はカメラからの奥行になるため、今回は「10」を入れてみました。
※マウスのZ座標が「0.0f」なので、マウスのZ座標で設定するとカメラにオブジェクトがぴったりくっついてしまい上手く表示されなくなります。

    void Update()
    {
        // ScreenToWorldPointでスクリーン座標からワールド座標へ変換
        gameObject.transform.position = cam.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, 10));
    }

スクリプトをオブジェクトにつけて実行すると、マウスカーソルと一緒にオブジェクトが動きます。

マウスカーソルにオブジェクトが追従しているgif
マウスカーソルにオブジェクトが追従しました
スクリーン座標・ワールド座標とは?

スクリーン座標とワールド座標はどちらも座標を表すものですが、基準となる位置が異なります。
スクリーン座標は解像度に一致します
例えば解像度が1920×1080の場合は左上が(0,0)、右下が(1920,1080)になります。
ワールド座標は画面の原点が中心となり、そこからx軸、y軸、z軸方向に値が変わります
オブジェクト選択時にInspectorウィンドウに表示されているTransformと同じです。

スクリーン座標とワールド座標の説明画像
解像度が1920×1080の場合の例です

2.マウスクリック

マウスクリックは「Input.GetMouseButton」系のメソッドで取得できます。
3つ種類があり、どれもbool型で返却されます。
・GetMouseButton:マウスがクリックされている間はtrueを返します
・GetMouseButtonDown:マウスをクリックしたフレームのみtrueを返します
・GetMouseButtonUp:マウスのクリックを離したフレームのみtrueを返します

以下はマウスの左クリックがされたかどうかを検知するスクリプトの例です。
引数に渡す値が0の場合は左クリック、1の場合は右クリック、2の場合はマウスホイールを検知できます。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MouseScript : MonoBehaviour
{
    private string msg, msg2;
    void Start()
    {
        msg = "";
        msg2 = "";
    }
    void Update()
    {
        // 0:左クリック, 1:右クリック, 2:マウスホイール
        if (Input.GetMouseButton(0))
            msg = "クリック中";
        else
            msg = "クリックしてない";
        if (Input.GetMouseButtonDown(0))
            msg2 = "左クリックした";
        if (Input.GetMouseButtonUp(0))
            msg2 = "左クリックを離した";
    }
    /// <summary>
    /// ラベル表示
    /// </summary>
    void OnGUI()
    {
        GUILayout.BeginArea(new Rect(20, 20, 250, 120));
        GUILayout.Label(msg);
        GUILayout.Label(msg2);
        GUILayout.EndArea();
    }
}

実行するとクリックに反応して画面に文字が表示されます。
GetMouseButtonDownとGetMouseButtonUpはフレームでの判定になるためこの例では分かりにくいですが、押した瞬間と離した瞬間にtrueが返ります。

クリック検知するgif
クリックしている間は「クリック中」、離している間は「クリックしてない」

3.マウスドラッグ

マウスドラッグは「OnMouseDrag」を使うと簡単に実装できます。
ただし、レイヤーが「Ignore Raycast」になっているオブジェクトには使用できないので注意してください
以下はオブジェクトをドラッグすると色が黒く変わっていくスクリプトの例です。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MouseScript : MonoBehaviour
{
    private Renderer rend;
    private Camera cam;
    void Start()
    {
        rend = GetComponent<Renderer>();
        cam = Camera.main;
    }
    void OnMouseDrag()
    {
        rend.material.color -= Color.white * Time.deltaTime;
        gameObject.transform.position = cam.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, 10));
    }
}

赤いオブジェクトと緑のオブジェクトの2つ用意しました。
緑のオブジェクトの方はレイヤーが「Ignore Raycast」になっています。
両方のオブジェクトにスクリプトとBoxColliderをアタッチして実行してみると、赤いオブジェクトはドラッグで位置と色が変わりましたが、緑のオブジェクトはドラッグに反応しませんでした。

マウスドラッグするgif
緑のオブジェクトはレイヤーが「Ignore Raycast」なのでOnMouseDragは効きません

4.マウスホイールのスクロール

「Input.mouseScrollDelta」でマウスホイールのスクロール量を取得できます。
以下はマウスホイールをスクロールしてオブジェクトを上下に移動させるスクリプトの例です。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MouseScript : MonoBehaviour
{
    void Update()
    {
        Vector3 pos = gameObject.transform.position;
        pos.y += Input.mouseScrollDelta.y * 0.1f;
        gameObject.transform.position = pos;
    }
}

実行すると、スクロールでオブジェクトのy座標が移動します。

スクロールでオブジェクトを移動させるgif
上下にスクロールするとオブジェクトが動きます

キーボード入力の判定

1.指定キーが入力されたかどうかの判定

キーボードの入力判定はマウスクリックと似ていて、「Input.GetKey」系のメソッドで取得できます。
こちらも3つ種類があり、どれもbool型で返却されます。
・GetKey:キーを押している間はtrueを返します
・GetKeyDown:キーを押したフレームのみtrueを返します
・GetKeyUp:キーを離したフレームのみtrueを返します

マウス(GetMouseButton)の場合は「0」で左クリック、「1」で右クリックのように識別しましたが、キーボード(GetKey)ではstring型の文字列でキーを識別する方法と、KeyCodeで識別する方法があります。
公式のUnityマニュアルに記載があるので、文字列で識別するキーについてはInput Managerを、KeyCodeについてはKeyCodeを参照してください。

以下は文字列とKeyCodeで指定したキーが入力されたかどうかを判定するスクリプトの例です。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class KeyboardScript : MonoBehaviour
{
    private string msg;
    void Start()
    {
        msg = "";
    }
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
            msg = "スペースが押された";
        if (Input.GetKeyDown("a"))
            msg = "aが押された";
    }
    /// <summary>
    /// ラベル表示
    /// </summary>
    void OnGUI()
    {
        GUILayout.BeginArea(new Rect(20, 20, 250, 120));
        GUILayout.Label(msg);
        GUILayout.EndArea();
    }
}

実行すると、スペースキーを押したときとAキーを押したときに画面に文字が表示されます。

キー入力を検知するgif
スペースキーとAキー以外はスクリプトに記述されていないので押しても反応しません

2.水平方向・垂直方向の入力の判定

上で説明した「Input.GetKey」は個別にキーを判定する方法なので、矢印キーを入力しても「左矢印が押された」「上矢印が押された」という情報しか分かりません。
水平方向・垂直方向で入力を取得したい場合は「Input.GetAxiz」「Input.GetAxizRaw」を使用します
・GetAxizRaw:-1、0、1で値を返します
・GetAxiz:-1から1の範囲で値を返します

以下は矢印キー(WASDキー)の入力に応じてオブジェクトを回転させるスクリプトの例です。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class KeyboardScript : MonoBehaviour
{
    void Update()
    {
        float h = Input.GetAxisRaw("Horizontal") * 70f *  Time.deltaTime;
        float v = Input.GetAxisRaw("Vertical") * 70f * Time.deltaTime;
        transform.Rotate(v, h, 0);
    }
}

実行すると矢印キー(WASDキー)の入力でオブジェクトが回転します。

オブジェクトを回転させるgif
水平方向と垂直方向の同時入力もできます

引数に指定した「Horizontal」「Vertical」に該当するキーはInputManagerで確認できます。
例では「Horizontal」が左右の矢印キーとAキーとDキー、「Vertical」が上下の矢印キーとSキーとWキーになっています。
各種キーの割り当てはここで設定できます。

InputManagerの画像
キー設定を変えれば他のキーでも同じ操作ができるようになります

ゲームパッド(コントローラー)入力の判定

ゲームパッドでの入力判定はこれまで説明してきたマウスやキーボードとほぼ同じです。
ボタンの入力は「Input.GetButton」「Input.GetButtonDown」「Input.GetButtonUp」で、スティック入力は「Input.GetAxiz」「Input.GetAxizRaw」で判定できます。
以下はゲームパッドでオブジェクトを移動させ、AボタンとBボタンでオブジェクトの色を変更するスクリプトの例です。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GamepadScript : MonoBehaviour
{
    private Renderer render;
    void Start()
    {
        render = GetComponent<Renderer>();
    }
    void Update()
    {
        // スティック移動
        Vector3 pos = transform.position;
        pos.x += Input.GetAxis("Horizontal") * 10f *  Time.deltaTime;
        pos.y += Input.GetAxis("Vertical") * 10f * Time.deltaTime;
        transform.position = pos;
        if (Input.GetButton("Fire1"))
        {
            render.material.color -= Color.white * Time.deltaTime;
        }
        if (Input.GetButton("Fire2"))
        {
            render.material.color += Color.white * Time.deltaTime;
        }
    }
}

実行結果です。「Horizontal」などで識別しているのでキーボードでも移動できます。

ゲームパッドでの操作gif
ゲームパッドでも問題なく動かせました

ちなみに使用したゲームパッドはこれです。
買ったのがかなり前のことなので覚えていませんがUnityのコンソールには「XBOX 360 For Windows」って表示されたので多分XBOXのコントローラーだと思います。
パソコンに認識されるものであればおそらくどのコントローラーでも大丈夫でしょう。

ゲームパッドの画像
関係ないですが最近のスマホって画質すごいですね
目視で見えてなかった汚れがはっきり見える…

モバイル端末(スマホ・タブレットなど)のタップ操作の判定

モバイル端末のタップを判定するには「Touch」を使用します。
以下はタップした場所にオブジェクトを生成し、現在タップしている数を画面に表示するスクリプトの例です。
オブジェクトを生成する際、タップした位置をスクリーン座標からワールド座標へ変換しています。
※「GUIStyle textStyle」は画面に表示するラベルのサイズを設定するために追加した部分なので処理には関係ありません。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MobileScript : MonoBehaviour
{
    public GameObject particle;
    public GUIStyle textStyle;
    Camera cam;
    void Start()
    {
        cam = Camera.main;
    }
    void Update()
    {
        foreach (Touch touch in Input.touches)
        {
            // タップした瞬間であれば
            if (touch.phase == TouchPhase.Began)
            {
                // オブジェクトを生成
                Instantiate(particle, cam.ScreenToWorldPoint(new Vector3(touch.position.x, touch.position.y, 10)), transform.rotation);
            }
        }
    }
    void OnGUI()
    {
        // タップしている数を表示
        Rect rect = new Rect(10, 10, 100, 200);
        GUI.Label(rect, "Touch" + Input.touchCount, textStyle);
    }
}

Androidで実行した結果です。
1か所のタップはもちろん、複数を同時にタップしても反応します。

Androidで実行したgif
左上のカウントは現在タップしている数を表示しています

タップの瞬間を取得するのに「TouchPhase.Began」を使っていますが、TouchPhaseにはこの他にも移動中を表すMovedやキャンセルを表すCanceledなどが定義されています。
UnityスクリプトリファレンスのTouchにいろいろ書いてありますので確認してみてください。

タップ操作はマウスのクリックで使用した「GetMouseButton」でも判定することができます。
左クリックと同じ「0」を指定することでモバイル端末上でのタップ判定になります。
ただし、マウス操作の場合1本指でのタップ操作になるので、マルチタップに対応させたい場合は「Touch」を使用する必要があります

まとめ:マウス・キーボード・ゲームパッド操作はほぼ同じ!モバイル向け操作ならTouchを使う!

入力系の操作は「GetKeyDown」や「GetMouseButtonDown」など似た名前のものが多いです。
マウスなのかキーボードなのかによってメソッドの名前は変わりますが押した瞬間・離した瞬間などのタイミングの考え方は一緒なので、一度覚えてしまえば簡単に実装できると思います!
モバイル端末の操作は他と少し違いますが、こちらもTouchを使うだけでそこまで複雑ではなさそうです。
スクリプトリファレンスを読みながらいろいろ試してみるのも面白いですね!

コメント

タイトルとURLをコピーしました