見出し画像

【Unity 初心者向け】オブジェクトの移動⑤ | Rigidbodyに力を加えて動かす ― AddForce編

これまで、Unityでオブジェクトを動かす方法をいくつか確認してきました。

前回は、Rigidbody2D の linearVelocity を使って、オブジェクトの速度を直接変更する方法を確認しました。

今回は、速度を直接決めるのではなく、オブジェクトに力を加えて動かす方法を確認します。

使用するのは、Rigidbody2D の AddForce です。

rb.AddForce(Vector2.right * power);

AddForce を使うと、

  • オブジェクトを押す

  • ジャンプさせる

  • 爆発で吹き飛ばす

  • ノックバックさせる

といった、物理演算らしい動きを作ることができます。

そして今回は、この「オブジェクトの移動」シリーズの最終回です。
最後には、これまで学習した移動方法を比較しながら、どの移動方法を使えばいいのか?についても整理していきます。



1.AddForceとは

1-1.AddForceの使用例

AddForce は、Rigidbody に力を加えるための命令です。
2Dの場合は、Rigidbody2D に対して使用します。

例えば、次のコードを見てみましょう。

rb.AddForce(Vector2.right * power);

このコードでは、オブジェクトに右方向の力を加えています。
それぞれの部分を確認してみましょう。

rb は、操作する Rigidbody2D 型の変数です。

rb

AddForce() が、Rigidbody2Dに力を加える命令です。

AddForce()

Vector2.right は右方向を表します。

Vector2.right

そして、power が加える力の大きさです。

Vector2.right * power

つまり、「rb に対して、右方向へ power 分の力を加える」という意味になります。


1-2.linearVelocityとの違い

前回使用した linearVelocity と、今回の AddForce は、どちらも Rigidbody2D を動かすことができます。

ただし、考え方が大きく異なります。

前回の linearVelocity では、例えば次のように書きました。

rb.linearVelocity = new Vector2(
    5f,
    rb.linearVelocity.y
);

これは「横方向の速度を5にする」という命令です。

つまり、速度そのものを直接指定しています。
一方、今回の AddForce は、

rb.AddForce(Vector2.right * power);

のように書きます。
こちらは「右方向へ力を加える」という命令です。
速度を直接指定しているわけではありません。
力を加えた結果として、オブジェクトの速度が変化します。


2.AddForceを使って動かしてみよう

2-1.スクリプトファイルを作成

実際に、オブジェクトへ右方向の力を加えてみましょう。

スクリプトファイル:AddForceMove を作って、次のコードを入力します。

public class AddForceMove : MonoBehaviour
{
    public Rigidbody2D rb;      // Rigidbody2Dコンポーネントへの参照
    public float power = 5f;    // 力の大きさ

    void FixedUpdate()
    {
        // 水平方向の入力を取得
        rb.AddForce(Vector2.right * power);
    }
}

このスクリプトでは、

rb.AddForce(Vector2.right * power);

を繰り返し実行しています。
そのため、オブジェクトには右方向の力が加わり続けます。

変数:rb にRigidbody2Dコンポーネントをセットして実行すると、最初はゆっくり動き始め、その後だんだん速度が上がっていきます。
ここが、linearVelocity との大きな違いです。

AddForce は、移動速度を設定しているのではなく、力を加えているという点を覚えておきましょう。


2-2.なぜFixedUpdateを使うの?

今回のコードでは、

void FixedUpdate()
{
    rb.AddForce(Vector2.right * power);
}

としています。
これまでよく使ってきた Update ではなく、FixedUpdate を使っています。
FixedUpdate は、Rigidbody などの物理演算を扱う処理でよく使用する関数です。

Update は画面の描画に合わせて実行されるため、実行回数がフレームレート(1フレームにかかる時間)によって変わります。

一方、FixedUpdate は一定の間隔で実行されます。
そのため、Rigidbody へ継続的に力を加えるような処理では、

FixedUpdate()

を使うと扱いやすくなります。
今回のように、毎回Rigidbodyへ力を加える処理は FixedUpdate に書いておくとよいでしょう。


2-3.力を加え続けると速度が変わる

FixedUpdate の中で、

rb.AddForce(Vector2.right * power);

