【Unity】Touch構造体とは?画面上の指のタッチ情報を管理

Touch構造体とは? Unity

こんにちは、ともくんのゲーム作り部屋にようこそ!

このページでは、

「UnityのTouch構造体ってなに?」

「ゲーム内を指で操作する処理を作りたい!」

というお悩みの方に向けた内容となっています。

ゲームの画面をスマホやタブレットなどの指で操作する際に、UnityではTouchという構造体が使われることがあります。

このTouchとは、ゲーム画面上での指によるタッチ状態を管理している構造体で、InputクラスのGetTouchメソッドで取得することができます。

Touch構造体を使うことで、画面上で複数の指を使った操作処理や、指が動いているかどうかなどの状態を判定してゲーム処理を作ることができます。

そこで、このページでは、UnityのTouch構造体について、どんな仕組みなのか、また基本的な使い方までをまとめていきます。

この記事を書いた人

ゲーム作りを学び始めた一児のパパです。
このブログは、子供から「ゲームを作ってみたい!」と言われ、非プログラマーでゲーム作りをしたことない僕が、ゲーム作りの本を読んで独学でゲーム開発を学んでいるブログです。
同じように初めてゲーム作りをしている方と一緒に学んでいけるようなブログに出来たらいいなと思っています。
また、「このコードはおかしい」とか「もっと良い書き方があるよ!」などあれば、どんどん指摘して頂けると助かります。

Touch構造体とは?

まずは、Touch構造体がどういうものなのかを紹介していきます。

画面を指でタッチした状態を保持する構造体

Touch構造体とは、冒頭でも解説した通り、ゲームの画面上において指で操作している状態を管理している構造体です。

もう少し具体的に言うと、Touch構造体は画面を指でタッチした際に、それぞれの指における情報(変数)を保持しているもので、

  • その指が動いているのか離れているのか?
  • その指の座標がどこにあるのか?
  • その指は何回タップされたのか?
  • タッチされてからどのくらいの時間が経過したのか?

といった情報を管理している構造体となっています。

マルチタップ操作などを作れるようになる

Touch構造体を使うことで、複数の指を使った処理を作る際に非常に便利に使えます。

そもそもUnityで指のタッチ操作処理を作る場合、InputクラスGetMouseButtonメソッドを使うことで、スマホなどのタップ操作も判定することができます。

ただし、このGetMouseButtonメソッドはあくまでもマウスのクリックを判定するものになっているので、1本の指でタッチ操作の処理を作るだけであれば問題ありませんが、複数の指を使った処理を作る場合には適していません。

一方で、Touch構造体では、それぞれの指ごとに動きや状態を管理していくことができるので、複数の指を使った処理を作ることができるようになります。

例えば、2本の指を使ったピンチ操作によるズーム処理であったり、複数の指で座標の位置を指定して、その座標間でオブジェクトを移動させる処理などをTouch構造体を使って作ることができます。

なお、Touch構造体は指でのタッチ操作だけに反応し、パソコンでのマウスクリックでは判定することができないので、スマホなどの実機を使って検証するのが良いでしょう。

Touch構造体の基本的な使い方

ここからは、Touch構造体の基本的な使い方を紹介していきます。

Input.GetTouchでTouch構造体を取得する

Touch構造体を取得する際は、InputクラスGetTouchというメソッドを使います。

GetTouchメソッドは、引数にint型の0から始まる整数を指定して、以下のように記述します。

Input.GetTouch(index);

index:画面をタッチした指の番号(int型)

この引数は、複数の指がタッチされている場合、画面をタッチした指の順番で、0から始まる整数の番号が振られていきます。

例えば、最初に画面を指でタッチして、そのタッチした状態で別の指もタッチすると、

最初の指の情報:Input.GetTouch(0)
次の指の情報:Input.GetTouch(1)

と記述することで、それぞれの指のTouch構造体を取得することができます。

また、このGetTouchメソッドと一緒に使われるのがInput.touchCountという変数で、画面上で指がタッチされている数int型で取得することができます。

