【Unity】ピースを増やしてパズルにする

2019/7/15更新

暫くサボっていました。(;^_^A
ボチボチ更新していこうと思います。

前回、ピースを位置にハメる動きまで出来たので、
ピースを増やしたらどうなるかを考えてみます。


実装するのに必要な物は

・ピースの数だけ座標変数を増やす
・各ピースが所定の位置でハマるようにする

でしょうか。

座標変数は配列で追加するとして、
ジャグ配列や2次元配列が妥当なんでしょうが、
勉強不足で使えません(^^ゞ

なので普通の配列で組んでみます。

前回のコードに

private int[] PiecePosX = { -300, -150, 0, 150, 300,
-300, -150, 0, 150, 300,
-300, -150, 0, 150, 300,
-300, -150, 0, 150, 300,
-300, -150, 0, 150, 300};

private int[] PiesePosY = { 300, 300, 300, 300, 300,
150, 150, 150, 150, 150,
0,0,0,0,0,
-150,-150,-150,-150,-150,
-300,-300,-300,-300,-300};

座標用の変数を追加します。
これで座標の用意ができました。

続いてエディター上に座標に合わせたピースのポジションベースを
用意します。

今回は、座標変数を見て貰えると分かるんですが、
-300~300としています。

-300にピースを乗せるとピースのサイズを150で取っているので、
実際の外枠は75ズレる計算になります。

なので、ポジションベースの大きさは600の幅に上下左右75大きい
750×750のイラストを用意します。
DragTest4.jpg座標変数と対応するベースが用意できたので、
ピースが各ポジションでハマるようにスクリプトを修正します。

まずピースを各ポジションにハメるためには、
・どのピースか?
・どのポジションか?

これが分からないとハマらないので、
ピースにナンバーを振ってポジションと対応させます。
変数はPieceNoとでもしておきます。

この変数を元にポジションの割り出しを行います。

ポジションが割り出せたらポジションからのオフセットを計算しないとダメなので、
オフセット用の変数を用意します。

最終的にできたのがこちら

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class DragManager : MonoBehaviour {


//各ピースのナンバー
public int PieceNo;

//ピースのポジション用変数
private int[] PiecePosX = { -300, -150, 0, 150, 300,
-300, -150, 0, 150, 300,
-300, -150, 0, 150, 300,
-300, -150, 0, 150, 300,
-300, -150, 0, 150, 300};

private int[] PiesePosY = { 300, 300, 300, 300, 300,
150, 150, 150, 150, 150,
0,0,0,0,0,
-150,-150,-150,-150,-150,
-300,-300,-300,-300,-300};

// Use this for initialization
void Start () {

}

// Update is called once per frame
void Update () {

}

//ドラッグ操作
public void OnDrag()
{
Vector3 TapPos = Input.mousePosition;
TapPos.z = 10f;
transform.position = Camera.main.ScreenToWorldPoint(TapPos);
}

//ドロップ時の位置判定と挙動
public void OnEndDrag()
{
//ドロップ時のピースのxy座標を取得
float objx = this.transform.localPosition.x;
float objy = this.transform.localPosition.y;

//ポジションからのオフセット
float leftx = PiecePosX[PieceNo] - 60;
float rightx = PiecePosX[PieceNo] + 60;
float upy = PiesePosY[PieceNo] + 60;
float downy = PiesePosY[PieceNo] - 60;

//ポジションからオフセット内にドロップされたかの判定
if (leftx <= objx && objx<=rightx)
{
if (upy >= objy && objy >= downy)
{
this.transform.localPosition = new Vector3(PiecePosX[PieceNo], PiesePosY[PieceNo], 0);
}
}
}
}

移動メソッドはPieceNoを元に配列から座標を呼び出しています。

ここまでできればエディターでピースを増やします。
ピースが増えるのでピースをまとめる空のオブジェクトを追加して、
この中でピースをDuplicateします。
DragTest5.jpg
空のオブジェクトはPieceParentとしておきます。

続いて、各ピースのPieceNoを対応する0~24のナンバーに書き替えます。
DragTest6.jpg
これで準備ができました。

ピースの初期配置は適当にバラバラにしておいてプレイでっす。

ピースの動きは問題ないのですが、
ピース同士が被るとレイヤーの低いピースが隠れてしまって、
ピースがどこにあるか分からない状態でっす。(ToT )( ToT) ウルウル

3Dならz座標で前に出す事もできるのでしょうが、
2Dはそうもいかないでっす。

ここである本に書いてあったSetSiblingIndexを試してみます。

これはレイヤーの順番を操作するコマンドで、
子オブジェクトのレイヤーを変える事ができるようです。

数値が大きいほど前にくるようになるそうです。

まず、ピースのレイヤーを変える位置は
・ピースを掴んだ時に最前面にする
・ピースをポジションにハメた時、最背面にする

こんな感じでしょうか。

スクリプトに加えてみます。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class DragManager : MonoBehaviour {


//各ピースのナンバー
public int PieceNo;

//ピースのポジション用変数
private int[] PiecePosX = { -300, -150, 0, 150, 300,
-300, -150, 0, 150, 300,
-300, -150, 0, 150, 300,
-300, -150, 0, 150, 300,
-300, -150, 0, 150, 300};

private int[] PiesePosY = { 300, 300, 300, 300, 300,
150, 150, 150, 150, 150,
0,0,0,0,0,
-150,-150,-150,-150,-150,
-300,-300,-300,-300,-300};

// Use this for initialization
void Start () {

}

// Update is called once per frame
void Update () {

}

//ドラッグ操作
public void OnDrag()
{
this.transform.SetSiblingIndex(99);
Vector3 TapPos = Input.mousePosition;
TapPos.z = 10f;
transform.position = Camera.main.ScreenToWorldPoint(TapPos);
}

//ドロップ時の位置判定と挙動
public void OnEndDrag()
{
//ドロップ時のピースのxy座標を取得
float objx = this.transform.localPosition.x;
float objy = this.transform.localPosition.y;

//ポジションからのオフセット
float leftx = PiecePosX[PieceNo] - 60;
float rightx = PiecePosX[PieceNo] + 60;
float upy = PiesePosY[PieceNo] + 60;
float downy = PiesePosY[PieceNo] - 60;

//ポジションからオフセット内にドロップされたかの判定
if (leftx <= objx && objx<=rightx)
{
if (upy >= objy && objy >= downy)
{
this.transform.SetSiblingIndex(0);
this.transform.localPosition = new Vector3(PiecePosX[PieceNo], PiesePosY[PieceNo], 0);
}
}
}
}

OnDragの1行目とOnEndDragの移動コマンドの前に入れてみました。

実際に操作してみます。

ピースの色が同じなので分かりにくいo(ToT)o ダー

でも、掴んだピースが最前面にきて、
ポジションにハマったら最背面になるようになりました。

これで操作的には問題ないかと思います。

後は全てのピースが所定位置にハマったか判定できれば、
一応ジグソーの最低限の操作はできそうです。

ほんとはピース同士の結合までやりたいのですが、
勉強不足で対応できてません(T^T) ヒック
はたして完成するのかな~?(・_・。)) マイッタナァ

この記事へのコメント