Unityでジグソーパズルゲームを作りたい。
画像を分割して、ドラッグ&ドロップで配置する仕組みを実装したい。
でも、画像処理や座標計算でつまずいてしまう。
Unityなら、Texture2Dの分割処理とドラッグ&ドロップAPIを組み合わせることで、ジグソーパズルを実装できます。
この記事では、画像の分割からスナップ判定まで、実装の流れを解説していきます。
- Texture2Dを使った画像の分割処理とReadPixelsの活用
- 分割した画像をSpriteに変換してPrefab化する方法
- OnMouseDragを使ったドラッグ&ドロップの実装
- 距離計算による正しい位置へのスナップ判定
- Dictionaryを使った完成判定の管理方法
\パズルの次は!頭を使うゲームを自分で作ってみよう/
最初の1本目に最適
Unity タワーディフェンス
ゲームの作り方講座
敵の侵攻を防ぐ配置戦略がパズル脳に直結!全10回のコンパクトな構成で、初心者でもゲーム開発の全体像をつかめます。
スマホアプリを作りたい方へ
Unity 放置インフレ型
クリッカーゲームの作り方講座
数値が積み上がる快感はパズル好きに刺さる!スマホ対応・リリースレベルの放置系クリッカーを全12回で完成させられます。
思考系ゲームに挑戦
Unity ノンフィールドRPG
+スレスパ風JRPG講座
カードを選んで戦略を組み立てるデッキ構築はパズル脳との相性抜群。Unity6対応・スマホ化対応の最新カリキュラムで挑戦できます。
あなたのオリジナルゲーム、今年こそ完成させませんか?
RPG・アクション・ホラー…Unityで本格ゲームを作りたい人のための学習サイトです。
実際に完成するゲームを題材に、
ソースコード・素材・プロジェクト一式をすべて公開。
仕事や学校の合間の1〜2時間でも、
「写経→改造」で自分のゲームまで作りきれる環境です。
Unityジグソーパズルの基本構造

Unityのジグソーパズルは、4つの要素で構成されています。
画像を分割してピースを作る処理、ドラッグでピースを移動させる処理、正しい位置へのスナップ判定、全ピースの配置状態をチェックする完成判定。
これらの要素が組み合わさることで、ゲームとして成立するんです。
まずは、それぞれの要素がどのような役割を担っているか、理解しておきましょう。
| 要素 | 役割 | 実装方法 |
|---|---|---|
| 画像分割 | 元画像をグリッド状に分割 | Texture2D.ReadPixels |
| Sprite変換 | 分割した画像をSprite化 | Sprite.Create |
| ドラッグ処理 | マウスでピースを移動 | OnMouseDragイベント |
| スナップ判定 | 正しい位置に近づいたら配置 | 距離計算と閾値判定 |
この4つの要素を順番に実装していけば、ジグソーパズルが完成します。
それぞれの実装方法を、詳しく見ていきましょう。
Texture2Dで画像を読み込む

画像を分割するには、まずTexture2Dとして読み込む必要があります。
Unityでは、画像ファイルをインポートすると自動的にTexture2Dとして扱われます。
ただし、分割処理を行うには、読み取り可能な設定にする必要があります。
Inspectorで「Read/Write Enabled」にチェックを入れておきましょう。
コードから読み込む場合も、同様の設定が必要です。
- Read/Write Enabledを有効にする
- Filter ModeはPoint推奨(ピクセルパーフェクトの場合)
- Formatは適切な形式を選択(RGBA32など)
設定が完了したら、分割処理に進みます。
ReadPixelsで画像を分割する

