Unityゲームの作り方メモパズルゲーム

【Unity】ツムツム風パズルゲームを作ろう!初心者向け完全ガイド

Unity
  1. 1. はじめに
  2. 2. ボールの作成
    1. ① 円の画像をUnityにインポート
    2. ② ヒエラルキーウィンドウにドラッグ&ドロップ
    3. ③ 物理コンポーネントの追加
    4. ④ Prefab化して使い回せるようにする
  3. 3. 壁の作成
    1. ① 空のオブジェクトを作成
    2. ② EdgeCollider 2Dを追加
    3. ③ U字型の壁を作成
  4. 4. ボールを跳ねさせる
    1. ① Physics Material 2Dを作成
    2. ② Bounciness(跳ね返り係数)を設定
    3. ③ ボールのRigidbodyのMaterialに適用
  5. 5. ボールを自動で生成
    1. ① BallGeneratorスクリプトの作成
    2. ② コルーチンを使用して、一定間隔でボールを生成
    3. ③ BallGeneratorをシーンに配置
    4. ④ 動作確認
  6. 6. 5種類のボールを生成
    1. ① スプライトの配列を用意
    2. ② BallGeneratorスクリプトを修正
    3. ③ BallGeneratorにスプライトを設定
    4. ④ 動作確認
  7. 7. ボールにIDを設定
    1. ① Ballスクリプトを作成
    2. ② BallGeneratorでIDを設定
    3. ③ BallスクリプトをボールのPrefabに適用
    4. ④ 動作確認
  8. 8. ボールをクリックできるようにする
    1. ① GameSystemスクリプトを作成
    2. ② マウスクリックでボールを検出
    3. ③ GameSystemをシーンに配置
    4. ④ 動作確認
  9. 9. ボールを削除する
    1. ① リストを作成し、選択したボールを格納
    2. ② ドラッグ終了時にリスト内のボールを削除
    3. ③ GameSystemにBallGeneratorをセット
    4. ④ 動作確認
  10. 10. 同じ種類のボールのみ削除
    1. ① IDが一致し、距離が近いボールのみリストに追加
    2. ② 3個以上で削除する処理を実装
    3. ③ 動作確認
  11. 11. スコア機能の追加
    1. ① スコアを表示するUIを作成
    2. ② スコアを管理する変数を追加
    3. ③ ボールを消した数 × 100 でスコアを加算
    4. ④ GameSystemにScoreTextをセット
    5. ⑤ 動作確認
  12. 12. まとめ
    1. 今回学んだことのおさらい
    2. 今後の応用
  13. よくある質問(FAQ)
    1. 関連記事:

1. はじめに

ツムツム風パズルゲームとは?

「ツムツム」は、同じ種類のキャラクターを3つ以上つなげて消していく人気のパズルゲームです。シンプルなルールながら、連鎖(コンボ)やスコアアタックの要素があり、幅広い層に楽しまれています。

この記事では、この「ツムツム」のようなパズルゲームをUnityでゼロから作成していきます!
基本的なボールの生成・消去の仕組みや、スコア機能の実装までを順番に解説するので、初心者でも安心して取り組める内容になっています。


本記事で作成するゲームの概要

今回作成するのは、以下のようなシンプルなパズルゲームです。

ボール(ツム)を生成して積み上げる
マウスでボールを選択し、同じ種類のものを消去
3つ以上つなげると消える
スコア機能を実装し、ボールを消すとスコアが加算

このような基本機能を作りながら、ゲーム開発の基礎を学んでいきます!


必要な環境

このチュートリアルを進めるには、以下の環境が必要です。

🖥 Unityのバージョン: Unity 2021.3 LTS 以上(最新のLTS推奨)
💻 開発環境: Windows または Mac
📜 プログラミング言語: C#(Unity標準のスクリプト言語)
🖼 使用するアセット:

  • 円形のボール画像(5種類)
  • 背景画像(任意)

※ボール画像は自作するか、フリー素材サイトからダウンロードしておきましょう!
例えば、無料の素材サイト(イラストAC、pixabayなど)を活用すると良いです。




2. ボールの作成

ツムツム風のパズルゲームでは、ボール(ツム)が積み重なっていくのが特徴です。まずは、ボールを作成し、物理的に動くように設定していきます。


① 円の画像をUnityにインポート

まずは、使用するボールの画像をUnityに取り込みましょう。

  1. 画像を用意する
    円形の画像を PNG形式 で準備します。(背景が透過されているものが理想的)
  2. Unityにインポート
    • プロジェクトウィンドウ(Project) を開く
    • 「Assets」フォルダ内で右クリック →「Import New Asset」 を選択
    • 用意した円の画像を選択し、インポート

インポートした画像は「Sprites」フォルダなどを作成して整理すると管理しやすくなります。


