Unity 6でClimbCloudを作る① ― Rigidbody2Dで歩いて、クリックでジャンプする(PC版)

広告

雲から雲へジャンプしながら、ゴールの旗を目指して登っていく――今回からは「ClimbCloud」を作ります。

CatEscapeまでは、transform.Translate でオブジェクトの位置を自分で少しずつ動かしていました。ClimbCloudでは、Unityの物理エンジンを使います。重力で落ちる、雲の上に乗る、力を加えてジャンプする――こうした動きを、物理エンジンに計算してもらうのが今回のテーマです。

ClimbCloudも2回に分けて解説します。

回内容
今回(①)Rigidbody2DとCollider2Dで物理を付ける/AddForceで右へ歩かせる/クリックでジャンプする
次回(②)歩く・ジャンプのアニメーション/旗に着いたらゴール/シーンの切り替え/落ちたらやり直し

この記事で作るもの

  • 猫が重力で落ちて、雲の上に着地する
  • 猫は自動で右へ歩き続ける(速くなりすぎない)
  • マウスを左クリックすると、猫がジャンプする
  • 空中ではジャンプできない(2段ジャンプしない)
項目内容
UnityUnity 6(サンプルは6000.1で作成)
テンプレートUniversal 2D(URP)
入力Input System(UnityEngine.InputSystem)
操作PC版:マウスの左クリックでジャンプ

1. シーンを準備する

使う画像は、背景(background.png)、雲(cloud.png)、猫(catWalkA.png)です。猫の画像は3枚ありますが、今回は歩く姿の1枚目だけを使います(残りは次回のアニメーションで使います)。

オブジェクトPositionOrder in Layerメモ
背景(background)(0, 0, 0)-1いちばん奥に表示する
猫(catWalkA)(-10, 2, 0)0左上からスタート
雲(cloudPrefab)下の表を参照0Prefabにして6つ並べる

雲は同じものをいくつも置くので、CatEscapeの矢と同じようにPrefabにしておきます。1つ目の雲にあとで説明するコライダーを付けてからProjectウィンドウへドラッグしてPrefabにし、そのPrefabをシーンに6つ並べます。

雲Position(X, Y)
1つ目(-8.8, 1.3)
2つ目(-5, -2.2)
3つ目(-1.9, -0.5)
4つ目(1.7, -1.4)
5つ目(5.7, -2.8)
6つ目(9.1, -1.7)

サンプルは横長の画面を想定しているので、Gameビューが16:9だと、猫のスタート位置(x = -10)が画面の左端より少し外になります。歩いてすぐ画面に入ってくるので問題ありませんが、最初から見えるようにしたい場合は猫のXを -8 くらいにしてください。

2. 物理を付ける ― Rigidbody2D と Collider2D

物理エンジンで動かすには、2種類のコンポーネントを使います。

コンポーネント役割たとえると
Rigidbody2D重力や力を受けて動くようにする「体重」を持たせる
Collider2Dぶつかったり、上に乗ったりできる形を決める「体の輪郭」を決める

猫の設定

Hierarchyで猫を選び、Inspectorの Add Component から次の3つを追加します。

コンポーネント設定理由
Rigidbody2DGravity Scale:3重力を強めにして、ジャンプの動きをキビキビさせる
Rigidbody2DConstraints → Freeze Rotation Z:チェックぶつかったときに猫が回転して転ばないようにする
CircleCollider2DRadius:0.25、Offset:(0, -0.2)足元を丸くして、雲の角に引っかかりにくくする
BoxCollider2DSize:(0.5, 0.6)、Offset:(0, 0.1)体の部分の当たりの形

足元に円のコライダーを使っているのがポイントです。四角だけだと、雲のふちに角が引っかかって止まってしまうことがあります。円なら、段差をなめらかに乗り越えやすくなります。

雲の設定

雲には BoxCollider2D だけを追加し、Sizeを (2.35, 0.5) にします。雲にはRigidbody2Dを付けません。

Rigidbody2D ありRigidbody2D なし
例猫雲
重力受けて落ちる受けない(その場から動かない)
Collider2D があるとほかの物にぶつかって止まる・乗るほかの物が上に乗れる「床」になる

ここまでできたら再生してみましょう。猫が落ちてきて、雲の上にちゃんと着地すれば成功です。まだスクリプトは1行も書いていませんが、重力と着地はすべて物理エンジンが計算してくれています。

猫にはRigidbody2DとCircleCollider2D・BoxCollider2D、雲にはBoxCollider2Dだけを付ける