画像を分割するには、ReadPixelsメソッドを使います。
ReadPixelsは、Texture2Dの特定範囲のピクセルデータを読み取るメソッド。
このメソッドを使って、元画像の一部分だけを新しいTexture2Dにコピーします。
分割数を決めたら、各ピースの範囲を計算。
3×3のグリッドなら、9つのピースに分割されます。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
public class PuzzleGenerator : MonoBehaviour { public Texture2D sourceTexture; public int gridWidth = 3; public int gridHeight = 3; List<Texture2D> pieceTextures = new List<Texture2D>(); void Start() { CreatePuzzlePieces(); } void CreatePuzzlePieces() { int pieceWidth = sourceTexture.width / gridWidth; int pieceHeight = sourceTexture.height / gridHeight; for (int y = 0; y < gridHeight; y++) { for (int x = 0; x < gridWidth; x++) { // 新しいTexture2Dを作成 Texture2D pieceTexture = new Texture2D(pieceWidth, pieceHeight); // 元画像の一部分を読み取る int sourceX = x * pieceWidth; int sourceY = y * pieceHeight; Color[] pixels = sourceTexture.GetPixels( sourceX, sourceY, pieceWidth, pieceHeight ); pieceTexture.SetPixels(pixels); pieceTexture.Apply(); pieceTextures.Add(pieceTexture); } } } } |
GetPixelsメソッドで、指定範囲のピクセルデータを取得。
取得したピクセルデータを、新しいTexture2DにSetPixelsで設定。
最後にApplyを呼び出して、変更を反映させます。
この処理を全ピース分繰り返せば、画像が分割されます。
Spriteに変換してPrefab化する

分割したTexture2Dは、Sprite.CreateでSpriteに変換します。
Spriteは、GameObjectに表示できる形式。
変換後は、GameObjectにSpriteRendererを追加して表示します。
最初の1つを作成したら、Prefab化しておくと便利。
他のピースも、同じPrefabから生成できます。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
void CreateSpriteFromTexture(Texture2D texture) { // Spriteに変換 Sprite sprite = Sprite.Create( texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f), // ピボット位置(中心) 100f // ピクセル単位 ); // GameObjectを作成 GameObject pieceObject = new GameObject("PuzzlePiece"); SpriteRenderer renderer = pieceObject.AddComponent<SpriteRenderer>(); renderer.sprite = sprite; // Colliderを追加(ドラッグ判定用) BoxCollider2D collider = pieceObject.AddComponent<BoxCollider2D>(); // Prefabとして保存(エディタでのみ動作) #if UNITY_EDITOR UnityEditor.PrefabUtility.SaveAsPrefabAsset(pieceObject, "Assets/PuzzlePiece.prefab"); #endif } |
Sprite.Createのピボット位置は、中心(0.5, 0.5)が一般的。
ピボット位置は、回転や拡大縮小の基準点になります。
ドラッグ判定のために、Collider2Dも追加しておきましょう。
OnMouseDragでドラッグ処理を実装する

ピースをドラッグするには、OnMouseDragメソッドを使います。
OnMouseDragは、マウスボタンを押したまま移動している間、毎フレーム呼び出されるイベント。
このメソッド内で、マウス位置にピースを追従させます。
マウス位置はスクリーン座標なので、ワールド座標に変換が必要。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
public class PuzzlePiece : MonoBehaviour { private bool isDragging = false; private Vector3 offset; void OnMouseDown() { isDragging = true; Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition); mousePos.z = 0; offset = transform.position - mousePos; // 前面に表示 transform.SetAsLastSibling(); } void OnMouseDrag() { if (isDragging) { Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition); mousePos.z = 0; transform.position = mousePos + offset; } } void OnMouseUp() { isDragging = false; CheckSnap(); } } |
OnMouseDownで、マウスとピースの相対位置を記録。
OnMouseDragで、その相対位置を保ったままピースを移動。
OnMouseUpでドラッグ終了とし、スナップ判定を実行します。

距離計算でスナップ判定を実装する

ピースが正しい位置に近づいたら、自動的に配置する処理を実装しましょう。
スナップ判定は、距離計算で実現します。
ピースの現在位置と目標位置の距離を計算し、閾値以内なら配置。
Vector3.Distanceを使えば、簡単に距離を計算できます。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
public class PuzzlePiece : MonoBehaviour { public Vector2 targetPosition; public float snapThreshold = 0.5f; private bool isPlaced = false; void CheckSnap() { if (isPlaced) return; float distance = Vector3.Distance(transform.position, targetPosition); if (distance < snapThreshold) { // スナップ成功 transform.position = targetPosition; isPlaced = true; // 視覚的フィードバック GetComponent<SpriteRenderer>().color = Color.green; // 完成判定をチェック PuzzleManager.Instance.CheckCompletion(); } } } |
snapThresholdの値を調整すれば、スナップの感度を変更できます。
値が小さいと、ピッタリ合わせないとスナップしないため、難易度が上がります。
値が大きいと、少し近づけるだけでスナップするため、初心者向けになります。
スナップ成功時は、完成判定もチェックしましょう。
Dictionaryで完成判定を管理する

全ピースの配置状態を管理するには、Dictionaryを使います。
Dictionaryは、キーと値のペアを管理するコレクション。
ピースのIDをキーに、配置状態を値として保存。
全てのピースが配置済みかチェックする処理も、簡単に実装できます。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
public class PuzzleManager : MonoBehaviour { public static PuzzleManager Instance; private Dictionary<int, bool> piecePlacement = new Dictionary<int, bool>(); private int totalPieces; void Awake() { Instance = this; } void Start() { // 全ピースを登録 PuzzlePiece[] pieces = FindObjectsOfType<PuzzlePiece>(); totalPieces = pieces.Length; foreach (var piece in pieces) { piecePlacement[piece.pieceID] = false; } } public void OnPiecePlaced(int pieceID) { piecePlacement[pieceID] = true; CheckCompletion(); } void CheckCompletion() { bool allPlaced = true; foreach (var kvp in piecePlacement) { if (!kvp.Value) { allPlaced = false; break; } } if (allPlaced) { Debug.Log("パズル完成!"); OnPuzzleComplete(); } } void OnPuzzleComplete() { // 完成時の処理 } } |
Dictionaryを使えば、各ピースの状態を効率的に管理できます。
配列を使う方法もありますが、ピースのIDが連番でない場合、Dictionaryの方が柔軟です。
完成判定は、ピースが配置される度に実行します。
実装手順の全体像

ここまで説明した内容を、実装手順として整理しましょう。
- STEP1画像の準備
ジグソーパズルに使う画像を準備し、Unityにインポートします。Texture2Dの設定で「Read/Write Enabled」を有効にしておきましょう。
- STEP2画像の分割処理
ReadPixelsやGetPixelsを使って、元画像をグリッド状に分割します。各ピースを新しいTexture2Dとして作成します。
- STEP3Sprite変換とPrefab化
分割したTexture2DをSpriteに変換し、GameObjectにSpriteRendererを追加します。最初の1つをPrefab化しておきます。
- STEP4ドラッグ処理の実装
OnMouseDragを使って、ピースをマウスでドラッグできるようにします。相対位置を記録することで、自然な操作感を実現します。
- STEP5スナップ判定の実装
距離計算を使って、ピースが正しい位置に近づいた時に自動配置するスナップ機能を実装します。閾値を調整して難易度を変更できます。
- STEP6完成判定の実装
Dictionaryを使って、全ピースの配置状態を管理します。全て配置されたら、完成イベントを実行します。
この順番で実装すれば、ジグソーパズルが完成します。
順番を間違えると、後で大幅な修正が必要になるので注意。
画像処理と座標変換のポイント

ジグソーパズルの実装では、画像処理と座標変換が重要。
ReadPixelsやGetPixelsを使う際、座標系に注意が必要です。
Unityの座標系は、左下が原点(0, 0)ですが、画像データは左上が原点の場合もあります。
座標の向きを間違えると、ピースが上下反転してしまうことも。
|
1 2 3 4 |
// 座標変換の例 int sourceY = (gridHeight - 1 - y) * pieceHeight; // Y座標を反転 Color[] pixels = sourceTexture.GetPixels(sourceX, sourceY, pieceWidth, pieceHeight); |
座標系の違いを理解しておけば、トラブルを回避できます。
デバッグ時は、分割した画像が正しく表示されているか確認しましょう。
当たり判定の精度調整

スナップ判定の精度は、ゲームの難易度に直結します。
閾値を小さくすると難しくなり、大きくすると簡単になります。
ただし、大きすぎると、意図しない位置にもスナップしてしまうので注意。
| 閾値 | 難易度 | 特徴 |
|---|---|---|
| 0.1〜0.3 | 高 | ピッタリ合わせないとスナップしない |
| 0.4〜0.6 | 中 | 適度な感度で、遊びやすい |
| 0.7〜1.0 | 低 | 少し近づけるだけでスナップする |
難易度調整は、テストプレイを繰り返して最適な値を見つけましょう。
ユーザー設定で変更できるようにするのもアリです。
デバッグ用の枠線表示

開発中は、ピースの配置位置を視覚的に確認できると便利。
GizmosやLineRendererを使って、目標位置に枠線を表示しましょう。
これにより、スナップ判定が正しく動作しているか確認できます。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
void OnDrawGizmos() { // 目標位置に枠線を表示 Gizmos.color = Color.yellow; Vector3 size = new Vector3(1f, 1f, 0.1f); Gizmos.DrawWireCube(targetPosition, size); // 現在位置と目標位置を線で結ぶ if (!isPlaced) { Gizmos.color = Color.red; Gizmos.DrawLine(transform.position, targetPosition); } } |
Gizmosを使えば、エディタ上で視覚的にデバッグできます。
本番ビルドでは表示されないので、開発中は積極的に活用しましょう。
- Texture2DのRead/Write Enabledを有効にせず、ReadPixelsが使えない
- 座標系を間違えて、ピースが上下反転してしまう
- スナップの閾値が適切でなく、難易度が極端になる
これらのポイントに注意すれば、スムーズに実装できます。
パズルゲームが好きなら!頭を使うゲームを自分で作る楽しさを体験しよう
パズルゲームが好きな人は、ゲームの仕組みや戦略を考えるのが得意です。その思考力はゲーム開発にそのまま活かせます。配置・戦略・ロジック設計が楽しめる講座を紹介します。
Unity タワーディフェンスゲームの作り方講座【全10回!配置戦略が楽しい初心者最初の1本!】

- 敵の侵攻ルートを読んで砲台を配置する戦略性がパズル脳に直結
- 全10回のコンパクトな構成で初心者でもゲーム開発の全体像をつかめる
- 敵AI・ステージ設計・アイテムショップ・レベルデザインまで習得
- 丁寧な解説とソースコード付きでサクサク進められる
Unity タワーディフェンスゲームの作り方講座は、敵の侵攻を防ぐために砲台をどこに配置するかを考える戦略性がパズル好きの思考回路と直結するジャンルです。
全10回というコンパクトな構成で、敵AI・ステージ設計・アイテムショップ・レベルデザインまで習得できます。「最初の1本目」として最もおすすめできる入門講座です。
パズルを解く感覚でゲームを作る第一歩を踏み出したい人に、自信を持っておすすめできる一本です。
全10回・配置戦略が楽しいタワーディフェンスをゼロから作る
まず1本完成させてゲーム開発の楽しさを体験しよう
→ タワーディフェンスゲームの作り方講座を見てみる
コンパクトな10回で完成!ゲーム開発の全体像を一気につかもう!
Unity 放置インフレ型クリッカーゲームの作り方講座【全12回!スマホアプリとしてリリースできるレベルのゲームを作れる!】

- 数値が積み上がる快感と段階的な要素解放がパズル好きに刺さる
- スマホ対応・リリースレベルのクリッカーゲームを全12回で完成
- ScriptableObjectやInterfaceなど実践で使えるUnity中級スキルも習得
- セーブ・ロード機能・サウンド実装まで本格的な構成
Unity 放置インフレ型クリッカーゲームの作り方講座は、数値が積み上がる快感・段階的な要素の解放・最適化の楽しさがパズルゲームと相性抜群のジャンルです。
単純なカウンターゲームではなく、本格的な放置系クリッカーゲームをスマホ対応でリリースレベルまで作り上げます。講座専用素材付きで、ダウンロードしてすぐに開発をスタートできます。
「自分で作ったアプリをスマホでプレイしたい!」という人の夢を全12回で叶えられる講座です。
スマホ対応・リリースレベルの放置系クリッカーを完成させる
数値が積み上がる快感をゲームで自分の手で作り上げよう
→ クリッカーゲームの作り方講座を見てみる
スマホで動く自分だけのクリッカーゲームを今すぐ作り始めよう!
Unity ノンフィールドRPG+スレスパ風JRPG講座【Unity6対応!カード戦略×JRPGで思考系ゲームを作れる!】

- カードを選んで戦略を組み立てるデッキ構築がパズル脳と相性抜群
- Unity6対応・スマホ化対応で最新環境のゲーム開発が学べる
- Slay the Spire風のゲームロジック設計を楽しみながら習得
- ノンフィールドRPGとデッキ構築JRPGの2つを合わせて学ぶのがおすすめ
Unity ノンフィールドRPGの作り方講座+Slay the Spire風デッキ構築JRPGの作り方講座は、手札から最適なカードを選んで戦略を組み立てるデッキ構築システムを実装できる講座です。
「どのカードを引いてどう組み合わせるか」を考える思考プロセスはパズルゲームと同じ脳の使い方。Unity6対応・スマホ化対応の最新カリキュラムで、思考系ゲームの設計を楽しみながら学べます。
タワーディフェンス・クリッカーで開発に慣れたら、次のステップとして挑戦したい一本です。
カード戦略×JRPGで思考系ゲームの設計を学ぶ
トレンドのデッキ構築システムをスマホ向けに実装しよう
→ スレスパ風デッキ構築JRPG講座を見てみる
パズル脳を活かしたゲーム設計で、一歩上のゲーム開発スキルを身につけよう!
まとめ

この記事では、Unityでジグソーパズルゲームを作る方法について解説しました。
- Texture2DのReadPixelsやGetPixelsを使って、元画像を分割する
- 分割したTexture2DをSpriteに変換し、Prefab化して管理する
- OnMouseDragでドラッグ処理を実装し、相対位置を記録することで自然な操作感を実現する
- 距離計算でスナップ判定を実装し、閾値を調整して難易度を変更する
- Dictionaryで全ピースの配置状態を管理し、完成判定を実装する
まずは簡単な分割数から始めて、動作を確認しながら機能を追加していきましょう。
画像処理と座標変換の考え方を覚えておけば、他のパズルゲームでも応用できます。
さらに高度な機能に挑戦する時は、専門の教材を活用するのがおすすめです。
あなたのオリジナルゲーム、今年こそ完成させませんか?
RPG・アクション・ホラー…Unityで本格ゲームを作りたい人のための学習サイトです。
実際に完成するゲームを題材に、
ソースコード・素材・プロジェクト一式をすべて公開。
仕事や学校の合間の1〜2時間でも、
「写経→改造」で自分のゲームまで作りきれる環境です。




コメント