② ヒエラルキーウィンドウにドラッグ&ドロップ

次に、インポートした画像をシーンに配置します。

  1. プロジェクトウィンドウ(Project) から、インポートした画像を選択
  2. ヒエラルキーウィンドウ(Hierarchy) にドラッグ&ドロップ

これで、シーン内にボールの画像が配置されました。


③ 物理コンポーネントの追加

ボールに 物理演算 を適用し、重力で落ちるようにするために「Rigidbody 2D」と「CircleCollider 2D」を追加します。

  1. ヒエラルキーウィンドウでボールを選択
  2. インスペクターウィンドウ(Inspector)で「Add Component」をクリック
  3. 以下のコンポーネントを追加
    • Rigidbody 2D
      → 重力の影響を受けて落下するようになる
    • CircleCollider 2D
      → 円形の当たり判定を設定し、他のオブジェクトと衝突可能にする

Rigidbody 2Dの設定

  • Gravity Scale → 「1.0」(デフォルトのままでOK)
  • Collision Detection → 「Discrete」
  • Interpolate → 「None」(基本的に変更不要)

CircleCollider 2Dの設定

  • Radius → 自動設定されるが、画像に合っているか確認

これで、ボールが物理エンジンで自然に落ちるようになりました!


④ Prefab化して使い回せるようにする

ゲーム中に何度もボールを生成するため、Prefab(プレハブ)として保存しておきます。

  1. ヒエラルキーウィンドウのボールを「Projectウィンドウ」にドラッグ&ドロップ
  2. 「Prefab」に変換される
  3. 元のボールは削除してOK(シーンがスッキリする)

Prefab化すると? ✅ 同じ設定のボールを何度でも簡単に生成できる
✅ スクリプトでボールをプログラムから生成できるようになる


ここまでで、物理的に落下するボールが作成できました。
次は 「壁を作成」して、ボールを囲むようにしていきます!




3. 壁の作成

ボールが画面外に落ちてしまわないように、左右と下に壁を作成します。
この壁は Edge Collider 2D を使用して U字型 に設定します。


① 空のオブジェクトを作成

まずは壁を作成するための 空のオブジェクト を用意します。

  1. ヒエラルキーウィンドウ(Hierarchy)で右クリック
  2. 「Create Empty」を選択
  3. 名前を「Wall」に変更

② EdgeCollider 2Dを追加

壁の当たり判定として、EdgeCollider 2D を使います。

  1. 「Wall」を選択した状態で、インスペクター(Inspector)を開く
  2. 「Add Component」ボタンをクリック
  3. 「EdgeCollider 2D」を検索して追加

Edge Collider 2D は 線状のコライダー なので、ボールが壁にぶつかると跳ね返るようになります。


③ U字型の壁を作成

Edge Collider 2D の 「Edit Collider」 を使用して、壁の形を調整します。

  1. 「Wall」を選択
  2. インスペクターで「Edit Collider」ボタンをクリック
  3. Sceneビューで頂点を編集し、U字型の形にする
    • 3つの点を設定して、ボールが画面外に落ちないようにする

この設定で ボールが跳ね返るU字型の壁 が完成しました!


壁を作成したことで、ボールが画面外に落ちずに跳ね返るようになりました!
次は 「ボールを跳ねるようにする」 ために、Physics Material 2D を設定していきましょう!




4. ボールを跳ねさせる

ツムツム風のパズルゲームでは、ボールが自然に跳ね返る動きが重要です。
そのために、Physics Material 2D を使用してボールの反発力(Bounciness)を設定します。


① Physics Material 2Dを作成

まずは 跳ね返りの設定を行うPhysics Material 2D を作成します。

  1. プロジェクトウィンドウ(Project)で「Assets」フォルダを開く
  2. 「Assets」内で右クリック →「Create」→「Physics Material 2D」 を選択
  3. 作成されたファイルの名前を「BallMaterial」に変更

これで、ボールの跳ね返りを調整する物理マテリアルが作成できました。


② Bounciness(跳ね返り係数)を設定

「BallMaterial」の設定を変更し、ボールが跳ね返るようにします。

  1. 「BallMaterial」をクリックしてインスペクター(Inspector)を開く
  2. 以下のパラメータを設定
    • Friction(摩擦): 0.4(摩擦)
    • Bounciness(跳ね返り係数): 0.5(高めにするとよく跳ねる)

Bounciness1.0 にすると 完全にエネルギーを失わずに跳ね続ける ため、適度な値(0.60.8)に調整すると自然な挙動になります。


③ ボールのRigidbodyのMaterialに適用