3. 右へ歩き続ける(AddForce)

次はスクリプトです。Create → Scripting → MonoBehaviour Script で PlayerController を作り、猫に付けます。まずは右へ歩かせてみましょう。

using UnityEngine;

public class PlayerController : MonoBehaviour
{
    Rigidbody2D rigid2D;          // 猫の Rigidbody2D
    float walkForce = 30.0f;      // 歩くときに加える力
    float maxWalkSpeed = 2.0f;    // 歩く速さの上限

    void Start()
    {
        // Update が1秒間に60回を目安に呼ばれるようにする
        Application.targetFrameRate = 60;

        // 同じオブジェクトに付いている Rigidbody2D を取り出しておく
        rigid2D = GetComponent<Rigidbody2D>();
    }

    void Update()
    {
        // 右向きの速さが上限より遅いときだけ、右へ力を加える
        if (rigid2D.linearVelocityX < maxWalkSpeed)
        {
            rigid2D.AddForce(transform.right * walkForce);
        }
    }
}

AddForce は「この方向に、この強さで押す」という命令です。transform.right は右向き(1, 0)を表すので、猫は右へ押されて歩き出します。

Translate と AddForce の違い

transform.TranslateRigidbody2D.AddForce
動かし方位置を直接ずらす(瞬間移動)力を加えて、物理エンジンに動かしてもらう
重力・衝突考慮されない(壁もすり抜ける)考慮される(落ちる・乗る・ぶつかる)
使った章ルーレット・SwipeCar・CatEscapeClimbCloud(今回)

速さに上限をつける理由

AddForce は押し続けるとどんどん加速します。毎フレーム押していると、猫はあっという間に猛スピードになってしまいます。そこで、linearVelocityX(今の右向きの速さ)が maxWalkSpeed(2.0)より遅いときだけ押すようにしています。これで、速さ2くらいを保ったまま、一定のペースで歩き続けます。

4. クリックでジャンプする(完成)

最後にジャンプを追加します。これで今回のPlayerControllerの完成です。

using UnityEngine;
using UnityEngine.InputSystem;   // Mouse を使うために必要

public class PlayerController : MonoBehaviour
{
    Rigidbody2D rigid2D;          // 猫の Rigidbody2D
    float jumpForce = 600.0f;     // ジャンプするときに加える力
    float walkForce = 30.0f;      // 歩くときに加える力
    float maxWalkSpeed = 2.0f;    // 歩く速さの上限

    void Start()
    {
        Application.targetFrameRate = 60;
        rigid2D = GetComponent<Rigidbody2D>();
    }

    void Update()
    {
        // クリックした瞬間、かつ上下に動いていない(着地している)ときだけジャンプ
        if (Mouse.current.leftButton.wasPressedThisFrame && rigid2D.linearVelocityY == 0)
        {
            rigid2D.AddForce(transform.up * jumpForce);
        }

        // 右向きの速さが上限より遅いときだけ、右へ力を加える
        if (rigid2D.linearVelocityX < maxWalkSpeed)
        {
            rigid2D.AddForce(transform.right * walkForce);
        }
    }
}

transform.up は上向き(0, 1)です。クリックした瞬間に上へ600の力で押すので、猫が跳び上がります。歩くときの力(30)に比べてずっと大きいのは、1回だけドンと押すからです。

linearVelocityY == 0 で「着地しているか」を調べる

ジャンプの条件に rigid2D.linearVelocityY == 0 が入っているのがポイントです。linearVelocityY は上下方向の速さです。

猫の状態linearVelocityYジャンプできる?
雲の上を歩いている0できる
ジャンプして上昇中プラスできない
落下中マイナスできない

雲の上にいるときは上下に動いていないので0になります。空中では0以外になるので、ジャンプの途中でもう一度クリックしても、2段ジャンプにはなりません。シンプルですが、よく使われる「着地判定」の考え方です。

AddForceで速さの上限まで加速して歩き、linearVelocityYが0のときだけジャンプする。最高点は約2.4

5. Unity 6では velocity が linearVelocity に変わった

ネットや少し前の本では、速さを rigid2D.velocity と書いているコードをよく見かけます。Unity 6では、この名前が linearVelocity に変わりました。

以前のUnityUnity 6意味
rigid2D.velocityrigid2D.linearVelocity速さ(Vector2)
rigid2D.velocity.xrigid2D.linearVelocityX左右方向の速さ
rigid2D.velocity.yrigid2D.linearVelocityY上下方向の速さ

