こんにちは、ともくんのゲーム作り部屋にようこそ!
このページでは、
「オブジェクトを徐々に加速させるように移動したい!」
「Rigidbodyを使わずに加速させる方法が知りたい!」
というお悩みの方に向けた内容となっています。
Unityでは、オブジェクトを徐々に加速させるなどのような物理的挙動を作る場合、基本的にはRigidbodyコンポーネントを使うことで、簡単に実装することができます。
ただし、ゲーム内の状況によっては、Rigidbodyコンポーネントを使いたくないという場合もあると思います。
その場合は、Lerpメソッドなどでオブジェクトの移動処理を作り、引数で指定する補間割合の値を累乗してあげることで、加速しながら移動させることができるようになります。
そこで、このページでは、Unityでオブジェクトに対して加速させる動きを作る際に、Rigidbodyコンポーネントを使って実装する方法と、Rigidbodyを使わずにLerpメソッドで実装する方法をそれぞれまとめていきます。
Rigidbodyで徐々に加速させる動きを作る方法
まずは、Rigidbodyを使ってオブジェクトを徐々に加速させる動きを作っていきます。
ここでは2Dゲームで、以下の赤色の四角いオブジェクトが黒色の丸いオブジェクトの位置まで徐々に加速して移動する処理を作ってみます。

オブジェクトにRigidbodyコンポーネントを紐づける
まずは、四角いオブジェクトにRigidbodyコンポーネントを紐づけておきます。
オブジェクトを選択した状態で、インスペクターウィンドウのAddComponentから「Rigidbody 2D」を選択します。

Rigidbody2Dを紐づけたら、今回はオブジェクトを移動させるだけで重力を設定する必要が無いため、「Gravity Scale」の値を0にしておきます。

なお、3Dゲームの場合はコンポーネントで「Rigidbody」を選択して、「Use Gravity」のチェックを外しておきます。

AddForceで継続的に力を与えて加速させる
次に、以下のスクリプトを四角いオブジェクトに紐づけておきます。
using UnityEngine;
public class SquareController : MonoBehaviour
{
[SerializeField] Transform circle; // 丸いオブジェクトを取得する変数
Rigidbody2D rb;
void Start()
{
rb = GetComponent<Rigidbody2D>(); // Rigidbodyコンポーネントを取得する処理
}
void FixedUpdate()
{
rb.AddForce(Vector3.Normalize(circle.position - this.transform.position) * 3.0f); // 目標となる地点へ力を加える処理
}
}
15行目でRigidbodyコンポーネントが持つAddForceメソッドを使って、オブジェクトに力を加える処理を行っています。
AddForceメソッドの引数で力を加える方向を指定していて、丸いオブジェクトの座標位置から四角いオブジェクトの座標位置を引いて、それをNormalizeメソッドで正規化した(長さを1にした)ベクトルに変換して指定しています。
また、ここでは継続的に力を加えたいので、FixedUpdate内でこのAddForceメソッドを記述しています。
これでゲームを実行してみると、

丸いオブジェクトに向かって、オブジェクトが少しずつ加速する動きを作ることができました。
なお、Rigidbodyを使う場合、オブジェクトが物理挙動になるため、指定したオブジェクトを通過して停止し、その後反対向きに戻ってくる動きが行われます。
Rigidbody無しで徐々に加速させる動きを作る方法
次に、Rigidbodyコンポーネントを使わずにオブジェクトを徐々に加速させる動きを作っていきます。
Lerpメソッドでオブジェクトの移動処理を作る
Rigidbodyを使わない場合は、冒頭でも解説した通りで、Lerpメソッドを使ってオブジェクトの移動処理を作っていくのが一般的です。
このLerpメソッドは、指定した2つの座標位置の間を線形補間してくれるメソッドで、以下のように記述することで、tで指定した補間割合におけるVector3の位置を返してくれます。
Vector3.Lerp(a, b, t);a:始点となる位置(Vector3型)
b:終点となる位置(Vector3型)
t:直線上で補間する0から1までの位置(float型)
実際に、Rigidbodyコンポーネントを付けていない四角いオブジェクトに、以下のようなスクリプトを紐づけてみます。
using UnityEngine;
public class SquareController : MonoBehaviour
{
[SerializeField] Transform circle; // 丸いオブジェクトを取得する変数
Vector3 startPos;
void Start()
{
startPos = transform.position; // スタート地点を取得する処理
}
void Update()
{
transform.position = Vector3.Lerp(startPos, circle.position, Time.time / 10.0f); // 線形補間で10秒かけて移動する処理
}
}15行目でオブジェクトの座標位置をLerpメソッドの値で指定していて、始点を自身のスタート地点の座標、終点を丸いオブジェクトの座標、補間する位置を計測時間(Time.time)で変動するように記述しています。
ちなみに、Lerpメソッドの第三引数である補間位置の割合は、1になると終点位置に到達することになります。
そして、ここでは計測時間の値を10で割って指定しているので、10秒間経過すると1になり、オブジェクトが到達するように移動処理が行われます。

なお現時点では、上記のように等速で動いているのが分かります。
引数で指定する補間割合を累乗して加速させる
先ほどの等速の動きを、今度は徐々に加速させるような動きに変化させてみます。
加速させる場合は、Lerpメソッドの引数で指定した補間割合を累乗(二乗や三乗など)することで実装できます。
以下のようにスクリプトを修正してみます。
using UnityEngine;
public class SquareController : MonoBehaviour
{
[SerializeField] Transform circle;
Vector3 startPos;
void Start()
{
startPos = transform.position;
}
void Update()
{
transform.position = Vector3.Lerp(startPos, circle.position, Mathf.Pow(Time.time, 2f) / 10.0f); // 計測時間を二乗して補間割合を指定
}
}15行目でLerpメソッドの第三引数で使っていた計測時間の値を、Powメソッドで二乗させる処理を行っています。
このPowメソッドは、以下のように記述することで、元の数を指定した回数分掛け合わせたfloat型の値を取得することができます。
Mathf.Pow(base, exponent)base:掛け合わせる元の数(float型)
exponent:掛ける回数・指数(float型)
実際にゲームを実行してみると、

上記のように、オブジェクトが加速して動くようになっているのが分かります。
なお、掛ける回数となる指数の値が増えれば増えるほど、初めの速度が遅くなる代わりに、後半での加速が速くなるという動きを作ることができます。
参考に、以下は計測時間の値を四乗に変更した場合です。

先ほどよりも、ゆっくりスタートしていますが、どんどんスピードが上がっているのが分かると思います。
まとめ
このページでは、Unityでオブジェクトを徐々に加速させながら移動する方法について、Rigidbodyを使った場合と使わない場合に分けてまとめていきましたが、いかがでしたでしょうか?
Rigidbodyを使った場合は、AddForceメソッドで継続的に力を加えてあげることで、オブジェクトが徐々に加速して動くようになります。
一方、Rigidbodyを使わない場合は、Lerpメソッドで計測時間の値を累乗してあげることで、オブジェクトを加速させて動かすことができるようになります。
Rigidbodyを使う方が簡単ですが、オブジェクトに物理挙動を持たせたくないという場合もあるので、どちらも使えるようになっておきましょう。
最後までお読みいただきまして、ありがとうございました!




コメント