LoginSignup
1
3

More than 5 years have passed since last update.

Unity備忘録、STG制作5:タッチパネル操作その1

Posted at

※この記事は2016年当時に在籍していた某社内での(略)、ある日、UnityでVRアプリを作って商売しようという話になった。だがちょっと待って欲しい、俺(達)は趣味でUnityを使っているわけであって、とてもじゃないが商業アプリなんか作れるレベルじゃないぞ!? まず本業を安定させてからやるべきじゃないのか? 皆がそう思っていた。。。(続く)

背景

スマホでゲームをする場合、当然だがタッチおよびタッチ座標を検出しなければならない。
PC用のゲームだったら十字キーで簡単に操作出来たのにね。
とりあえず今回は簡単だと思われる方法で、タッチ操作によるキャラ移動方法を記載する。

タッチ有無を検出する

以下のメソッドを使うことでタッチしたかどうかを検出できる。
Input.GetMouseButtonDown(0) //タッチした瞬間のみTRUEを返す
Input.GetMouseButton(0) //タッチしている間はTRUEを返す
Input.GetMouseButtonUp(0) //離した瞬間にTRUEを返す

ちなみに名前からも分かる通り、本来はマウスボタン押下の検出に使うメソッドなのだが、実はシングルタッチにも使える。2点タッチやドラッグなどを検出したい場合はタッチパネル専用のメソッドを使うこと。

タッチ座標を検出する

例えば自分のスマホ(SHARPのSHV31)の解像度は1920x1080のFullHDである。
なので座標としては下記図のようになる。
01.png

この座標を取得する場合は下記のメソッドを使えばよい。これもマウス用のメソッドだが、シングルタッチでも同様に使用可能。
Input.mousePosition;

タッチ座標をワールド座標に変換する

さて、タッチ座標は上記のメソッドで取得できるようになるが、実はこれだけでは不十分である。
例として、下記図の設定でのカメラ座標は(0, 0, -10)だと分かるが、これはワールド座標系での座標を意味している。
カメラを中心とした座標はこんな感じになっており、タッチパネルと明らかに異なることが分かる。
02.png

つまりタッチ座標をワールド座標に変換しなければならない。変換は下記のメソッドを使えばよい。
Camera.main.ScreenToWorldPoint(Vector3 position);

サンプルコード

このコードは、
 (1)タッチを検出
 (2)タッチ座標を検出
 (3)タッチ座標をワールド座標に変換
 (4)キャラ位置とタッチ位置から移動方向ベクトルを計算
 (5)(4)の計算値をvelocityにセットしてキャラを移動させる
 (6)指を離したときはキャラを停止する
という処理となっている。

moveTest.cs
using UnityEngine;
using System.Collections;

public class MoveTest : MonoBehaviour {
    public static Vector2 screenPos; 
    public static Vector2 worldPos;

    // Update is called once per frame
    void Update () {
        if (Input.GetMouseButtonDown(0) || Input.GetMouseButton(0)) {
            screenPos = Input.mousePosition;
            worldPos = Camera.main.ScreenToWorldPoint(screenPos);

            //指で隠れないようにタッチ座標の少し上を移動地点に設定する
            Vector3 fixWorldPos = worldPos;
            fixWorldPos.y += 0.7f;

            //タッチ位置からキャラ位置を引くことで、移動方向のベクトルが求められる。
            //距離が離れているほど移動速度が早くなり、近づくにつれて減速する。
            //あとは適度に係数を掛けることで移動速度を調整することもできる。
            GetComponent<Rigidbody2D>().velocity = (fixWorldPos - transform.position) * 10;

            //ちなみに移動速度を一定にしたい場合はnormalizedプロパティを用いて単位ベクトルに変換すればよい
            //GetComponent<Rigidbody2D>().velocity = (fixWorldPos - transform.position).normalized * 3;
        }

        if (Input.GetMouseButtonUp (0)) {
            GetComponent<Rigidbody2D>().velocity = Vector3.zero;

        }

    }
}

実行結果

タッチ座標(screenPos)がワールド座標(worldPos)に変換され、かつタッチ位置にキャラが移動することを確認できた。
毎フレームでタッチ検出してるので、ドラッグ操作も一応できる。
03.png

今後の課題

色々タッチして気づいたのだが、スマホ上ではワールド座標の左右が切れていることが分かった。Y座標については-5~5をカバーしており問題なし。
(Unityエディタ上では、ワールド座標のX座標は-3.125~3.125まであるはずなのに、スマホ上では-2.8~2.8くらいになっている)
試しにスマホを横置きにしてみたところ、Y座標は-5~5を保っており問題ないが、X座標は逆に範囲が拡大してしまった。
おそらくY座標の設定を優先しているからだと思われる。これはスマホのアスペクト比によって画面表示範囲が異なることを意味している。左右端がカットされるor拡大されると問題があるゲームの場合は要検討である。
04.png

以上

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3