【Unity】スイカ風マージパズルゲームの作り方 その2 ~ スポナーを作る ~【2024年最新】

Unityを使ってスイカ風のマージパズルゲームを作成する方法を解説します。
前回の記事はこちらです。
【Unity】スイカ風マージパズルゲームの作り方 その1【2024年最新】 - なぎなぎブログ
前回は容器と駒(ボール)を作成しました。
今回は、駒を生成するスポナーの作成を行います。
目次
スポナーの作成
スポナーは、駒を生成するためのオブジェクトです。
スポナーも駒と同じように画像をインポートして、ゲームオブジェクトを作成します。
スポナー画像のインポート
まずは、スポナーの画像をインポートします。
Spritesフォルダに画像を入れて、Pixels Per Unitを設定します。
今回画像は 512x512 で作成していたので、Pixels Per Unitは 512 に設定します。

スポナーのゲームオブジェクト作成
次に、スポナーのゲームオブジェクトを作成します。
Spritesフォルダにあるスポナー画像をHierarchyにドラッグ&ドロップして、ゲームオブジェクトを作成します。
Spawnerは下記の設定しておきます
- Spawner
- 名前を Spawner に変更
- Position を (0, 4.2, 0) に設定
- Scale を (2, 2, 1) に設定

スポナーのスクリプト作成
スクリプトファイルの作成
いよいよスクリプトを書いていくので、まずスクリプトを保管するためのフォルダを作成します。
Assets > Create > Folder を選択し、名前を Scripts として作成します。
作成したスクリプトフォルダにスポナーのスクリプトを作成します。
Hierarchy にある Spawner を選択し、Inspector にある Add Component を選択し、New Script を選択し「Spawner」という名前でスクリプトを作成します。
作成したスクリプトは Scripts フォルダに移動させておいてください。
作成すると次の図のような状態になります。

スポナーを動かすスクリプトの記述
スポナースクリプトを記述します。
using UnityEngine;
public class Spawner : MonoBehaviour
{
// スポナーのY位置
private const float SpawnerImagePositionY = 4.2f;
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
}
// Update is called once per frame
void Update()
{
UpdateSpawnerPosition();
}
private void UpdateSpawnerPosition()
{
// マウスの座標を取得
var mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
var newPosition = new Vector2(mousePosition.x, SpawnerImagePositionY);
// x の範囲がボックスのサイズ内にあるかどうか
if (newPosition.x < -2.5f)
{
newPosition.x = -2.5f;
}
else if (newPosition.x > 2.5f)
{
newPosition.x = 2.5f;
}
transform.position = newPosition;
}
}

クリックして駒を生成する
駒を生成するために、スポナーをクリックした時に駒を生成するようにします。
まずは駒を生成するためのスクリプトを作成します。
駒生成のスクリプトをアタッチするオブジェクトの作成
駒のスクリプトをアタッチするオブジェクトを作成します。
Hierarchy を右クリックし、Create Empty を選択し、名前を KomaFactoryObject に変更します。
Inspector の Add Component から New Script を選択し、名前を KomaFactory にしてスクリプトを作成します。
作成したスクリプトは Scripts フォルダに移動させておいてください。
![駒のスクリプトをアタッチするオブジェクト]/imgs/how-to-create-unity-merge-puzzle-2-4.png)
駒のスクリプトの作成
駒のスクリプトを作成します。
Inspectorからスクリプトを作成していましたが、今回は先にスクリプトを作ってからアタッチします。
Scriptsフォルダで右クリックをし、Create > MonoBehaviour Script を選択し、名前を Koma にしてスクリプトを作成します。

ProjectウィンドウからPrefabsフォルダを開き、駒のプレファブを一括選択して、Inspectorから Add Component を選択し、Komaスクリプトをアタッチします。