作成した「BallMaterial」をボールに設定します。

  1. ヒエラルキーウィンドウ(Hierarchy)で「Ball」のPrefabを選択
  2. インスペクター(Inspector)で「Rigidbody 2D」の設定を確認
  3. 「Material」の項目に「BallMaterial」をドラッグ&ドロップ

これで、ボールが跳ね返るようになりました!
再生ボタン(▶)を押して動作を確認 してみましょう。ボールが床や壁に当たると、自然に跳ね返るはずです。


ボールが跳ね返るようになったので、次は 「ボールをランダムな位置に生成する」 処理を作っていきます!
コルーチンを使って、一定間隔でボールを生成してみましょう!




5. ボールを自動で生成

ツムツム風パズルゲームでは、ボールが自動的に生成され、画面上に積み重なっていく仕組みが必要です。
ここでは、新しく BallGenerator スクリプト を作成し、一定間隔でボールをランダムな位置に生成する 方法を解説します。


① BallGeneratorスクリプトの作成

まず、ボールを自動生成するスクリプトを作成します。

  1. プロジェクトウィンドウ(Project)で「Assets」フォルダを開く
  2. 「Assets」内で右クリック →「Create」→「C# Script」 を選択
  3. スクリプトの名前を「BallGenerator」に変更
  4. スクリプトをダブルクリックして開く

② コルーチンを使用して、一定間隔でボールを生成

ボールを 一定間隔で自動生成 するために、コルーチン(Coroutine) を使います。

以下のコードを BallGenerator.cs に入力してください。

using System.Collections;
using UnityEngine;

public class BallGenerator : MonoBehaviour
{
    [SerializeField] GameObject ballPrefab = default; // ボールのプレハブを設定

    private void Start()
    {
        StartCoroutine(Spawns(10)); // コルーチンを開始し、ボールを生成
    }

    public IEnumerator Spawns(int count)
    {
        for (int i = 0; i < count; i++)
        {
            // ランダムな位置にボールを生成
            Vector2 pos = new Vector2(Random.Range(-2f, 2f), 5f);
            Instantiate(ballPrefab, pos, Quaternion.identity);

            // 次のボールを生成するまで少し待つ
            yield return new WaitForSeconds(0.5f);
        }
    }
}

ポイント解説

  • Start関数StartCoroutine(Spawns(10)) を呼び出し、ボールを10個生成。
  • Spawns関数 の中で、for ループを使い、ボールを1つずつ生成 する。
  • Random.Range(-2f, 2f) を使用し、X座標がランダムな位置にスポーン するようにする。
  • WaitForSeconds(0.5f) で、0.5秒ごとにボールを生成 する。

③ BallGeneratorをシーンに配置

作成した BallGenerator スクリプトをシーンに配置します。

  1. ヒエラルキーウィンドウ(Hierarchy)で「空のオブジェクト」を作成
    • 右クリック →「Create Empty」
    • 名前を BallGenerator に変更
  2. インスペクターウィンドウ(Inspector)で「Add Component」ボタンをクリック
    • 検索ボックスで BallGenerator を検索して追加
  3. インスペクターの「Ball Prefab」に、作成したボールのPrefabを設定
    • プロジェクトウィンドウの BallPrefabドラッグ&ドロップ

④ 動作確認

再生ボタン(▶)を押してゲームを実行 してみましょう!
画面上部から ボールがランダムな位置に一定間隔で生成 されるはずです。


ボールが生成されるようになったので、次は 「5種類のボールをランダムに生成する」 仕組みを追加します!
ボールに 異なるスプライトを適用 して、色の違うボールを作成してみましょう!




6. 5種類のボールを生成

ツムツム風のパズルゲームでは、さまざまな種類のボール(ツム)を用意し、ランダムに生成 することで、より楽しいゲームになります。
ここでは、5種類のボールを生成する方法 を解説します!


① スプライトの配列を用意

まず、5種類のボール画像をスクリプトで管理できるように、スプライトの配列を用意します。

  1. 5種類のボール画像(円形の異なる色)を用意する
    • Ball_1.png(赤)
    • Ball_2.png(青)
    • Ball_3.png(緑)
    • Ball_4.png(黄)
    • Ball_5.png(紫)
  2. これらの画像を「Sprites」フォルダにインポート
    • プロジェクトウィンドウ(Project)で「Assets」→「Sprites」フォルダを作成
    • そこに5種類の画像をドラッグ&ドロップしてインポート

② BallGeneratorスクリプトを修正

ボールの生成時に、ランダムなスプライトを適用する処理 を追加します。

BallGenerator.cs を開き、以下のコードに修正してください。

using System.Collections;
using UnityEngine;

public class BallGenerator : MonoBehaviour
{
    [SerializeField] GameObject ballPrefab = default; // ボールのプレハブ
    [SerializeField] Sprite[] ballSprites = default; // 5種類のスプライト配列

