【Unity】2Dゲームでキャラクターを移動させる方法を解説!
こんにちは。あっきーです。
早稲田大学を退学して4年間アメリカ留学に行く予定の人間で、ゲーム制作をしています。
2Dゲームを作りたい人
Unityで2Dゲームを作ろうと思っているんだけど、キャラクターの移動ってどうやるんだろう?マリオみたいな動きを実装したいなぁ
今回はこれについて詳しく説明していきます。
Unityでゲーム制作をしたい人は多くいるかと思いますし、一番やりやすいのは2Dゲームかなと思います。
マリオみたいな2Dアクションは作ってみたくなるかもしれません。そこで、今回はキャラクターの移動について詳しく解説していきます。
まずは2Dテンプレートを作成しよう
Unityで新しくゲームを作る場合、プロジェクトを作る必要があります。
3Dでもz軸を使わなければ2Dゲームを作ることが可能ですが、今回は初めから2Dテンプレートを使っていきましょう。
新しくプロジェクトを作る方法は【ゲーム制作】初心者にも分かりやすくUnityの使い方を解説!を見てください。
2Dのキャラクターや地面を設定しよう
また、2Dのキャラクターなどを作りたいのですが、これはいろいろと面倒なのでAsset Storeから画像などをお借りしましょう。
今回は以下のようなものをダウンロードします。
ちなみに、Asset Storeで素材をダウンロードする方法は別の記事で紹介していますので参考に、どうぞ。
また、移動だけの説明であれば、別に地面とか当たり判定とかつけなくてもいいのですが、今後ゲームを作るのであれば避けては通れないポイントなので、地面の作り方と当たり判定の付け方をマスターしておきましょう。
ここの話をすると長くなってしまうので、別の記事で紹介します。
キャラクターを移動
キャラクターの移動方法は主に2つあります。
- rigidbodyを操作する(物理演算)
- transformを操作する
多くの場合は上のrigidbodyを利用した移動を使っていますし、僕もこちらをオススメしています。
では、それぞれ使っていきましょう。
rigidbodyを利用した移動方法
rigidbodyの操作するというのは物理演算をするということです。高校や大学で物理を学んでいた人ならよくわかりますね。運動方程式「ma = F」を利用したりして、落下運動とかを考えるやつです。
ものすごくかみ砕けば「速さ×時間 = 距離」の関係をうまく利用するというのが物理演算です。
ここでは2つの方法について説明していきます。
- velocityを直接操作
- AddForceによる操作
velocity(速度)を直接書き換える
まずは、ものすごく単純な方法です。
キャラクターのインスペクター上にある”Rigidbody2D”を見てみると、InfoというところにVelocityという項目がありますね。
これは速度を表します。
このVelocityの値を書き換えて動かすという感じです。
ということで、実際にVelocityを書き換えて動かすスクリプト(名前は”Player”としておきます)を書いてみましょう。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
public float speed;
private Rigidbody2D rb;
void Start()
{
rb = GetComponent();
}
// 物理演算をしたい場合はFixedUpdateを使うのが一般的
void FixedUpdate()
{
float horizontalKey = Input.GetAxis("Horizontal");
//右入力で左向きに動く
if(horizontalKey > 0)
{
rb.velocity = new Vector2(speed, rb.velocity.y);
}
//左入力で左向きに動く
else if(horizontalKey < 0)
{
rb.velocity = new Vector2(-speed, rb.velocity.y);
}
//ボタンを話すと止まる
else
{
rb.velocity = Vector2.zero;
}
}
}
このスクリプトをキャラクターのオブジェクトにつけて、Speedという項目に適当な数字を入れましょう。
その数字が移動速度になります。
実際に動かしてみましょう。
しっかり動いているのが分かります。
public float speed;
これは、移動速度を入れる変数です。publicとすることでインスペクター上で数値を変えることができるので手間が省けます。
void FixedUpdate()
UnityではよくUpdateを使いますが、それに似たものにFixedUpdateというメソッドがあります。
FixedUpdateはざっくり言うと物理演算をする際に使うメソッドです。今回はまさにこれですね。
この説明をすると長くなるので、別の記事でお話するので、どうぞ。
float horizontalKey = Input.GetAxis("Horizontal");
horizontalKeyはキー入力の値を保持する変数です。
Input.GetAxis("名前")は「名前」というボタンを押したときの値のことです。
今回の場合、右ボタンを押している間は1を、左ボタンを押している間は-1を、押してない場合は0となります。(厳密にはちょっと違いますがざっくりこんな感じです。)
ボタン入力に関してはいろいろ奥が深いので別の記事で詳しく説明します。
rb.velocity = new Vector2(speed, rb.velocity.y);
これは速度を直接書き換えるコードです。
基本的に、「"A"というコンポーネントの"b"の情報得る」場合"A.b"とすればOKです。
今回の場合、「"rb(Rigidbody2D)"の"velocity"」なのでrb.velocityとなります。
velocityはx方向とy方向の両方を設定するベクトルなので、new Vector2(x, y)として、x,yに好きな速度を入れます。
xは最初に宣言した変数speedで、yはキャラクターの現在のy速度ということでrb.velocity.yとしています。
AddForceを利用した移動
続いては、Add.Forceを利用した移動です。これがよく使われる移動方法なのでしっかり理解しましょう。
先ほどのPlayerスクリプトを以下のように書き換えましょう。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
private Rigidbody2D rb;
void Start()
{
rb = GetComponent();
}
// 物理演算をしたい場合はFixedUpdateを使うのが一般的
void FixedUpdate()
{
float horizontalKey = Input.GetAxis("Horizontal");
//右入力で右向きに動く
if(horizontalKey > 0)
{
rb.AddForce(transform.right * 10.0f);
}
//左入力で左向きに動く
else if(horizontalKey < 0)
{
rb.AddForce(-transform.right * 10.0f);
}
//ボタンを話すと止まる
else
{
rb.velocity = Vector2.zero;
}
}
}
これで実行してみます。
先ほどとはまた違った動きですね。だんだん速くなっているのがわかりますね。
ここでは直接速度をいじっていませんが、代わりに力を用いています。
「右入力をしている間は右向きに力を加え続け、逆も然り」というようなコードです。
力を加えると速度が変化する(厳密には違いますが)というのを利用して間接的に速度を変えています。
AddForceの使い方
rb.AddForce(transform.right * 10.0f);
AddForceはこのように使っていきます。
Rigidbody.AddForce(ベクトル, 力の加え方)とすることで「"ベクトル"の力を"力の加え方"で加える」ということになります。
今回の場合、「"ベクトル" = transform.right * 10.0f」です。
transformは(1, 0)のベクトルを表します(3次元だと(1, 0, 0))。つまり、右向きということです。
10.0fを掛け算しているのは、単純に加える力を大きくしているだけです。そうしないと、力が弱くて全然動きません。
今回の場合は、"ベクトル"のところを「new Vector2(10.0f, 0)」としてもOKです。
今回の例では"力の加え方"を宣言していませんが、力の加え方には2種類あります。
-
力を加え続ける → ForceMode.Force(これがデフォルトで設定される)
瞬間的に力を加える → ForceMode.Impulse
今回の場合は何も書いていませんが、ForceMode.Forceが適用されています。
もし、瞬間的に力を加えたい場合は
rb.AddForce(tranform.right * 10.0f, ForceMode.Impulse);
のように書けばOKです。
AddForceをまとめると
AddForce("ベクトル", "力の入れ方")
で宣言- "ベクトル"という力を"力の入れ方"の通りに加える
ForceMode.Force
で力を加え続けるForceMode.Impulse
で瞬間的に力を加える
AddForceを使うとよりしなやかな動きを再現できるので、ぜひマスターしておきましょう。
Transformを利用した移動方法
Rigidbodyの操作以外では、TransformのPositionを直接書き換える方法もあります。
速さではなく、位置そのものを指定しちゃうというわけです。
実際にやってみましょう。先ほどのPlayerスクリプトを以下のように書き換えます。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
public float speed;
private Rigidbody2D rb;
private float timer;
void Start()
{
rb = GetComponent();
}
//Transformの操作はUpdateの方が良い
void Update()
{
float horizontalKey = Input.GetAxis("Horizontal");
//右入力で右向きに動く
if(horizontalKey > 0)
{
transform.position += new Vector3(speed, 0, 0);
}
//左入力で左向きに動く
else if(horizontalKey < 0)
{
transform.position += new Vector3(-speed, 0, 0);
}
}
「キャラクターの位置を少しずつずらして動かす」というコードになってます。
実際に動かしてみましょう。
一定速度で動いているように見えますね。
Transformを使うのはあまりおすすめしません
一見うまくいっているようですが、あまりオススメはできません。
もし移動の幅が大きくなると、瞬間移動したようにキャラクターが動いてしまいます。そうなると、障害物や敵をすり抜ける現象などが起きてしまいます。
実際は極端にしない限り通り抜けはないと思うのですが、挙動がおかしくなったりするので、rigidbodyを使った物理演算をすることをオススメします。
コードの解説
今回のコードは先ほどやったvelocityを操作した場合と全く同じです。
transform.position += new Vector3(speed, 0, 0);
「transformのposition」を操作したいのでtransform.position
とまずは書きます。
(transformはGetcomponentで取得をする必要はありません。)
「現在地からx方向へ一定間隔で進む」としたいのでこのtransform.position
にspeed
を加えていくという具合です。
実際にキャラクター移動を作ってみよう
いかがでしたか?
だんだん速くなって(遅くなって)、途中で一定になる移動。
ふわっとした動きや、ずっしりした動き。。。
などなど、実際に自分にあった移動を作ってみてください。
まとめ
移動全般について
- 移動にはrigidbody操作とtransform操作の2種類ある
- 「当たり判定のある移動」はrigidbodyがオススメ
- rigidbodyの移動には主にvelocityを直接操作とAddForceを使った力による移動がある
- AddForceを使う方がオススメ(より現実っぽい動きができる)
コードについて
- AddForce(ベクトル, 力の加え方)→「ベクトル」という力を「力の加え方」の通りに加える
それでは、また。
スポンサードサーチ
人気記事英語学習用SNSをLaravelで作ってみた【システム解説あり】