例えば、画面上に指を2本タッチした際に、それぞれの指のTouch構造体を取得する場合は、以下のようにスクリプトを記述していきます。

using UnityEngine;

public class Test : MonoBehaviour
{
    Touch touch0;   // 1本目の指のTouch型の変数
    Touch touch1;   // 2本目の指のTouch型の変数

    void Update()
    {
        // 2本の指がタッチされている状態
        if (Input.touchCount == 2)
        {
            touch0 = Input.GetTouch(0); // 1本目の指の情報を取得
            touch1 = Input.GetTouch(1); // 2本目の指の情報を取得
        }
    }
}

まず、5行目と6行目でそれぞれの指のTouch構造体の変数を宣言しておきます。

そして、11行目でInput.touchCount「2」、つまり2本の指で画面をタッチしている場合に、13行目と14行目でそれぞれの変数にGetTouchメソッドで取得したTouch構造体の値を入れています。

このようにtouchCountで条件指定して記述することで、指定する指の数で画面がタッチされた状態の時だけ、GetTouchメソッドの処理が行われるようになり、指のタッチ情報を取得することができます。

Touch構造体で定義されている変数

Touch構造体を取得できたら、定義されている変数を使って情報を取得していきます。

ここでは、Touch構造体の変数の中から、

  • Touch.phase:タッチしている指の状態
  • Touch.position:タッチしている指の座標
  • Touch.tapCount:その指でタップした回数
  • Touch.deltaTime:指のタッチを最後に計測してからの経過時間

上記の4つの変数について紹介していきます。

Touch.phase:タッチしている指の状態

phaseは、タッチしている指の状態を表している変数で、TouchPhaseという列挙型を使って、以下の5つの名前で表されています。

  • TouchPhase.Began:指が画面をタッチした時
  • TouchPhase.Moved:指が画面の上を動いている状態
  • TouchPhase.Ended:指が画面から離れた時
  • TouchPhase.Stationary:指が画面の上で動いていない状態
  • TouchPhase.Canceled:指が追跡不能になった状態

例えば、以下のオブジェクトを配置しておき、指が画面をタッチしたら赤色に変わり、指が画面の上を動いたら青色に変わり、指が画面から離れたら黄色に変わるという処理を作ってみます。

オブジェクトに対して、以下のスクリプトをアタッチしておきます。

using UnityEngine;

public class Test : MonoBehaviour
{
    Touch touch;   // Touch型の変数を宣言
    SpriteRenderer sr;

    void Start()
    {
        sr = GetComponent<SpriteRenderer>();    // SpriteRendererコンポーネントを取得
    }

    void Update()
    {
        // 画面に指がタッチされている場合
        if (Input.touchCount > 0)
        {
            touch = Input.GetTouch(0);  // 指のタッチ情報を取得

            // タッチ状態で条件分岐
            switch(touch.phase)
            {
                // 指でタッチされた時
                case TouchPhase.Began:
                    sr.color = Color.red;
                    break;

                // 指が動いている状態
                case TouchPhase.Moved:
                    sr.color = Color.blue;
                    break;

                // 指が離れた時
                case TouchPhase.Ended:
                    sr.color = Color.yellow;
                    break;
            }
        }
    }
}

18行目でGetTouchメソッドを使ってTouch構造体を取得して、21行目でswitch文を使ってphaseの値をそれぞれの状態毎で分けて処理を作っています。

これでゲームを実行してみると、

上記のように指をタッチした時、動かしている時、離した時でそれぞれ指定した処理が行われているのが分かります。

Touch.position:タッチしている指の座標

position変数を使うことで、タッチしている指の座標をVector3型で取得することができます。

ただし、この座標はゲーム上のワールド座標ではなく、UIなどで使われるスクリーン座標を取得することになります。

このスクリーン座標とは、画面の左下の座標を原点(0, 0)とした座標で、ゲーム内の処理で使う場合は、ワールド座標に変換して使う必要があります。

例えば、以下のオブジェクトを配置して、画面を指でタッチした場所にそのオブジェクトを移動させる処理を作ってみます。

