どうもなおゆです。
スマホアプリのズーム動作を実装する際に、タッチ処理について何日も悩んだので備忘として記事をのこしておきます。
スマホのタッチ動作とズーム動作の原理について解りやすく図解で説明
今回は原理についてのみ説明して、実装コードは掲載しません。皆さんには雰囲気を理解していただければそれで充分です。
タッチ動作と一口に言っても、Unity上のマウスクリック動作もスマホ画面ではタッチとして扱われます。しかし今回は二本指を使ったズーム機能も考慮していますのでInput.touches等について触れていきます。
※ 今回のタッチ処理のデバッグは実機で行いました。(これが理解を遅くする理由泣)
タッチ関係について以下の3つをなんとなく理解していればスワイプやズーム機能等を実装できますので、前半はこれらについて説明していきます。
- Input.touchCount
- TouchPhase.〇〇
- Input.touches[ ]
Input.touchCountについて
まずはtouchCountです。これはint型で画面をタッチしている指の数をカウントしてくれます。触れている指の本数を使った条件分岐等に利用できます。
カウントが0の場合
touchCount = 0 であれば画面にタッチしていない状態です。普通のゲームであれば待機状態ですね。
if (Input.touchCount = 0)
{
//画面に触れていない場合の処理
}
カウントが1の場合
touchCount = 1 は画面に一本の指が触れている状態です。スワイプやキャラの移動が想定されます。
if (Input.touchCount = 1)
{
// スワイプ処理など
}
カウントが2の場合
touchCount = 2 は画面に二本の指が触れている状態です。ピンチ(ズーム)処理などが想定されます。
if (Input.touchCount = 2)
{
// ズーム処理など
}
これらを組み合わせると待機状態の処理・スワイプ処理・ピンチ処理の状態を管理できます。
if (Input.touchCount = 0)
{
//待機状態の処理
}
else if (Input.touchCount = 1)
{
// スワイプ処理
}
else if (Input.touchCount = 2)
{
// ズーム処理
}
else
{
// それ以外の処理(例外とか)
}
TouchPhaseについて
さらに、触れている指の状態を管理できるのがTouchPhaseです。説明についてはUnityスクリプトリファレンスから引用させていただきます。
Began | 画面に指が触れたとき |
Moved | 画面上で指が動いたとき |
Stationary | 指が画面に触れているが動いてはいないとき |
Ended | 画面から指が離れたとき |
Canceled | システムがタッチの追跡をキャンセルしました |
// TouchPhase.〇〇みたいな感じで書く
使い方はこんな感じで条件分岐に使用します。
if (touch.phase == TouchPhase.Ended)
{
// 指を離した瞬間の処理
}
Input.touches[ ]について
Input.touches[ ]はTouch型の値が配列として割り当てられます。簡単に言うと、タッチした指ごとに番号が割り振られるため、その番号を条件分岐に使用できるという事です。
画面サイズの拡大・縮小(ピンチ)の実装のしかた
以上三つを組み合わせることでズームなどを実装できます。
まず基本的な説明ですが、スマホで拡大・縮小する時は2本の指でつまむように操作します。これを「ピンチ」と呼びます。
指の間隔を狭くする事を「ピンチイン」指の間隔を狭くする事を「ピンチアウト」と呼び、これをtouch系の処理で実装していきます。
ピンチ処理の原理
ピンチ処理とは、最初に触れた位置・現在触れている位置。この二つの座標の差を求めることでどれくらいの拡縮にするかを決めます。
一つ目の座標は画面に最初に触れた位置です。それを代入する変数をVector2型のbaseDistanceとしましょう。
この変数は指0と指1の距離を代入したものです。方法としてはVector2.Distanceで指0・指1の二点間の距離を求めそれを代入しています。この変数が基準となるため、画面から指を離すまでこの変数は変動しません。
初期位置の取得
if (Input.touches[0].phase == TouchPhase.Moved || Input.touches[1].phase == TouchPhase.Moved)
{
baseDistance = Vector2.Distance(Input.touches[0].position, Input.touches[1].position);
}
現在位置の取得
次に現在触れている位置です。変数名はVector2型のcurrentDistanceとしましょう。指を動かしている間の現在座標を変数に代入し続けるため、値は常に変動します。
float currentDistance = Vector2.Distance(Input.touches[0].position, Input.touches[1].position);
二つの座標の差を求める
この二つの変数の差を求めることで、どれぐらいピンチしたのかを検知できます。これを変数に代入します。今回は仮にpinchDistanceとします。
float pinchDistance = (baseDistance - currentDistance);
このpinchDistanceを元に、カメラのtransformを変更するようなスクリプトを作成するとズーム機能などを実装できます。
以上。簡単ですみませんが原理はこういう事です。実際に実装コードもいつか載せたいのですが…長くなりそうなので未定です。(汗)
ではまた!
コメント