学習記事一覧 · Unity教科書_Unity6対応

Unity入門:雲を踏んで頂上を目指せ!ClimbCloudゲームを作りながら学ぼう!

対象読者:Unity学び始めの方・C#をこれから覚えたい方 このブログでは、実際のClimbCloudゲームのコードを読み解きながら、Unityの物理演算・アニメーション・シーン管理を学びます。


記事の目次

この記事はやや長めです。目的に合わせてジャンプして読み分けてください。

おすすめの読み方

セクション一覧

ポイント一覧


このゲームで何ができるの?

今回題材にするのは、雲の足場を踏みながら自動で右に進む猫を、クリックでジャンプさせてゴールを目指す2Dアクションゲームです。

  • 🖱️ マウスをクリックすると猫がジャンプする
  • 🐱 猫は自動で右方向に歩き続ける
  • ☁️ 雲の足場を踏みながら上を目指す
  • 🏁 ゴールに触れるとクリア画面に切り替わる
  • 💀 画面の下に落ちるとゲームが最初からやり直しになる

雲の足場を踏んでジャンプしながら登っていく様子(イメージ)

たった 1つのスクリプト(約65行) でこれが実現できます。物理演算・スプライトアニメーション・シーン切り替えという、ゲーム開発の核心的なトピックが詰まっています。一緒に読み解いていきましょう!


プロジェクトの構成

このプロジェクトのファイル構成はこうなっています。

Assets/
  ├── PlayerController.cs   # プレイヤー(猫)を制御するスクリプト
  ├── catWalkA.png          # 歩きアニメーション画像①
  ├── catWalkB.png          # 歩きアニメーション画像②
  ├── catJump.png           # ジャンプ中の画像
  ├── cloud.png             # 足場となる雲の画像
  ├── cloudPrefab.prefab    # 雲のプレハブ
  ├── flag.png              # ゴールのフラグ画像
  ├── background.png        # ゲーム中の背景
  ├── backgroundClear.png   # クリア時の背景
  ├── GameScene.unity       # ゲームのメインシーン
  └── ClearScene.unity      # クリア後のシーン

今回は スクリプト1本で多くの機能を実現しています。物理演算はUnityのコンポーネントに任せ、スクリプトはその制御に集中するという設計です。


コードを全部見てみよう

PlayerController.cs(プレイヤーの制御)

using UnityEngine;
using UnityEngine.InputSystem;          // 入力を検知するために必要!!
using UnityEngine.SceneManagement;      // LoadSceneを使うために必要!!

public class PlayerController : MonoBehaviour
{
    Rigidbody2D rigid2D;
    float jumpForce = 600.0f;
    float walkForce = 30.0f;
    float maxWalkSpeed = 2.0f;
    public Sprite[] walkSprites;
    public Sprite jumpSprite;
    float time = 0;
    int idx = 0;
    SpriteRenderer spriteRenderer;

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

    void Update()
    {
        // ジャンプする
        if (Mouse.current.leftButton.wasPressedThisFrame && this.rigid2D.linearVelocityY == 0)
        {
            this.rigid2D.AddForce(transform.up * this.jumpForce);
        }

        // 右に移動
        if (this.rigid2D.linearVelocityX < this.maxWalkSpeed)
        {
            this.rigid2D.AddForce(transform.right * walkForce);
        }

        // アニメーション
        if (this.rigid2D.linearVelocityY != 0)
        {
            this.spriteRenderer.sprite = this.jumpSprite;
        }
        else
        {
            this.time += Time.deltaTime;
            if (this.time > 0.1f)
            {
                this.time = 0;
                this.spriteRenderer.sprite = this.walkSprites[this.idx];
                this.idx = 1 - this.idx;
            }
        }

        // 画面外に出た場合は最初から
        if (transform.position.y < -10)
        {
            SceneManager.LoadScene("GameScene");
        }
    }

    // ゴールに到達
    void OnTriggerEnter2D(Collider2D collision)
    {
        Debug.Log("ゴール");
        SceneManager.LoadScene("ClearScene");
    }
}

このスクリプトには、合計8つの学びポイントがあります。順番に見ていきましょう!


ポイント①:Rigidbody2D で物理演算を使う

Rigidbody2D rigid2D;

void Start()
{
    this.rigid2D = GetComponent<Rigidbody2D>();
}

Rigidbody2D はUnityの物理演算コンポーネントです。これをGameObjectにアタッチすると、重力・摩擦・慣性などの物理法則が自動的に適用されます。

コンポーネント 役割
Rigidbody2D 物理演算(重力・力・速度)を管理する
Collider2D 物体の形・当たり判定の範囲を定義する

GetComponent<Rigidbody2D>() でこのコンポーネントへの参照を取得し、フィールド rigid2D に保存しています。Start() で一度だけ取得して変数に入れておくのがベストプラクティスです。


ポイント②:AddForce() で力を加えて動かす

// ジャンプする
this.rigid2D.AddForce(transform.up * this.jumpForce);