オブジェクトに以下のスクリプトをアタッチしておきます。

using UnityEngine;

public class Test : MonoBehaviour
{
    Touch touch;   // Touch型の変数を宣言
    Vector3 touchPosition;  // タッチした座標を取得する変数

    void Update()
    {
        // 画面に指がタッチされている場合
        if (Input.touchCount > 0)
        {
            touch = Input.GetTouch(0);  // 指のタッチ情報を取得
            touchPosition = Camera.main.ScreenToWorldPoint(touch.position); // タッチしたスクリーン座標をワールド座標に変換
            transform.position = new Vector3(touchPosition.x, touchPosition.y, 0);  // オブジェクトの座標を移動する処理
        }
    }
}

13行目でGetTouchメソッドを使ってTouch構造体を取得して、14行目で指でタップした座標をposition変数で取得しています。

このposition変数の座標は、前述の通りスクリーン座標になっているので、ScreenToWorldPointメソッドを使ってスクリーン座標からワールド座標に変換する処理を行っています。

なお、ScreenToWorldPointメソッドを使った場合は、Z座標がカメラと同じ座標になってしまうため、15行目でZ座標だけ個別で設定しています。

これでゲームを実行してみると、

上記のように、指でタッチした座標にオブジェクトが移動しているのが分かります。

Touch.tapCount:その指でタップした回数

tapCountの変数は、指で画面をタップした回数int型で計測しているもので、通常はダブルタップなどを検出するために使用します。

例えば、以下のオブジェクトを配置して、1回タップしたら青色に変更して、2回タップしたら緑色に変更する処理を作ってみます。

オブジェクトに以下のスクリプトをアタッチしておきます。

using UnityEngine;

public class Test : MonoBehaviour
{
    Touch touch;   // Touch型の変数を宣言
    SpriteRenderer sr;

    void Start()
    {
        sr = GetComponent<SpriteRenderer>();    // SpriteRendererコンポーネントを取得
    }

    void Update()
    {
        // 画面に指がタッチされている場合
        if (Input.touchCount > 0)
        {
            touch = Input.GetTouch(0);  // 指のタッチ情報を取得
            
            // 1回タップした場合
            if (touch.tapCount == 1)
            {
                sr.color = Color.blue;
            }
            // 2回タップした場合
            else if (touch.tapCount == 2)
            {
                sr.color = Color.green;
            }
        }
    }
}

これまでと同様に、18行目でGetTouchメソッドを使ってTouch構造体を取得しておきます。

そして、21行目でtapCount1回の場合、26行目でtapCount2回の場合で処理を分けて記述しています。

これでゲームを実行してみると、

上記のように、シングルタップとダブルタップで処理が変わるようになりました。

Touch.deltaTime:指のタッチを最後に計測してからの経過時間

deltaTimeは、その指のタッチ情報を最後に更新してからどのくらいの時間が経過したかを秒数で取得することができる変数です。

このdeltaTimeの値を加算してあげることで、指がタッチしてから離れるまでの時間を計測することができるようになります。

例えば、ゲーム画面を指でタッチしている時間を計測して、ゲーム内に表示させてみます。

TextMeshProのオブジェクトに以下のスクリプトをアタッチしておきます。

using TMPro;
using UnityEngine;

public class Test : MonoBehaviour
{
    Touch touch;   // Touch型の変数を宣言
    TextMeshProUGUI tmp;
    float time;

    void Start()
    {
        tmp = GetComponent<TextMeshProUGUI>();  // TextMeshProのコンポーネントを取得
    }

    void Update()
    {
        // 画面に指がタッチされている場合
        if (Input.touchCount > 0)
        {
            touch = Input.GetTouch(0);  // 指のタッチ情報を取得

            //指がタッチされ始めた時
            if (touch.phase == TouchPhase.Began)
            {
                time = 0;   // 時間をリセットする
            }

            time += touch.deltaTime;    // 経過時間を加算
            tmp.text = time.ToString(); // 経過時間を表示
        }
    }
}