    private void Start()
    {
        StartCoroutine(Spawns(10)); // ボールを10個生成
    }

    public IEnumerator Spawns(int count)
    {
        for (int i = 0; i < count; i++)
        {
            // ランダムな位置
            Vector2 pos = new Vector2(Random.Range(-2f, 2f), 5f);
            
            // ボールを生成
            GameObject ball = Instantiate(ballPrefab, pos, Quaternion.identity);
            
            // ランダムなスプライトを適用
            int randomIndex = Random.Range(0, ballSprites.Length);
            ball.GetComponent<SpriteRenderer>().sprite = ballSprites[randomIndex];

            // 次のボールを生成するまで少し待つ
            yield return new WaitForSeconds(0.5f);
        }
    }
}

③ BallGeneratorにスプライトを設定

スクリプトを修正したら、Unityのインスペクターで設定を行います。

  1. ヒエラルキーウィンドウ(Hierarchy)で「BallGenerator」を選択
  2. インスペクターウィンドウ(Inspector)で「Ball Sprites」の項目を確認
  3. 「Ball Sprites」のサイズを「5」に変更
  4. それぞれのスロットに用意した5種類のスプライトをドラッグ&ドロップ

④ 動作確認

再生ボタン(▶)を押して、ゲームを実行!
画面上部から ランダムな色のボールが一定間隔で生成 されることを確認しましょう。

異なる色のボールが出てくるか?
ボールがバラバラの位置にスポーンするか?


これで 5種類のボールがランダムに生成 されるようになりました!
次は、ボールにIDを設定し、同じ種類のボールを識別できるように していきましょう!




7. ボールにIDを設定

ツムツム風のパズルゲームでは、同じ種類のボールを識別できるようにする ことが重要です。
これを実現するために、ボールにIDを付与し、後でグループ分けできるようにします。


① Ballスクリプトを作成

まず、新しいスクリプトを作成し、ボールごとにIDを持たせる 仕組みを作ります。

  1. プロジェクトウィンドウ(Project)で「Assets」フォルダを開く
  2. 「Assets」内で右クリック →「Create」→「C# Script」
  3. スクリプトの名前を「Ball」に変更
  4. スクリプトをダブルクリックして開く

次に、以下のコードを入力してください。

using UnityEngine;

public class Ball : MonoBehaviour
{
public int id; // ボールの種類を識別するID
}

このスクリプトを ボールのPrefab に設定することで、各ボールに 異なるID を持たせることができるようになります。


② BallGeneratorでIDを設定

次に、BallGenerator.cs を修正し、ボールを生成する際にIDを設定 するようにします。

BallGenerator.cs を開いて、以下のように修正してください。

using System.Collections;
using UnityEngine;

public class BallGenerator : MonoBehaviour
{
    [SerializeField] GameObject ballPrefab = default; // ボールのプレハブ
    [SerializeField] Sprite[] ballSprites = default; // 5種類のスプライト配列

    private void Start()
    {
        StartCoroutine(Spawns(10)); // ボールを10個生成
    }

    public IEnumerator Spawns(int count)
    {
        for (int i = 0; i < count; i++)
        {
            // ランダムな位置
            Vector2 pos = new Vector2(Random.Range(-2f, 2f), 5f);
            
            // ボールを生成
            GameObject ball = Instantiate(ballPrefab, pos, Quaternion.identity);
            
            // ランダムなIDを取得(0~4)
            int ballID = Random.Range(0, ballSprites.Length);

            // ボールにスプライトを設定
            ball.GetComponent<SpriteRenderer>().sprite = ballSprites[ballID];

            // ボールにIDを設定
            ball.GetComponent<Ball>().id = ballID;

            // 次のボールを生成するまで少し待つ
            yield return new WaitForSeconds(0.5f);
        }
    }
}

③ BallスクリプトをボールのPrefabに適用

スクリプトを修正したら、Unityで以下の設定を行います。

  1. プロジェクトウィンドウ(Project)で「BallPrefab」を選択
  2. インスペクターウィンドウ(Inspector)で「Add Component」ボタンをクリック
  3. 「Ball」スクリプトを追加
  4. 変更を適用(Prefabに保存)

④ 動作確認

再生ボタン(▶)を押して、ゲームを実行!
Unityの Consoleウィンドウ(ログ)Debug.Log(ballID); を追加すると、各ボールに異なるID が割り当てられていることを確認できます。

5種類のボールが異なるIDを持っているか?
IDごとに正しくスプライトが割り当てられているか?


これで ボールにIDを設定し、同じ種類を識別 できるようになりました!
次は 「ボールをクリックできるようにする」 機能を実装し、プレイヤーがボールを選択できるようにしていきましょう!




