以前、Unityチュートリアルで作成したシューティングゲームに、
バーチャルジョイスティックを導入しました。
しかし、タッチパネルでのバーチャルジョイスティックでの操作は、
細やかな操作が必要なシューティングゲームでは使い物にならないことがわかりました。
(敵の弾がよけられない!!)
そこで今回は、タッチパネル操作にてプレイヤーを移動させる機能を実装していきます。
イメージとしてはこんな感じです。
①ユーザが画面の自機をタッチ
②ユーザが自機をタッチしたまま、移動させたい場所まで指を動かす
③自機はユーザの指に追随して動く
目次
案1 自機のポジションにタッチした場所の座標を代入する
Player.cs
if (Input.touchCount > 0) { Touch touch = Input.GetTouch (0); Vector3 vec = touch.position; vec.z = 10f; vec = Camera.main.ScreenToWorldPoint (vec); transform.position = vec; }
案1は、ユーザがタッチした場所に自機のポジションを変える方法です。
Camera.mainでメインカメラを取得できます。
そしてカメラの関数である、ScreenToWorldPointを使用し、スクリーン座標をワールド座標に変換します。
Input.touch.positionの情報は、そのままだとスクリーン座標というものになりますので、
実際にゲームの中で使われている、ワールド座標に変換する必要があります。
この方法だと、指にぴったり自機が移動するため、かなり弾がよけやすくなりました。
しかしながら、この方法だと自機の位置から離れた位置をタップすれば、
そこに自機がワープすることができてしまいます!!
そのため、
弾が来た!⇒敵の背後にワープ
みたいなスーパーサイヤ人ばりの回避ができてしまうので、 今回この方法はボツです。
苦労した点
vecにvec.z = 10fと代入しているのは、touch.positionにはz座標情報がないため。
そのままではうまくScreenToWorldPointで変換してくれない。
10fはメインカメラから対象までの距離をあらわす。
案2 タッチの移動量を使う
Player.cs
if (Input.touchCount > 0) { float x = touch.deltaPosition.x; float y = touch.deltaPosition.y; // 移動する向きを求める Vector2 direction = new Vector2 (x, y); // 移動する向きとスピードを代入する Move (direction); }
touch.deltaPositionはタッチで移動した量をあらわす。
このタッチ移動量xとタッチ移動量yから2次元ベクトルを作成し、
Move関数に代入する。
Move関数は公式チュートリアルで作成したものです。
チュートリアルの関数だと、ベクトルを作成する際に
Vector2 direction = new Vector2 (x, y).normalized;
というようにnormalizedがついていますが、
これはベクトルを単位ベクトル(大きさ1のベクトル)に変換する関数です。
今回は'向き'だけでなく、タッチで移動した'量'もMove関数に伝えたいため付けません。
Playerプレハブのspeed変数を1に変更します。
そうしないと、タッチ移動量のspeed倍を自機が移動してしまいます。
苦労した点
最初normalizedの意味を理解していなかったため付けたまま試験し、
タッチ移動量と自機の移動量が微妙に違う結果となり、なんでだろうと数日悩んでました。
厳密にいうと案2は指を追随するのではなく、タッチ移動量の通り自機が動く仕組みのため
当初想定していた動きとは若干ことなるのですが、
実機で操作してみたら頭の中で思い描いていた通りに動いてくれたのでこちらを採用します。