20行目で、GetTouchメソッドでTouch構造体を取得し、28行目でdeltaTimeの値をtimeの変数に加算していきます。

そして、29行目でTextMeshProのtext変数に、timeで計算した値をToStringメソッドを使って表示させるようにします。

これでゲームを実行してみると、

指で画面をタッチしたら時間の計測が始まり、離れたら計測が止まるようになっています。

ちなみに、指を全く動かしていない状態の場合は、指のタッチ情報が更新されないため、deltaTimeの加算が行われず、次に指を動かしたタイミングでそれまでの経過時間が加算されるようになっています。

複数の指を使った操作処理を作る

Touch構造体が使えるようになってきたところで、最後に複数の指を使った操作処理を作ってみます。

ここでは、画面を一つ目の指でタッチした場所にオブジェクトが移動するようにして、その状態でもう一つの指をタッチしたら、その場所に向かってオブジェクトが滑らかに移動するという処理を作ってみます。

まずは、以下のようにオブジェクトを配置しておき、このオブジェクトにスクリプトをアタッチしておきます。

using UnityEngine;

public class Test : MonoBehaviour
{
    Touch touch0;   // 最初の指のTouch型の変数
    Touch touch1;   // 2本目の指のTouch型の変数
    Vector3 position0;  // 最初の指の座標
    Vector3 position1;  // 2本目の指の座標
    Vector3 velocity = Vector3.zero;
    bool isMoving = false;  // 動いているかどうかを判定する変数

    void Update()
    {
        if (!isMoving)
        {
            // 画面に指がタッチされている場合
            if (Input.touchCount > 0)
            {
                touch0 = Input.GetTouch(0); // 最初の指のタッチ情報を取得
                position0 = Camera.main.ScreenToWorldPoint(touch0.position);    // 最初の指のタッチ座標を取得
                transform.position = new Vector3(position0.x, position0.y, 0);  // オブジェクトをタッチ座標に移動させる
            }
            // 指が2本タッチされている場合
            if (Input.touchCount == 2)
            {
                touch1 = Input.GetTouch(1); // 2本目の指のタッチ情報を取得
                position1 = Camera.main.ScreenToWorldPoint(touch1.position);    // 2本目の指のタッチ座標を取得
                isMoving = true;
            }
        }
        else
        {
            transform.position = Vector3.SmoothDamp(transform.position, new Vector3(position1.x, position1.y, 0), ref velocity, 1.0f);  // オブジェクトを移動させる処理

            // 移動速度が遅くなった場合
            if (velocity.sqrMagnitude < 0.1f)
            {
                isMoving = false;   // 移動処理を終了させる
            }
        }
    }
}

まず、19行目で最初の指の情報をGetTouchメソッドで取得して、タッチした場所にオブジェクトが移動するように、21行目でposition変数を使って移動させる処理を作っています。

そして、2本目の指が押されたら、同様に26行目でその指の情報をGetTouchメソッドで取得しておき、position変数の座標を取得しておきます。

あとは、移動処理を33行目でSmoothDampメソッドを使って、2本目の指の座標を目標地点として滑らかに移動させるようにしています。

これでゲームを実行してみると、

1本の指だけの場合はオブジェクトが移動するだけですが、2本目の指を押すと、そこに向かってオブジェクトが滑らかに移動されるようになりました。

まとめ

このページでは、UnityのTouch構造体について、どんな仕組みなのか、また使い方までをまとめていきましたが、いかがでしたでしょうか?

Touch構造体とは、ゲーム画面をタップしている指の情報を管理する構造体で、それぞれの指ごとに状態タップ回数座標などを取得することができます。

Unityでは、シングルタップはGetMouseButtonメソッドで対応できますが、複数の指を使う場合はTouch構造体を使うことで、処理を作ることができます。

また、Touch構造体を取得する場合は、InputクラスGetTouchメソッドを使うことで、指ごとのTouch構造体を取得することができます。

最後までお読みいただきまして、ありがとうございました!

コメント