を実行すると、一定間隔で力が加わり続けます。
処理のイメージは次のようになります。

右方向へ力を加える
        ↓
少し速度が上がる
        ↓
また右方向へ力を加える
        ↓
さらに速度が上がる
        ↓
また力を加える
        ↓
さらに速度が変化する

このように、AddForce は力を加えるたびにRigidbodyの速度へ影響を与えます。

例えば車のアクセルを想像すると分かりやすいでしょう。
アクセルを踏んだからといって、いきなり最高速度になるわけではありません。
力が加わることで、少しずつ速度が変化します。
AddForce も、それに近い考え方です。


2-4.Massによって動き方が変わる

Rigidbody2Dには、Mass という項目があります。
Mass はオブジェクトの質量を表します。

同じ AddForce を使っていても、Mass の値によって動き方が変わります。

例えば、

rb.AddForce(Vector2.right * power);

という同じ力を加えた場合でも、Mass が小さいオブジェクトは動きやすくなります。
一方、Mass が大きいオブジェクトは動きにくくなります。

つまり、同じ力なら、軽い物体ほど速度が変化しやすく、重い物体ほど速度が変化しにくいということです。

これは現実世界でも同じです。
軽いボールと重い箱を同じ力で押した場合、軽いボールのほうが簡単に動きます。

AddForce を使うと、こうした Rigidbody の物理設定も動きに影響します。


3.FoeceMode について

AddForce では、力の加え方を指定することもできます。

そのときに使用するのが、

ForceMode2D

です。
例えば、次のように書くことができます。

rb.AddForce(
    Vector2.right * power,
    ForceMode2D.Force
);

AddForce の2つ目の引数として、

ForceMode2D.Force

を指定しています。
2Dでよく使うのは、次の2つです。

  • ForceMode2D.Force

  • ForceMode2D.Impulse

ForceMode2D.Impulse

です。
この2つは、力の加え方が異なります。


3-1.Force ― 力を加え続ける

まずは、

ForceMode2D.Force

Force は、継続的に力を加えるような動きに向いています。
イメージとしては、「物体をグーッと押し続ける」という感じです。

例えば、

  • 車を加速させる

  • 宇宙船を推進させる

  • 風で物体を押す

  • キャラクターを徐々に加速させる

といった動きに使えます。

なお、

rb.AddForce(Vector2.right * power);

のように、2つ目の ForceMode2D を省略した場合も、通常は Force として力が加えられます。

そのため、最初に使った、

rb.AddForce(Vector2.right * power);

も Force を使用していると考えてよいでしょう。


3-2.Impulse ― 一瞬だけ強い力を加える

次は、

ForceMode2D.Impulse

Impulse は、力を一瞬だけ加えたいときに使います。
イメージとしては「ドンッ!」と一度だけ強く押すような感じです。

例えば、

  • ジャンプする

  • ボールを蹴る

  • 爆発で吹き飛ばす

  • 敵から攻撃を受けてノックバックする

といった動きに向いています。


3-3.AddForceでジャンプさせてみよう

Impulse の分かりやすい使用例が、ジャンプです。

次のスクリプトを作成してみましょう。

using UnityEngine;

public class Jump : MonoBehaviour
{
    public Rigidbody2D rb;
    public float jumpPower = 5f;

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            rb.AddForce(
                Vector2.up * jumpPower,
                ForceMode2D.Impulse
            );
        }
    }
}

スペースキーを押したときに、

rb.AddForce(
    Vector2.up * jumpPower,
    ForceMode2D.Impulse
);

を実行しています。まず、

Vector2.up

は上方向を表します。
そのため、

Vector2.up * jumpPower

で、上方向へ加える力の大きさを作っています。

さらに、2つ目の引数として、

ForceMode2D.Impulse

Impulse はオブジェクトへ瞬間的な衝撃を与えるような力の加え方です。

ジャンプでは、上方向へ長時間力を加え続けるというよりも、キーを押した瞬間に「ポンッ」と上方向へ勢いを与える、という動きにしたいため、Impulse が分かりやすい使い方になります。

ここで、「Input.GetKeyDown() はキーを押した瞬間に1回だけ実行されるのだから、Force を使っても同じなのでは?」と思うかもしれません。

しかし、