8. ボールをクリックできるようにする

ツムツム風のパズルゲームでは、プレイヤーがボールを選択して消せるようにする 必要があります。
ここでは、マウスクリックでボールを検出する GameSystemスクリプト を作成し、クリックしたボールを識別する処理を実装します。


① GameSystemスクリプトを作成

まず、新しいスクリプトを作成し、ボールをクリックして検出する処理 を追加します。

  1. プロジェクトウィンドウ(Project)で「Assets」フォルダを開く
  2. 「Assets」内で右クリック →「Create」→「C# Script」
  3. スクリプトの名前を「GameSystem」に変更
  4. スクリプトをダブルクリックして開く

② マウスクリックでボールを検出

次に、GameSystem.csクリックしたボールを識別する処理 を実装します。

以下のコードを入力してください。

using UnityEngine;

public class GameSystem : MonoBehaviour
{
    void Update()
    {
        // 左クリックが押されたとき
        if (Input.GetMouseButtonDown(0))
        {
            OnClick();
        }
    }

    void OnClick()
    {
        // マウスの位置を取得し、ワールド座標に変換
        Vector2 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);

        // クリック位置にRaycastを飛ばす
        RaycastHit2D hit = Physics2D.Raycast(mousePosition, Vector2.zero);

        // ボールがクリックされた場合
        if (hit && hit.collider.GetComponent<Ball>())
        {
            Ball clickedBall = hit.collider.GetComponent<Ball>();
            Debug.Log("ボールがクリックされました! ID: " + clickedBall.id);
        }
    }
}

③ GameSystemをシーンに配置

作成した GameSystem スクリプトをシーンに配置します。

  1. ヒエラルキーウィンドウ(Hierarchy)で「空のオブジェクト」を作成
    • 右クリック →「Create Empty」
    • 名前を GameSystem に変更
  2. インスペクターウィンドウ(Inspector)で「Add Component」ボタンをクリック
    • 検索ボックスで GameSystem を検索して追加

④ 動作確認

再生ボタン(▶)を押して、ゲームを実行!
画面内のボールを クリックしてConsoleウィンドウ(ログ)を確認 してみましょう。

ボールをクリックすると「ボールがクリックされました! ID: ○○」と表示されるか?
異なるボールをクリックすると、IDが正しく変わるか?


ボールをクリックできるようになったので、次は 「クリックしたボールを削除する」 処理を追加していきます!
リストを作成し、選択したボールを削除する仕組みを作りましょう!




9. ボールを削除する

ツムツム風パズルゲームでは、プレイヤーがボールを選択し、リストに追加し、最終的に削除する 仕組みが必要です。
ここでは、クリックしたボールを リストに格納 し、ドラッグ終了時に リスト内のボールを削除 する処理を追加します。


① リストを作成し、選択したボールを格納

まず、GameSystem スクリプトに リストを作成 し、選択したボールを追加できるようにします。

GameSystem.cs を開いて、以下のコードを追加してください。

using System.Collections.Generic;
using UnityEngine;

public class GameSystem : MonoBehaviour
{
    [SerializeField] BallGenerator ballGenerator = default; // ボール生成用
    private List<Ball> removeBalls = new List<Ball>(); // 削除対象のボールリスト
    private bool isDragging = false; // ドラッグ判定

    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            OnDragBegin(); // ドラッグ開始
        }
        else if (Input.GetMouseButtonUp(0))
        {
            OnDragEnd(); // ドラッグ終了
        }
        else if (isDragging)
        {
            OnDragging(); // ドラッグ中
        }
    }

    void OnDragBegin()
    {
        // マウスの位置を取得し、ワールド座標に変換
        Vector2 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        RaycastHit2D hit = Physics2D.Raycast(mousePosition, Vector2.zero);

        if (hit && hit.collider.GetComponent<Ball>())
        {
            Ball ball = hit.collider.GetComponent<Ball>();
            AddRemoveBall(ball); // ボールをリストに追加
            isDragging = true; // ドラッグ開始フラグを立てる
        }
    }

    void OnDragging()
    {
        Vector2 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        RaycastHit2D hit = Physics2D.Raycast(mousePosition, Vector2.zero);

        if (hit && hit.collider.GetComponent<Ball>())
        {
            Ball ball = hit.collider.GetComponent<Ball>();
            AddRemoveBall(ball);
        }
    }
}

ポイント解説

  • removeBalls リストを作成 し、削除対象のボールを格納
  • OnDragBegin()クリックしたボールをリストに追加
  • OnDragging()ドラッグ中のボールを追加

② ドラッグ終了時にリスト内のボールを削除

次に、OnDragEnd() を追加し、リストに追加されたボールを削除する処理を実装します。

GameSystem.cs に以下のコードを追加してください。