// 右に移動
this.rigid2D.AddForce(transform.right * walkForce);

AddForce() はRigidbody2Dに力を加えるメソッドです。transform.Translate() のような「直接座標を動かす」のとは違い、力を加えることで物理的に自然な動きが生まれます。

アプローチ 特徴
transform.Translate() 座標を直接変える。物理演算を無視
Rigidbody2D.AddForce() 力を加える。慣性・重力が自然に働く

transform.up はGameObjectの「上方向」のベクトル(2Dでは Y プラス方向)を表します。transform.right は「右方向」(X プラス方向)です。これに力の大きさを掛けることで、方向と強さを指定しています。

transform.up * 600.0f  → 上方向に600の力 → ジャンプ!
transform.right * 30.0f → 右方向に30の力 → 右に歩く

ポイント③:linearVelocityY == 0 で二段ジャンプを防ぐ

if (Mouse.current.leftButton.wasPressedThisFrame && this.rigid2D.linearVelocityY == 0)
{
    this.rigid2D.AddForce(transform.up * this.jumpForce);
}

クリックしたときにY方向の速度がゼロのときだけジャンプを許可しています。

地面や雲の上にいる → Y速度 = 0 → ジャンプOK
ジャンプ中(上昇・落下中)→ Y速度 ≠ 0 → ジャンプ禁止

&&(AND条件)を使って2つの条件を同時にチェックしているのがポイントです。これにより、空中でクリックしても二段ジャンプができない仕様を1行で実現しています。

💡 Unity6では速度プロパティが velocity から linearVelocity に名称変更されました。X方向は linearVelocityX、Y方向は linearVelocityY でアクセスできます。


ポイント④:最大速度を上限として自動歩行する

float walkForce = 30.0f;
float maxWalkSpeed = 2.0f;

// 右に移動
if (this.rigid2D.linearVelocityX < this.maxWalkSpeed)
{
    this.rigid2D.AddForce(transform.right * walkForce);
}

毎フレーム右方向に力を加え続けることで、猫は自動で右に歩き続けます。しかし力を加え続けると速度が無限に増えてしまいます。そこで「現在のX速度が最大速度未満のときだけ力を加える」という上限チェックを入れています。

速度 < 2.0f → 力を加える(加速)
速度 ≥ 2.0f → 力を加えない(速度維持)

この仕組みによって、猫は maxWalkSpeed = 2.0f の速度で安定して右に歩き続けます。プレイヤーの操作は「ジャンプだけ」という、シンプルな一ボタン操作が実現できています。


ポイント⑤:スプライト配列と 1 - idx でアニメーションする

public Sprite[] walkSprites;
public Sprite jumpSprite;
float time = 0;
int idx = 0;
SpriteRenderer spriteRenderer;

// アニメーション
if (this.rigid2D.linearVelocityY != 0)
{
    this.spriteRenderer.sprite = this.jumpSprite;
}
else
{
    this.time += Time.deltaTime;
    if (this.time > 0.1f)
    {
        this.time = 0;
        this.spriteRenderer.sprite = this.walkSprites[this.idx];
        this.idx = 1 - this.idx;
    }
}

スプライトアニメーションの仕組みを分解しましょう。

状態による画像切り替え:

Y速度 ≠ 0(ジャンプ中・落下中)→ jumpSprite を表示
Y速度 = 0(地面・足場の上)   → 歩きアニメーションを再生

歩きアニメーションの切り替え:

Time.deltaTime を積算して0.1秒ごとに画像を切り替えています。walkSprites は配列(画像を複数格納できる箱)で、idx がどの画像を使うかを示します。

this.idx = 1 - this.idx;

この1行が巧みです。idx が 0 のとき 1 - 0 = 1idx が 1 のとき 1 - 1 = 0 になり、0と1を交互に切り替えられます。

0.0: idx=0 → catWalkA を表示
0.1: idx=1 → catWalkB を表示
0.2: idx=0 → catWalkA を表示
0.3: idx=1 → catWalkB を表示
...(くり返し)

SpriteRenderer コンポーネントの .sprite プロパティに画像を代入するだけで、表示が切り替わります。


ポイント⑥:SceneManager.LoadScene() でシーンを切り替える

using UnityEngine.SceneManagement;

// 画面外に出た場合は最初から
if (transform.position.y < -10)
{
    SceneManager.LoadScene("GameScene");
}

SceneManager.LoadScene("シーン名") で別のシーンに移動できます。シーン名はUnityエディター上でのシーン名(ファイル名から .unity を除いたもの)を文字列で指定します。

呼び出し 何が起きる?
SceneManager.LoadScene("GameScene") ゲームを最初からやり直す
SceneManager.LoadScene("ClearScene") クリア画面に移動する

猫のY座標が -10 を下回ったとき(画面の下に落ちたとき)に "GameScene" をリロードしてゲームを最初からやり直す設計になっています。

