この記事の動機
Unity勉強がてら、初めて2Dゲーム制作にチャレンジしていた時に、プレイヤーの1マス移動の実装が単純なものではなかったので忘れないように備忘録としてメモと共有。
(ゲーム開発者にとっては常識かもしれませんが。。)
※タイルマップやプレイヤーの配置などは割愛
※実際の動作は映像を添付できないので割愛
最初につまづいたこと
単純にプレイヤーが移動するためには、移動速度を持たせて入力があった方向にプレイヤーの場所を変えてあげれば良いのかと思い、プレイヤーに紐づくコードを以下のように書いてみた。
public class PlayerController : MonoBehaviour
{
// Playerの移動
// Playerから移動速度を取得できるように設定
[SerializeFiled] float moveSpeed;
// 外部で入力内容を保持する用の変数
Vector2 input;
void Update()
{
// キーボードの入力情報をinputに格納
input.x = Input.GetAxisRaw("Horizontal"); // 横方向
input.y = Input.GetAxisRaw("Vertical"); // 縦方向
// 入力があったら(inputに値が入っていたら)
if (input != Vector2.zero)
{
// 入力内容をもとにプレイヤーを移動させる
transform.position += (Vector3)input;
}
}
}
Unityに戻って、プレイヤーの移動速度を"5"に設定して実行してみると。。
プレイヤーがビュンビュン移動するではありませんか!(映像で見せれないのが悔しい)
原因はこのコードだと、入力がある限りどこまでも移動してしまうからです。
どのように1マス移動を実装させるか
どのように1マス移動を実装するかですが以下のような考え方で実装します。
・入力があった分を一旦目的地として保持し、その目的地に徐々に近づけるような処理をかく(すぐに移動させない)
・入力中(移動中)は入力を受け付けないようにする
入力されている間、プレイヤー徐々に近づけるように動かすにはコルーチンを使います。
bool isMoving; // 移動中判定
void Update()
{
// 移動中だと入力を受け付けない
if (!isMoving)
{
// キーボードの入力情報をinputに格納
input.x = Input.GetAxisRaw("Horizontal"); // 横方向
input.y = Input.GetAxisRaw("Vertical"); // 縦方向
// 入力があった時
if (input != Vector2.zero)
{
// 入力があった分を目的地にする
Vector2 targetPos = transform.position;
targetPos += input;
StartCoroutine(Move(targetPos));
}
}
}
// コルーチンを使って徐々に目的地に近づける
IEnumerator Move(Vector3 targetPos)
{
// 移動中は入力を受け付けない
isMoving = true;
// targetposとの差があるなら繰り返す:目的地に辿り着くまで繰り返す
while ((targetPos - transform.position).sqrMagnitude > Mathf.Epsilon)
{
// targetPosに近づける
transform.position = Vector3.MoveTowards(transform.position, targetPos, moveSpeed * Time.deltaTime);
// 徐々に近づけるため
yield return null;
}
// 移動処理が完了したら目的地に到着させる
transform.position = targetPos;
isMoving = false;
}
Vector3のMoveTowardsを使えば、現在地を目的地に向かって任意のスピードで移動させることが出来ます。
これを徐々に近づけさせながら繰り返したいのでコルーチンの中に書きます。
MoveTowardsには
引数1:現在地
引数2:目的地
引数3:速さ
を渡してあげると移動先を返してくれます。
さらに、コルーチンの最初で移動中フラグを立てて、移動処理中に入力を受け付けないようにします。
コルーチンの最後(移動完了時)にfalseにしてあげることで、次の入力を受け付けるようになります。
上記のコードを動かしてみると、見事1マス移動を実現することが出来ました!
この技術はゲーム制作において必須スキルになっているのかもと感じました。
ゲームを作るうえでテンプレのように覚えていて損はないですね!