void OnDragEnd()
{
    // リストに格納されたボールを削除
    int removeCount = removeBalls.Count;
    if (removeCount > 0)
    {
        for (int i = 0; i < removeCount; i++)
        {
            Destroy(removeBalls[i].gameObject);
        }
        removeBalls.Clear(); // リストをリセット
    }

    Debug.Log("ドラッグ終了 - ボール削除完了");
    isDragging = false; // ドラッグフラグをリセット
}

void AddRemoveBall(Ball ball)
{
    // すでにリストに含まれていない場合のみ追加
    if (!removeBalls.Contains(ball))
    {
        removeBalls.Add(ball);
    }
}

ポイント解説

  • OnDragEnd()removeBalls 内のすべてのボールを削除
  • removeBalls.Clear(); でリストをリセット
  • リストにすでに含まれているボールは追加しない

③ GameSystemにBallGeneratorをセット

Unityのインスペクターで設定を行います。

  1. ヒエラルキーウィンドウ(Hierarchy)で「GameSystem」を選択
  2. インスペクターウィンドウ(Inspector)で「Ball Generator」フィールドを確認
  3. 「BallGenerator」をドラッグ&ドロップしてセット

④ 動作確認

再生ボタン(▶)を押して、ゲームを実行!
画面内のボールを ドラッグして選択後、離したときに削除されるか確認 しましょう。

ボールをクリックすると削除リストに追加されるか?
ドラッグ中のボールも追加されるか?
ドラッグ終了時にリスト内のボールが削除されるか?


これで 選択したボールを削除できる ようになりました!
次は、「同じ種類のボールのみリストに追加する」 処理を実装し、ゲームのルールを完成させていきましょう!




10. 同じ種類のボールのみ削除

ボールを削除する処理ができましたが、現在はどのボールでも削除できる状態です。
ツムツム風ゲームでは、同じ種類(IDが一致)かつ、距離が近いボール だけが削除されるようにする必要があります。
また、3個以上つながった場合のみ削除 することで、ゲームのルールを作ります。


① IDが一致し、距離が近いボールのみリストに追加

まず、GameSystem に、ドラッグしたボールの IDが一致し、一定距離以内 である場合のみ削除リストに追加する処理を実装します。

GameSystem.cs に以下のコードを追加してください。

using System.Collections.Generic;
using UnityEngine;

public class GameSystem : MonoBehaviour
{
    [SerializeField] BallGenerator ballGenerator = default; // ボール生成用
    private List<Ball> removeBalls = new List<Ball>(); // 削除対象のボールリスト
    private bool isDragging = false; // ドラッグ判定
    private Ball currentDraggingBall; // 現在選択しているボール

    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            OnDragBegin(); // ドラッグ開始
        }
        else if (Input.GetMouseButtonUp(0))
        {
            OnDragEnd(); // ドラッグ終了
        }
        else if (isDragging)
        {
            OnDragging(); // ドラッグ中
        }
    }

    void OnDragBegin()
    {
        Vector2 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        RaycastHit2D hit = Physics2D.Raycast(mousePosition, Vector2.zero);

        if (hit && hit.collider.GetComponent<Ball>())
        {
            Ball ball = hit.collider.GetComponent<Ball>();
            currentDraggingBall = ball; // 選択したボールを基準にする
            AddRemoveBall(ball);
            isDragging = true;
        }
    }

    void OnDragging()
    {
        Vector2 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        RaycastHit2D hit = Physics2D.Raycast(mousePosition, Vector2.zero);

        if (hit && hit.collider.GetComponent<Ball>())
        {
            Ball ball = hit.collider.GetComponent<Ball>();

            // 同じIDを持ち、かつ距離が近いボールのみ追加
            if (ball.id == currentDraggingBall.id)
            {
                float distance = Vector2.Distance(ball.transform.position, currentDraggingBall.transform.position);
                if (distance < 1.5f) // 近いボールのみ追加
                {
                    AddRemoveBall(ball);
                }
            }
        }
    }
}

② 3個以上で削除する処理を実装

次に、OnDragEnd() の処理を変更し、3個以上のボールが選択された場合のみ削除 するようにします。

GameSystem.cs に以下のコードを追加してください。

void OnDragEnd()
{
    int removeCount = removeBalls.Count;

    // 3個以上なら削除
    if (removeCount >= 3)
    {
        for (int i = 0; i < removeCount; i++)
        {
            Destroy(removeBalls[i].gameObject);
        }
    }

    // リストをリセット
    removeBalls.Clear();
    isDragging = false;
}

void AddRemoveBall(Ball ball)
{
    // すでにリストに含まれていない場合のみ追加
    if (!removeBalls.Contains(ball))
    {
        removeBalls.Add(ball);
    }
}