💡 SceneManager を使うには、ファイル先頭に using UnityEngine.SceneManagement; の追加が必須です。忘れるとコンパイルエラーになります。また、遷移先のシーンは事前に Build Settings に追加しておく必要があります。


ポイント⑦:OnTriggerEnter2D() でゴール判定をする

void OnTriggerEnter2D(Collider2D collision)
{
    Debug.Log("ゴール");
    SceneManager.LoadScene("ClearScene");
}

OnTriggerEnter2D は、トリガー設定されたColliderに別のColliderが触れた瞬間に自動で呼ばれるメソッドです。物理的な衝突(当たって止まる)ではなく、「接触を検知するだけ」の判定に使います。

コールバック 呼ばれるタイミング
OnTriggerEnter2D トリガー領域に入った瞬間
OnTriggerStay2D トリガー領域の中にいる間
OnTriggerExit2D トリガー領域から出た瞬間
OnCollisionEnter2D 物体に物理的に衝突した瞬間

フラグ(ゴール)のCollider2Dの Is Trigger にチェックを入れることで、猫がフラグに触れた瞬間にこのメソッドが呼ばれてクリア画面へ遷移します。


ポイント⑧:public フィールドでInspectorから設定する

public Sprite[] walkSprites;
public Sprite jumpSprite;

フィールドに public をつけると、UnityのInspectorウィンドウから値を設定できるようになります。

private(またはアクセス修飾子なし)→ Inspectorに表示されない
public                            → Inspectorに表示され、設定できる

walkSprites は配列型なので、Inspectorで要素数を指定して複数の画像をドラッグ&ドロップして登録できます。コードを変更せずに画像を差し替えられるため、アーティストやゲームデザイナーがスクリプトを触らずに調整しやすい設計になっています。


スクリプトの処理フロー

Start()】
  ├─ フレームレートを60FPSに固定
  ├─ Rigidbody2D コンポーネントを取得
  └─ SpriteRenderer コンポーネントを取得

Update() の毎フレーム処理フロー】

① クリックされた AND Y速度がゼロ?
   └─ YES → 上方向に 600 の力 → ジャンプ

X速度が maxWalkSpeed(2.0f) 未満?
   └─ YES → 右方向に 30 の力 → 加速(最大速度まで)

③ Y速度がゼロでない(空中)?
   ├─ YES → jumpSprite を表示
   └─ NO  → time を加算
             time > 0.1f?
             └─ YES → time=0、walkSprites[idx] を表示
                       idx = 1 - idx(0↔1を交互に)

④ Y座標 < -10?
   └─ YES → GameScene をリロード(ゲームオーバー)

【OnTriggerEnter2D()】
  └─ フラグに触れた → ClearScene に移動

自分でカスタマイズしてみよう!

挑戦①:ジャンプ力を変える

float jumpForce = 600.0f;  // 大きくすると高くジャンプ!

挑戦②:歩く速さを変える

float maxWalkSpeed = 2.0f;  // 大きくすると速く歩く
float walkForce = 30.0f;    // 加速力(大きいとすぐに最大速度に達する)

挑戦③:アニメーションの切替速度を変える

if (this.time > 0.1f)  // 0.05f にすると素早いパラパラアニメに!

挑戦④:落下判定の高さを変える

if (transform.position.y < -10)  // -20 にするともっと下まで落ちてからリスタート

挑戦⑤:衝突したオブジェクトの種類によって処理を分ける

void OnTriggerEnter2D(Collider2D collision)
{
    if (collision.gameObject.name == "flag_0")
    {
        SceneManager.LoadScene("ClearScene");
    }
}

まとめ

今回のClimbCloudゲームから学んだことを整理しましょう。

  • Rigidbody2D をアタッチすると重力・慣性などの物理演算が自動で働く
  • GetComponent<>()Start() で一度だけ取得して変数に保存するのがベストプラクティス
  • AddForce() で力を加えると、物理的に自然な動きが生まれる(Translate との違いに注目)
  • linearVelocityY == 0 をチェックすることで、地上にいるときだけジャンプを許可できる
  • 最大速度チェックを使うと、自動歩行の速度上限を簡単に設定できる
  • Sprite[] 配列と 1 - idx のトグルテクニックで、2枚の画像をパラパラアニメ風に切り替えられる
  • SceneManager.LoadScene() でシーンを切り替えられる(using UnityEngine.SceneManagement; を忘れずに)
  • OnTriggerEnter2D はトリガー領域に触れた瞬間に自動で呼ばれる(Is Trigger の設定も必要)
  • public フィールドはInspectorから設定でき、コードを触らずに調整できる

物理演算・アニメーション・シーン管理という3つの要素が1つのスクリプトにまとまっています。「動く→コードを読む→カスタマイズする」 のサイクルを繰り返すことが、Unity上達の近道です。

次のステップとして、ゴールするまでの時間を計測してタイムを表示したり、何回落ちたかのミス数をカウントしたりする機能を追加してみましょう!


最終更新:2026年4月