何回AddForceを呼び出すか?と、その1回の力をどのように物理演算へ反映するか?は別の話です。

例えば、

rb.AddForce(
    Vector2.up * jumpPower,
    ForceMode2D.Force
);

とした場合も、GetKeyDown() を使っていれば AddForce 自体は1回しか実行されません。
ただし Force は、継続的に力を加える用途に向いたモードで、1回だけ実行した場合は「一瞬だけ少し押す」ような力になります。

一方、

rb.AddForce(
    Vector2.up * jumpPower,
    ForceMode2D.Impulse
);

では、その1回の呼び出しで「一瞬にまとまった力を与える」ような動きになります。

ジャンプのように、

  • キーを押した瞬間に

  • 上方向へ

  • はっきりとした勢いを与えたい

という処理では、ForceMode2D.Impulse が扱いやすいでしょう。

jumpPower の値が同じ場合、Force と Impulse では動き方が同じにはなりません。


4.どの移動方法を使えばいい?

ここまでの「Unity オブジェクトの移動」シリーズでは、いくつかの移動方法を確認してきました。

最後に、それぞれの違いを整理してみましょう。

transform.position

transform.position += new Vector3(
    speed * Time.deltaTime,
    0,
    0
);

transform.position は、オブジェクトの座標そのものを変更する方法です。Unityでオブジェクトが動く基本であり、「位置が変わるとオブジェクトが動く」という考え方を理解するのに適しています。

単純な移動や、指定した場所へ移動させたい場合にも使いやすい方法です。


Transform.Translate

transform.Translate(
    Vector3.right * speed * Time.deltaTime
);

Translate は「現在位置から、この方向へ移動する」という書き方がしやすい方法です。

右へ進む、前へ進む、といった方向を意識した移動をシンプルに書くことができます。


linearVelocity

rb.linearVelocity = new Vector2(
    speed,
    rb.linearVelocity.y
);

linearVelocity は、Rigidbody2D の速度を直接変更します。

そのため「この速度で動いてほしい」という場合に使いやすい方法です。
一定速度で移動するキャラクターなどにも向いています。


AddForce

rb.AddForce(
    Vector2.right * power
);

AddForce は、Rigidbody2Dへ力を加えます。
速度を直接決めるのではなく、力を加えた結果として速度が変化します。

そのため、

  • 加速

  • ジャンプ

  • ノックバック

  • 吹き飛ばし

など、物理演算を活かした動きを作りやすい方法です。

ここまでいくつかの移動方法を学習してきましたが「どの方法が一番優れている」というわけではありません。

例えば、キャラクターを一定速度で左右へ動かしたいのであれば、linearVelocity が扱いやすいことがあります。

ジャンプさせたいのであれば、

AddForce

と、

ForceMode2D.Impulse

の組み合わせが使いやすいでしょう。

また、物理演算が必要ない単純なオブジェクト移動なら、

transform.position

や、

Transform.Translate

のほうがシンプルに作れる場合もあります。
大切なのは「どんな動きを作りたいのか」を考えて、その目的に合った方法を選ぶことです。

Unityでは、同じように見える動きでも、実装方法はいくつもあります。

ゲームを作りながら「今回はどの方法が使いやすいかな?」と考えられるようになると、プログラムの組み立て方も少しずつ分かってきます。


5.今回のまとめ

今回は、Rigidbody2Dに力を加えてオブジェクトを動かす AddForce について確認しました。


こちらはUnity初心者向けの記事をテーマ別にまとめています。
▼ Unity初心者向け記事まとめはこちら


こちらのマガジン「ミニゲーム作成講座 全8回セット」でもシーンの切り替えなどを活用して、初心者でも知識ゼロから作れるミニゲーム作成講座を紹介しています。

さらにステップアップの「スマホで遊ぶジャンプゲーム 8回セット」のマガジンもぜひご活用ください。


ファイブボックスでは、スクラッチやUnityの個別指導のオンラインレッスンを行っています。
ご興味のある方は当サイト、オンラインレッスンから、無料体験授業へお問い合わせ下さい。

いいなと思ったら応援しよう!

ファイブボックス よろしければ応援お願いします! いただいたチップはクリエイターとしての活動費に使わせていただきます!