③ 動作確認

再生ボタン(▶)を押して、ゲームを実行!
画面内のボールを ドラッグして、3つ以上つなげると消えるか確認 しましょう。

同じ種類のボール(IDが一致するもの)のみ削除されるか?
異なる種類のボールは削除されないか?
距離が遠すぎるボールは選択されないか?
3個未満だと削除されないか?


これで、同じ種類のボールのみ削除 し、3個以上でのみ消える ようになりました!
次は、「スコア機能」を追加し、ボールを消した数に応じてスコアを加算する処理 を実装しましょう!




11. スコア機能の追加

ツムツム風のパズルゲームでは、ボールを消した数に応じてスコアを加算し、プレイヤーに達成感を与えることが重要です。
ここでは、スコアを表示するUIを作成し、消したボールの数 × 100 でスコアを加算し、新しいボールを補充する処理 を実装します。


① スコアを表示するUIを作成

まず、スコアを表示するテキストUI を作成します。

  1. ヒエラルキーウィンドウ(Hierarchy)で「右クリック」 →「UI」 →「Text – TextMeshPro」 を選択
  2. 名前を「ScoreText」に変更
  3. インスペクターウィンドウ(Inspector)で以下の設定を行う
    • Text: 「Score: 0」 に変更(初期スコア)
    • Font Size: 50(大きめに設定)
    • Alignment: 左揃え(もしくは中央揃え)
    • Position: 画面の左上(X: -400, Y: 250, Z: 0) に配置

※ UIが見えない場合は、「Canvas」の Render Mode を「Screen Space – Overlay」に設定してください。


② スコアを管理する変数を追加

GameSystem.cs に、スコアを管理する変数とUIの参照 を追加します。

GameSystem.cs に以下のコードを追加してください。

using TMPro;
using System.Collections.Generic;
using UnityEngine;

public class GameSystem : MonoBehaviour
{
    [SerializeField] BallGenerator ballGenerator = default; // ボール生成用
    [SerializeField] TextMeshProUGUI scoreText = default; // スコア表示用UI
    private int score = 0; // 現在のスコア

    private List<Ball> removeBalls = new List<Ball>(); // 削除対象のボールリスト
    private bool isDragging = false;
    private Ball currentDraggingBall;

    void Start()
    {
        // スコアの初期表示
        UpdateScore(0);
    }

    void UpdateScore(int points)
    {
        score += points; // スコアを加算
        scoreText.text = "Score: " + score; // UIを更新
    }
}

ポイント解説

  • score 変数 を作成し、スコアを管理
  • TextMeshProUGUI scoreText を追加 し、スコアUIを操作可能に
  • UpdateScore(int points) メソッドを追加 し、スコアを加算する処理を実装

③ ボールを消した数 × 100 でスコアを加算

次に、OnDragEnd() の処理を修正し、削除したボールの数 × 100 のスコアを加算 するようにします。

GameSystem.cs に以下のコードを修正してください。

void OnDragEnd()
{
    int removeCount = removeBalls.Count;

    // 3個以上なら削除&スコア加算
    if (removeCount >= 3)
    {
        for (int i = 0; i < removeCount; i++)
        {
            Destroy(removeBalls[i].gameObject);
        }

        // スコアを加算(1個につき100点)
        UpdateScore(removeCount * 100);

        // 消えた分だけ新しいボールを補充
        StartCoroutine(ballGenerator.Spawns(removeCount));
    }

    removeBalls.Clear();
    isDragging = false;
}

ポイント解説

  • 3個以上のボールが選択されたときのみ削除
  • 削除した数 × 100 のスコアを加算
  • 消えた分だけボールを補充するために Spawns(removeCount) を呼び出す

④ GameSystemにScoreTextをセット

Unityのインスペクターで設定を行います。

  1. ヒエラルキーウィンドウ(Hierarchy)で「GameSystem」を選択
  2. インスペクターウィンドウ(Inspector)で「Score Text」の項目を確認
  3. 「ScoreText」をドラッグ&ドロップしてセット

⑤ 動作確認

再生ボタン(▶)を押して、ゲームを実行!
画面内のボールを ドラッグして3個以上つなげると消え、スコアが加算されるか確認 しましょう。

3個以上つなげたらボールが消えるか?
消したボールの数 × 100 のスコアが加算されるか?
ボールが消えた分だけ新しいボールが補充されるか?
スコアがリアルタイムで更新されるか?


スコアUIをもっとオシャレにしたい? 現在はシンプルなスコア表示ですが、ゲームらしいカジュアルなデザインにしたい方におすすめ!
Casual Puzzle Game UI Pack を使えば、スコア表示やボタン、背景まで統一感のあるデザイン にできます。
デザイナーがいなくても、プロっぽいUIをすぐに適用可能!
👉 今すぐアセットストアでチェック!


