Unity 6の2Dで徐々に加速・減速する移動を作る(Mathf.MoveTowards)
この記事は「Unity 6 2D移動の総合ガイド」の一部です。前の記事では、キーを押すとすぐに最高速度で動きました。今回は、キーを押すと徐々に加速し、離すと徐々に停止する、少し慣性のある動きを作ります。乗り物や、ドシッとした操作感のキャラクターに使えます。
この記事で分かること
Mathf.MoveTowards()で、値を少しずつ目標に近づける方法- 加速と減速の強さを別々に設定する方法
Rigidbody2D.linearVelocityXで、横方向の速度だけを扱う方法
1. 完成する動き
- Dキーを押すと、徐々に右へ加速していく
- Aキーを押すと、徐々に左へ加速していく
- キーを離すと、徐々に減速して停止する
2. 準備
共通の準備は総合ガイドの「共通の準備」をご覧ください。この記事もRigidbody2Dを使うため、Playerに次のコンポーネントと設定を用意します。
- Rigidbody 2D
- Box Collider 2D
| 項目 | 設定値 | 理由 |
|---|---|---|
| Body Type | Dynamic | 物理演算に従って動くオブジェクトにする |
| Gravity Scale | 0 | 横方向だけを制御するため、重力で落ちないようにする |
| Freeze Rotation Z | 有効 | 回転しないようにする |
前の記事のPhysicsMoveが付いている場合は、取り外してください。
3. スクリプトを作る
AccelerationMoveという名前でスクリプトを作り、Playerに取り付けます。
AccelerationMove.cs
using UnityEngine;
using UnityEngine.InputSystem;
public class AccelerationMove : MonoBehaviour
{
[SerializeField] float maxSpeed = 5f;
[SerializeField] float acceleration = 10f;
[SerializeField] float deceleration = 15f;
Rigidbody2D rb;
float inputX;
void Awake()
{
rb = GetComponent<Rigidbody2D>();
}
void Update()
{
inputX = 0f;
if (Keyboard.current == null)
return;
if (Keyboard.current.aKey.isPressed)
inputX -= 1f;
if (Keyboard.current.dKey.isPressed)
inputX += 1f;
}
void FixedUpdate()
{
float targetSpeed = inputX * maxSpeed;
float rate = inputX == 0f
? deceleration
: acceleration;
float newSpeed = Mathf.MoveTowards(
rb.linearVelocityX,
targetSpeed,
rate * Time.fixedDeltaTime
);
rb.linearVelocityX = newSpeed;
}
}
Inspectorで、Max Speed、Acceleration、Decelerationの3つの数値を変更できます。ゲームを再生しながら、動きの変化を確かめてみましょう。
4. コードの解説
① 3つの数値
| 変数 | 意味 | 初期値 |
|---|---|---|
maxSpeed | 最高速度 | 5 |
acceleration | 1秒あたりに速度が増える量 | 10 |
deceleration | 1秒あたりに速度が減る量 | 15 |
② 目標の速度を決める
float targetSpeed = inputX * maxSpeed;
キーが押されているときは、最高速度(±5)が目標になります。離したときはinputXが0なので、目標は0になります。
③ 加速と減速を切り替える
float rate = inputX == 0f
? deceleration
: acceleration;
これは条件演算子です。キーを押していない(inputX == 0f)ときは減速の強さを、押しているときは加速の強さを使います。
④ Mathf.MoveTowards()
Mathf.MoveTowards(
現在の値,
目標の値,
1回で変化できる最大量
);
現在の値を、目標の値に向けて、最大量だけ近づけます。目標を行き過ぎることはありません。
たとえば現在の速度が0で目標が5の場合でも、一度に5にはなりません。accelerationが10でTime.fixedDeltaTimeが0.02なら、1回で増えるのは10 × 0.02 = 0.2だけです。これを繰り返すと、約0.5秒で最高速度に到達します。
減速は、目標が0になるだけで同じ仕組みです。decelerationが15なら、最高速度から約0.33秒で停止します。
⑤ rb.linearVelocityX
linearVelocityXは、Rigidbody2Dの速度のX成分だけを読み書きできるプロパティです。Y方向の速度には影響しません。前の記事のlinearVelocityは、1つのベクトルとしてXとYをまとめて扱いました。
このサンプルは横方向だけを制御するため、linearVelocityXが便利です。次のジャンプの記事でも、Y方向を別に扱うために使います。
⑥ 力(AddForce)との違い
このサンプルは、物理的な力を加えているのではなく、速度を直接、少しずつ変えています。物理的な力を使った加速は、⑫ AddForceで物理的に移動するで比較します。
この方法の利点は、加速と減速の強さを別々に設定できることです。
5. よくあるつまずき
| 症状 | 確認すること |
|---|---|
| ゲーム開始と同時に落ちる | Gravity Scaleが0になっているか |
| 動かない | Body TypeがDynamicか。前の記事のスクリプトと競合していないか |
| 加速しない・すぐ最高速度になる | accelerationの値が極端に大きくなっていないか |
| 離しても止まらない | decelerationが0になっていないか |
linearVelocityXでエラーが出る | Unity 6以降であることを確認する |
6. 練習問題
accelerationとdecelerationをいろいろな値にして、動きの違いを比べてみましょう- 右に進んでいるときAキーを押して左へ切り返すと、すぐに向きを変えられません。切り返しを速くする方法を考えてみましょう
ヒント
- 2つ目では、現在の速度と入力の向きが逆になっているかどうかを調べます。
- 逆向きの場合は、減速の強さを使います。
- 現在の速度と入力を掛け算して、マイナスになるかどうかで判定できます。
解答例(まず自分で試してから見ましょう)
void FixedUpdate()
{
float targetSpeed = inputX * maxSpeed;
// 現在の向きと入力の向きが逆なら、掛け算がマイナスになる
bool isTurning = rb.linearVelocityX * inputX < 0f;
float rate = (inputX == 0f || isTurning)
? deceleration
: acceleration;
rb.linearVelocityX = Mathf.MoveTowards(
rb.linearVelocityX,
targetSpeed,
rate * Time.fixedDeltaTime
);
}
切り返すときは、まず強い減速で速度を落とし、その後で逆向きに加速します。
7. まとめ
Mathf.MoveTowards()で、速度を少しずつ目標に近づけられる- 目標速度を0にすると、徐々に減速して停止する
- 加速と減速の強さを別々に設定できる
linearVelocityXを使うと、横方向の速度だけを扱える
次の記事では、横スクロールアクションで欠かせないジャンプを作ります。
参考:Unity公式ドキュメント










ディスカッション
コメント一覧
まだ、コメントがありません