駒のスクリプトの記述
駒がぶつかったときの処理などは、後で追加していきます。 一旦今は、駒の情報を持たせるためのプロパティだけを追加しておきます。
Assets/Scripts/Koma.cs に下記のように記述します。
using UnityEngine;
public class Koma : MonoBehaviour
{
// 駒の種類
public int Type { get; set; }
// マージ済みフラグ
public bool IsMerge { get; set; }
// 進化可能かどうか
public bool CanPromote { get; set; }
}
駒のスクリプトには、下記の情報を持たせるためのプロパティを追加しています。
- 駒の種類
- マージ済みフラグ
- 進化可能かどうか
駒生成スクリプトの記述
Assets/Scripts/KomaFactory.cs に下記のように記述します。
using System;
using UnityEngine;
public class KomaFactory : MonoBehaviour
{
// シーン内でシングルトンにする
public static KomaFactory Instance { get; private set; }
// 駒のPrefabのリスト
[SerializeField] private Koma[] komaPrefabList;
private void Awake()
{
if (Instance == null)
{
Instance = this;
}
else
{
Destroy(gameObject);
}
}
// 駒を生成する
public Koma CreateKoma(Vector2 position, int komaType)
{
if (komaType < 0 || komaType >= komaPrefabList.Length)
{
throw new ArgumentOutOfRangeException(nameof(komaType), komaType, "komaType is out of range");
}
// 駒を生成
var koma = Instantiate(komaPrefabList[komaType]);
koma.transform.position = position;
// 角度をランダムにする
koma.transform.rotation = Quaternion.Euler(0, 0, UnityEngine.Random.Range(0, 360));
// 駒の種類を設定
koma.Type = komaType;
// 進化可能かどうかを設定
koma.CanPromote = komaType + 1 < komaPrefabList.Length;
return koma;
}
// ランダムな位置に駒を生成する
public Koma CreateRandomKoma(Vector2 position, int maxKomaType)
{
var komaType = UnityEngine.Random.Range(0, maxKomaType);
return CreateKoma(position, komaType);
}
}
KomaFactoryクラスは、シーン内でシングルトンになるようにしています。
CreateKomaメソッドは、引数で渡された位置に、指定された種類の駒を生成します。
CreateRandomKomaメソッドは、引数で渡された位置に、ランダムな種類の駒を生成します。
これで、例えば別のスクリプトから、 KomaFactory.Instance.CreateRandomKoma(new Vector2(0,0), 3);
のように記述することで、任意の位置に駒を生成することができます。
駒はPrefabを使って生成するので、komaPrefabListに生成対象となるPrefabを設定しておきます。
Inspectorから、KomaFactoryObjectを選択し、Inspectorにある Koma Factory (Script) の Koma Prefab List に、駒のPrefabを設定します。

スポナーでクリックした時に駒を生成するように修正
クリックした時に駒落とすようにスクリプトを修正します
Assets/Scripts/Spawner.cs に下記のように記述します。
using System.Collections;
using UnityEngine;
public class Spawner : MonoBehaviour
{
// スポナーのY位置
private const float SpawnerImagePositionY = 4.2f;
// 現在持っている駒のY位置
private const float CurrentKomaPositionY = 3.6f;
// スポナーが現在持っている駒
private Koma _currentKoma;
void Start()
{
// 起動時に最初に持っている駒を生成
var koma = KomaFactory.Instance.CreateRandomKoma(new Vector2(transform.position.x, CurrentKomaPositionY), 4);
// 現在持っている駒に設定
_currentKoma = koma;
// 重力を0に設定
_currentKoma.GetComponent<Rigidbody2D>().gravityScale = 0;
}
void Update()
{
UpdateSpawnerPosition();
if (Input.GetMouseButtonDown(0) && _currentKoma)
{
// 現在持っている駒を落とす
DropKoma();
// 次落とす駒を生成
StartCoroutine(GenerateNextKoma(4));
}
}
private void UpdateSpawnerPosition()
{
// マウスの座標を取得
var mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
var newPosition = new Vector2(mousePosition.x, SpawnerImagePositionY);
// x の範囲がボックスのサイズ内にあるかどうか
if (newPosition.x < -2.5f)
{
newPosition.x = -2.5f;
}
else if (newPosition.x > 2.5f)
{
newPosition.x = 2.5f;
}
// スポナーの位置を更新
transform.position = newPosition;
// スポナーが持っている駒の位置を更新
if (_currentKoma)
{
_currentKoma.transform.position = new Vector2(newPosition.x, CurrentKomaPositionY);
}
}
private void DropKoma()
{
if (!_currentKoma) return;
// 重力を元に戻して落とす
_currentKoma.GetComponent<Rigidbody2D>().gravityScale = 1;
// 落とすとスポナーは駒を持たない状態になるので、スポナーが持っている駒をnullに設定
_currentKoma = null;
}
private IEnumerator GenerateNextKoma(int maxKomaType)
{
// 1秒待つ
yield return new WaitForSeconds(1.0f);
// 駒を生成
var koma = KomaFactory.Instance.CreateRandomKoma(new Vector2(transform.position.x, CurrentKomaPositionY), maxKomaType);
// 重力を0に設定
koma.GetComponent<Rigidbody2D>().gravityScale = 0;
// 現在スポナーが持っている駒に設定
_currentKoma = koma;
}
}
ここまでのスクリプトを記述することで、クリックすると駒が落ちるようになります。

レイヤー位置の設定
うまい感じに動いていますが、スポナーと駒が重なっているときに、駒が手前に表示されるようにレイヤー位置を設定します。
下記のようにそれぞれのオブジェクトのレイヤー位置を設定します。
- Box->Field
- Order in Layer: -50
- Spawner
- Order in Layer: -20
- Prefabs->各駒
- Order in Layer: -10

これできれいに表示されるようになりました。

まとめ
今回は、スポナーを作成し、クリックした時に駒を生成するようにしました。
次回は、駒がぶつかった時の処理を追加していきます。