古い velocity を書くと、「古い書き方(obsolete)です」という警告が出ます。警告なので動くことは動きますが、これから覚えるなら linearVelocity を使いましょう。「回転の速さ(angularVelocity)」と区別するために、「直線方向の(linear)速さ」という名前になったと考えると覚えやすいです。

6. 数字で見るジャンプの高さ

物理エンジンの計算を、ざっくり数字で確かめてみます。

  • AddForce の力は、物理の計算1回分(標準で0.02秒)だけ加わる
  • 猫の重さ(Mass)は1なので、ジャンプの初速は 600 × 0.02 ÷ 1 = 約12
  • 重力は 9.81 × Gravity Scale(3)= 約29.4
  • 最高点の高さは 12 × 12 ÷ (2 × 29.4) = 約2.4

つまり、猫は1回のジャンプで約2.4上がる計算です。次の雲へ登るときの高さの差は最大でも1.7くらいなので、しっかり跳べば届く配置になっています。jumpForce や Gravity Scale を変えて、ジャンプの高さや落ちる速さがどう変わるか試してみましょう。

変える値大きくすると小さくすると
jumpForce(600)高く跳ぶ低くしか跳べない
Gravity Scale(3)速く落ちる・低く跳ぶ(キビキビ)ゆっくり落ちる・高く跳ぶ(ふわふわ)
maxWalkSpeed(2.0)速く歩くゆっくり歩く

7. よくあるつまずき

猫が雲をすり抜けて落ちていく

猫か雲のどちらかにCollider2Dが付いていません。猫にはCircleCollider2DとBoxCollider2D、雲にはBoxCollider2Dが付いているか確認しましょう。雲をPrefabにしたあとでコライダーを付けた場合は、Prefab側に付いているかも確認します。

猫がゴロンと転がってしまう

Rigidbody2Dの Constraints → Freeze Rotation Z にチェックが入っていません。

NullReferenceException が出る

NullReferenceException: Object reference not set to an instance of an object
PlayerController.Update ()

猫にRigidbody2Dが付いていないため、GetComponent<Rigidbody2D>() が null(空っぽ)を返しています。猫のInspectorにRigidbody2Dがあるか確認しましょう。GetComponentの仕組みは次の記事でも解説しています。

【学習】Unity で他のオブジェクトの機能を使う(Find と GetComponent)

その他のチェックポイント

  • クリックしてもジャンプしない → Gameビューの中をクリックしているか、猫が雲の上に着地しているか確認する
  • 雲も一緒に落ちていく → 雲にRigidbody2Dを付けていないか確認する
  • Mouse が見つからないエラー → using UnityEngine.InputSystem; があるか確認する

8. もう一歩:物理の処理は FixedUpdate で

物理エンジンは、Update(画面の更新ごと)とは別に、決まった間隔(標準で0.02秒ごと)で計算をしています。この物理の計算のタイミングで呼ばれるのが FixedUpdate です。

今回のコードは Update の中で毎フレーム AddForce しているので、フレームレートによって歩く力の加わり方が少し変わります。CatEscapeで学んだ「フレーム単位だと環境で速さが変わる」のと同じ話です。本格的なゲームでは、押し続ける力は FixedUpdate で加えるのが一般的です。ただし、クリックの判定(wasPressedThisFrame)は Update で行う必要があるので、まずは教科書どおりの書き方で動かして、慣れてきたら分けてみましょう。

Unity 6でCatEscapeを作る① ― 猫の移動と、Prefabで矢を降らせる仕組み(PC版)

まとめ

  • Rigidbody2D を付けると重力や力で動き、Collider2D で当たりの形が決まる
  • 動かない床(雲)は、Collider2Dだけを付けてRigidbody2Dは付けない
  • Freeze Rotation Z で、猫が転がらないようにできる
  • AddForce で力を加えて動かす。速さに上限をつけると一定のペースで歩ける
  • linearVelocityY == 0 で「着地しているか」を調べ、2段ジャンプを防げる
  • Unity 6では velocity が linearVelocity に変わった

次回は、猫の歩く・ジャンプのアニメーションと、旗に着いたらクリア画面に切り替わる仕組みを作ります。

続きの②はこちらです。

Unity 6でClimbCloudを作る② ― パラパラ漫画のアニメーションと、ゴール・シーンの切り替え(PC版)

訪問数 1 回, 今日の訪問数 1回

広告