【Unity基礎】Addforceを使ってRigidbodyオブジェクトを動かす方法

Unityで物理演算を効かせたRigidbodyなオブジェクトを、「Addforce(アドフォース)」を使って動かす方法を説明します。
Addforceは、Rigidbodyコンポーネントをアタッチしたオブジェクトを動かす最も一般的な方法なので、しっかり理解しておきましょう。

この記事の環境
Unity Version 2018.2.17f1 Personal
OS Windows10

Addforceとは

「Addforce」はRigidbodyクラスの関数(メソッド)で、オブジェクトに力を加えて動かすイメージです。
車がアクセルを踏んで加速したり、ボールを蹴飛ばしたり、といった動きが自然な感じで行なえます。

Addforceはどういうときに使う?

物理演算を使用して現実に比較的近い動きをさせたい場面で、オブジェクトを動かす時に使う一番無難な方法です。
positionやVelocityを使う方法は、あまり推奨されていないようです。

特に他のオブジェクトに接触する場合にpositionを使うと、正確な物理演算が出来ません。
動きが速いと他のオブジェクトをすり抜ける場合があります。

推奨されてないと言っても、positionやVelocityを使ってはいけないわけではありません。
現実的で自然な動きが不要なときや、むしろ不自然な動きをさせたい時とかは積極的に使っていいと思います。

AddForceの基本的な使い方

AddForceを使うときのスクリプトの書き方や、AddForceを実装したスクリプト例を紹介します。

AddForceのスクリプトの書き方

AddForceのスクリプトの書き方は次の2種類あります。

AddForce (Vector3 force, ForceMode mode= ForceMode.Force);

AddForce (float x, float y, float z, ForceMode mode= ForceMode.Force);

力のベクトルを与えるのにVector3を突っ込むか、x, y, zそれぞれの方向を直接与えるかの違いです。

ForceModeは省略可能で、省略した場合はデフォルトで「Force」と言うモードになります。

Addforce実装スクリプト例

シーンビューに床としてPlaneと、動かすオブジェクトとしてCubeを配置。
CubeにRigidbodyコンポーネントをアタッチ。
スクリプトを新規作成し、class内に下記をコピペ。
ゲームを再生し、カーソルキー上でcubeが動きます。

// Rigidbodyコンポーネントを入れる変数"rb"を宣言する。
public Rigidbody rb;

void Start() {
    // Rigidbodyコンポーネントを取得する
    rb = GetComponent<Rigidbody>();
}

void FixedUpdate() {
    //  Upキーで前に進む
    if (Input.GetKey("up")) {
        rb.AddForce(transform.forward * 10.0f, ForceMode.Force);
    }
}

このスクリプト例では、AddForceに与える引数として「transform.forward * 10.0f」としているため、Cubeから見て前方向(Z軸方向)に力がくわえられます。
ForceModeに「Force」を指定していますが、これは省略することができます。

AddforceのForceMode(フォースモード)による挙動の違い

AddForceには4つのFoceModeがあります。
各ForceModeの説明と、ForceModeごとの挙動の違いを説明します。

ForceMode(フォースモード)の種類

ForceModeには次の4種類あります。

ForceModeの種類 力を加え方 オブジェクトの質量
Force 継続的に力を加える 質量を考慮
Acceleration 継続的に力を加える 質量を無視
Impulse 瞬間的に力を加える 質量を考慮
VelocityChange 瞬間的に力を加える 質量を無視

AddForceでForceModeの指定を省略した場合「Force」を指定したのと同じになります。

「Force」継続的に力を加える(質量を考慮)

オブジェクトに継続的に力を加えます。
力を加え続けると、オブジェクトはどんどん加速していきます。

車がアクセルを踏み込んで加速するような動き

公式リファレンス 「Force」の解説はこちら

ForceMode-Force - Unity スクリプトリファレンス
質量を使用して、リジッドボディへ継続的な力を加えます。

「Acceleration」継続的に力を加える(質量を無視)

「Acceleration」は「Force」と似ていますが、オブジェクトの質量に影響されないという特徴を持っています。
重いオブジェクトと軽いオブジェクトをAddForceによって同じように動かしたい場合などに使用できます。

公式リファレンス 「Acceleration」の解説はこちら

ForceMode-Acceleration - Unity スクリプトリファレンス
その質量を無視して、リジッドボディへ継続的な加速を追加します。

「Impulse」瞬間的に力を加える(質量を考慮)

「Impulse」はボールを蹴飛ばしたときのように、オブジェクトへ瞬間的に力を与えて動かす方法です。

上の画像は、上向きに1度だけImpulseのAddForceを与えた例です。
ボールが蹴飛ばされたように跳ね上がっているのが分かりますね。
次のスクリプトで動かしています。

public Rigidbody rb; void Start() {         rb = GetComponent<Rigidbody>();         rb.AddForce(transform.up * 10.0f, ForceMode.Impulse); }

公式リファレンス 「Impulse」の解説はこちら

ForceMode-Impulse - Unity スクリプトリファレンス
その質量を使用し、リジッドボディにインスタントフォースインパルスを追加します。

「VelocityChange」瞬間的に力を加える(質量を無視)

「VelocityChange」はImpulseと似ていますが、オブジェクトの質量に影響されないという特徴があります。

公式リファレンス 「VelocityChange」の解説はこちら

ForceMode-VelocityChange - Unity スクリプトリファレンス
質量を無視して、リジッドボディにインスタント速度変化を追加します。

ForceMode「force」と「impulse」の挙動の違い

forceとimpulseの挙動の違いを見てみましょう。
上の画像は左が継続的に力を加える「Force」、右が瞬間的に力を加える「Impulse」でキューブを動かしています。

ForceはずっとFixedUpdate関数で力を加え続けていて、ImpulseはStart関すで1度だけ力を加えています。
スクリプトは下記です。

// Forceでキューブを動かすスクリプト
public Rigidbody rb;

void Start() {
    // Rigidbodyコンポーネントを取得する
    rb = GetComponent<Rigidbody>();
}

void FixedUpdate() {
    rb.AddForce(0, 15.0f, 0, ForceMode.Force);
}
// Impulseでキューブを動かすスクリプト
void Start() {
    GetComponent<Rigidbody>().AddForce(0, 5.0f, 0, ForceMode.Impulse);
}

Forceはゆっくり浮き上がったその後加速していきますが、Impulseは飛び跳ねるように浮き上がっています。

ForceMode「Force」と「Acceleration」の挙動の違い

「Force」と「Acceleration」は質量を考慮するかしないかの違いがあります。
上の画像はキューブの質量を変えて、「Force」と「Acceleration」でそれぞれ動かした例です。

スクリプトは、下記のように与える力は同じでForceModeを変えています。

rb.AddForce(0, 20.0f, 0, ForceMode.Force);
rb.AddForce(0, 20.0f, 0, ForceMode.Acceleration);

Forceは質量を考慮するので、mass = 2のキューブはゆっくり浮き上がるのに対し、Accelerationは質量に影響されないので、質量の違うキューブが同じように浮き上がっています。

ForceMode「Impulse」と「VelocityChange」の違い

「Impulse」と「VelocityChange」の違いは、「Force」と「Acceleration」の違いと同じく「質量を考慮するかしないか」です。
なので、上の画像の例のようにAccelerationは質量の違うキューブも同じように飛び跳ねています。

ちなみに上の例は次のスクリプトで動かしています。

rb.AddForce(0, 5.0f, 0, ForceMode.Impulse);
rb.AddForce(0, 5.0f, 0, ForceMode.VelocityChange);

コメント