Unityでスマホゲーム(主に2Dゲームを想定)を作ってて、
タップやスワイプでキャラを動かしたい時の実装です。
ただ、タップした「位置」にキャラを移動させてしまうと、
自分の指が邪魔してキャラが見えなくなってしまいます。
よって、今回はタップした「方向」にキャラを移動させる実装について書きます。
つまり、移動する「方向」だけをタップした位置から検知します。
移動の「大きさ」については、1つの変数の値を変えるだけの実装になっているので、楽チンです。
#サンプルコード
以下のコードを写して、そのスクリプトを動かしたいキャラのGameObjectにアタッチすれば、とりあえず動きます。
もしかしたら、上下左右ではなく、上下と奥行きにキャラが移動してしまうかもしれませんが、下の解説を読んでいけば解決するはずです。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Sample : MonoBehaviour {
float speed = 5.0f;
Vector3 preMousePos;
void Update () {
Move();
}
void Move()
{
if (Input.GetMouseButtonDown(0))
{
preMousePos = Input.mousePosition;
}
if (Input.GetMouseButton(0))
{
Vector3 mousePosDiff = Input.mousePosition - preMousePos;
preMousePos = Input.mousePosition;
Vector3 newPos = this.gameObject.transform.position + new Vector3(mousePosDiff.x / Screen.width, 0, mousePosDiff.y / Screen.height) * speed;
this.transform.position = newPos;
}
}
}
#解説
##変数宣言
float speed = 5.0f;
Vector3 preMousePos;
speed
は移動の「大きさ」を表す変数です。
speed
の値を大きくすれば、タップして指を少し動かしただけで、キャラは大きく移動し、
小さくすれば、指を動かしてもキャラは少ししか移動しません。値を変えて動かしてみれば、実感できると思います。
preMousePos
は、(x,y,z)座標を示す3次元ベクトルです。
1フレーム前にタップしていた座標を保存しておく変数です。詳しくは、後ほど解説します。
##Move()関数
###画面をタップした瞬間
if (Input.GetMouseButtonDown(0))
{
preMousePos = Input.mousePosition;
}
Input.GetMouseButtonDown(0)
は画面をタップした瞬間 を表しています。(公式ドキュメントはこちら)
タップした瞬間に以下の処理をします。
preMousePos = Input.mousePosition;
この Input.mousePosition
は、タップした位置の座標を示しています。(公式ドキュメントはこちら)
そのタップした座標を、先に宣言したpreMousePos
というVector3型の変数に格納しています。
###画面をタップして指を移動している間
if (Input.GetMouseButton(0))
{
Vector3 mousePosDiff = Input.mousePosition - preMousePos;
preMousePos = Input.mousePosition;
Vector3 newPos = this.gameObject.transform.position + new Vector3(mousePosDiff.x / Screen.width, 0, mousePosDiff.y / Screen.height) * speed;
this.transform.position = newPos;
}
Input.GetMouseButton(0)
はタップしている間ずっとtrueを返します。(公式ドキュメントはこちら)
つまり、タップしたまま指を動かしている間(=スワイプ?)ずっとif文以下が実行されるわけです。
if文内の処理についてです。
Vector3 mousePosDiff = Input.mousePosition - preMousePos;
mousePosDiff
は変数名の通り、1フレーム前の指の位置との差異のベクトルを表します。ベクトルの引き算です。
現在のフレームの座標:Input.mousePosition
1フレーム前の座標:preMousePos
とし、この2つを引き算することで、2つのフレームの差異のベクトル、つまり移動した「方向」をmousePosDiff
という変数に格納しています。
preMousePos = Input.mousePosition;
こちらで、前節の 画面をタップした瞬間 と同じ処理をします。
つまり、
方向(mousePosDiff)を検知 → preMousePosを更新
をフレームごとに絶え間なく繰り返していることになります。
Vector3 newPos = this.transform.position + new Vector3(mousePosDiff.x / Screen.width, 0, mousePosDiff.y / Screen.height) * speed;
この行で、現在のキャラの位置(this.transform.position
)に対して、
先ほど取得した指が移動した方向(mousePosDiff
)を用いて、移動先の座標newPos
を定義しています。
※座標は、Screen.widthとScreen.heightで割ることで画面に対応させてます。
※この例ではx座標とz座標を移動させていますが、自身のゲームに合わせてどの座標を動かすかは適宜変更してください。(mousePosDiff.x / Screen.width, 0, mousePosDiff.y / Screen.height)
の部分。
※speed の値を変更することで移動の大きさを変更できます。
this.transform.position = newPos;
定義したnewPos
を自分の今の座標this.transform.position
に代入することで、実際に移動をします。
以上の処理を、タップして指を動かしている間ずっと実行し続けることで、移動します。
つまり、1フレームごとに、
現在のタップしている座標Input.mousePosition
と
前のフレームでタップしていた座標preMousePos
から
移動した方向mousePosDiff
を検知して、
それを繰り返すことで、移動している ということになります。
もう少しわかりやすく書きたかったんですが、
文面だけだとかなりわかりづらくなってしまいました。。
とりあえず、サンプルコードを写せば動きます。。