これで、スコアが加算される仕組みボールが補充される処理 が完成しました!




12. まとめ

ここまでのステップで、Unityを使ってツムツム風のパズルゲームを作成する方法を学びました。
ボールの生成から削除、スコアの加算までの基本的な仕組み を実装できたので、
ゲームとしての形ができあがりましたね!


今回学んだことのおさらい

ボールを作成してPrefab化Rigidbody 2DCircleCollider 2D を追加)
壁を作成してボールが落ちないようにするEdgeCollider 2D を使用)
ボールが跳ね返るようにするPhysics Material 2DBounciness を調整)
一定間隔でボールをランダムに生成するBallGenerator を作成)
ボールの種類をランダムに設定する(5種類のスプライトを適用)
ボールにIDを設定し、種類ごとに識別Ball スクリプトを追加)
クリックしたボールを削除できるようにするGameSystem でドラッグ判定を実装)
同じ種類のボールのみ削除する処理(IDが一致し、近い距離にあるボールだけ選択)
3個以上つなげたら削除するルールの実装(ツムツム風のゲーム性を追加)
ボールを消したらスコアが加算される仕組みの実装(削除したボールの数 × 100)
消えたボールの数だけ新しく補充する処理を追加(プレイが継続できるようにする)

ここまでの処理で、ツムツム風の基本システムが完成しました!


今後の応用

今回のシンプルなシステムをベースに、さらにゲームを面白くするための応用要素を追加できます。

① エフェクトの追加

ボールが消えたときにエフェクトを表示すると、見た目がもっと楽しくなります!

  • Particle System を使って、キラキラしたエフェクト を追加する
  • SoundManager を作成して、ボールが消えるときに音を再生 する
  • Animation を適用して、消えるときにボールが弾けるアニメーション をつける

② 連鎖(コンボ)システム

連続でボールを消すと、スコアがどんどん増えるコンボシステムを作ると、プレイヤーのやる気が上がります!

  • 例:「3秒以内に次のボールを消すとコンボ継続!」
  • コンボが続くほど スコア倍率 が上がるようにする

③ タイムアタックモード

制限時間を設けて、「60秒でどれだけスコアを稼げるか?」といったルールを追加すると、ゲーム性が深まります!

  • Timer を作成し、時間が0になったらゲーム終了
  • 一定スコア以上でクリア! などの達成目標を設定

④ 特殊ボールの追加

通常のボールに加えて、特殊な効果を持つボール を追加すると、より戦略的なプレイが可能になります!

  • 爆弾ボール → 消すと 周囲のボールも一緒に消える
  • レインボーボールどの色ともつながる
  • 時間延長ボール → タイムアタックモードで 制限時間を増やす

⑤ ランキング機能

スコアを競えるようにすると、ゲームのリプレイ性が向上します!

  • ローカルランキング → 一番高いスコアを保存する
  • オンラインランキング → Firebaseなどを使って、他のプレイヤーとスコアを競えるようにする

さらに本格的なパズルゲームを作りたいなら? Unityには、すぐに使えるパズルゲームのテンプレート があります!
Puzzle Match Game Kit Bundle を使えば、マッチ3ゲームやツムツム風のパズルゲームを簡単に構築 できます。
エフェクトやアニメーションも含まれている ので、一から作るよりも 開発時間を大幅に短縮 できます!
👉 今すぐアセットストアでチェック!


今回作成したツムツム風パズルゲームは、シンプルなルールながら奥深いゲーム性 を持っています。
さらに工夫を加えることで、本格的なゲーム に進化させることもできます!

ぜひ、今回のプロジェクトを土台にして、自分なりのアレンジを加えてみてください!
より面白いゲームを作るために、エフェクト、スコア倍率、ランキング機能などを実装してみるのもオススメ です! 🎮✨




よくある質問(FAQ)

Q
ボールが跳ね返らないのですが、どうすればいいですか?
A

Physics Material 2D のBounciness(跳ね返り係数)が0になっていないか確認してください。また、ボールのRigidbody 2Dの設定で「Gravity Scale」が高すぎるとすぐ落ちてしまうため、調整してみてください。

Q
ボールの色をランダムに変える方法がわかりません。
A

BallGeneratorのスクリプトで、スプライトの配列を作成し、ball.GetComponent<SpriteRenderer>().sprite = ballSprite[ballID]; というコードを追加してください。

Q
クリックしたボールが消えないのですが?
A

OnDragEnd()removeBalls の中のオブジェクトをしっかり Destroy() しているか確認してください。また、Colliderが設定されていないとRaycastが当たらないので、CircleCollider 2Dが適用されているかチェックしましょう。

タイトルとURLをコピーしました