質問の回答にはなってないお遊びコードの修正です。
修正前のコードより、落ちる処理と連鎖も作ってみた。
軽くコメントも入れといた。
Dictionaryは失敗だった気もする。面倒だった。
gif入れてる回答とか分かりやすいから入れたかったけど、そういえばgif作った事なかった。全くわからん。
コピペで動作します。
処理が遅いとかコードが汚いとか、変数名がおかしいとか、つっこみどころは山ほどありそうですが、その他いろいろ気にしなければこんな感じで特に難しい事はせずに作れますよって程度に思ってもらえれば。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
// puyoクラスにしてみた
public class Puyo
{
public GameObject gameObject;
public int color;
public bool searched = false;
public int connectedValue = 0;
public int chainId = 0;
public Puyo(int color, GameObject gameObject)
{
this.color = color;
this.gameObject = gameObject;
}
}
public class Scripts : MonoBehaviour
{
// お遊び
int[,] twentythree = new int [,] {
{ 0,0,0,0,1,3 },
{ 0,0,0,0,1,1 },
{ 0,3,0,0,4,1 },
{ 2,4,4,4,3,3 },
{ 3,3,1,5,2,3 },
{ 3,2,2,1,5,1 },
{ 2,1,1,5,2,2 },
{ 4,5,4,5,3,2 },
{ 4,4,3,3,1,1 },
{ 1,5,1,2,3,1 },
{ 2,5,5,1,2,5 },
{ 3,1,1,4,2,2 },
{ 4,4,4,5,5,5 },
{ 3,3,1,2,1,4 },
{ 3,4,3,2,1,4 },
{ 2,2,4,3,2,1 },
{ 2,1,4,3,2,1 },
{ 1,1,4,3,4,4 },
};
// データ管理用、正直この方法は失敗したと思います。面倒だった
Dictionary<Vector2Int, Puyo> data = new Dictionary<Vector2Int, Puyo>();
private bool falled = true;
// 動きを確認出来るようコルーチンにして描画処理を走らせる(コードを減らす為)
IEnumerator Start()
{
// puyoの位置決定
for (int y = 0; y < 18; y++)
{
for (int x = 0; x < 6; x++)
{
// int color = Random.Range(0, 6);
int color = twentythree[17 - y, x];
if (color == 0) continue;
var obj = GameObject.CreatePrimitive(PrimitiveType.Sphere);
data.Add(new Vector2Int(x, y), new Puyo(color, obj));
obj.transform.position = new Vector2(x, y);
if (color == 1) obj.GetComponent<Renderer>().material.color = Color.red;
if (color == 2) obj.GetComponent<Renderer>().material.color = Color.blue;
if (color == 3) obj.GetComponent<Renderer>().material.color = Color.yellow;
if (color == 4) obj.GetComponent<Renderer>().material.color = Color.green;
if (color == 5) obj.GetComponent<Renderer>().material.color = Color.cyan;
}
}
// デバッグ表示用の変数
int chainCount = 0;
int totalCount = 0;
// 連鎖のループ
while (falled)
{
FallStart();
yield return new WaitForFixedUpdate();
SearchStart();
int id = data.Max(_ => _.Value.chainId);
yield return new WaitForSeconds(1.0f);
if (id > 0) chainCount++;
int count = 0;
// 同時消しを別々に処理してみた、id個の同時消しが存在する
for (int i = 1; i <= id; i++)
{
var eraseData = data.Where(_ => _.Value.chainId == i);
foreach (var puyo in eraseData)
{
Destroy(puyo.Value.gameObject);
count++;
}
foreach (var erasePosition in eraseData.ToList())
{
data.Remove(erasePosition.Key);
}
yield return new WaitForSeconds(0.2f);
}
// 処理終了でクラスに持たせてしまった変数の初期化、これは正直無駄すぎる気がする
foreach (var puyo in data)
{
puyo.Value.searched = false;
puyo.Value.connectedValue = 0;
}
if (id == 0) continue;
Debug.Log($"{chainCount}連鎖目、{id}箇所で同時消し、{count}個のpuyoが消えました");
totalCount += count;
}
Debug.Log($"結果、{chainCount} 連鎖、{totalCount}のpuyoが消えました");
}
// 上下左右を調べる、currentPositionと同じ色なら位置を再設定して再起、connectedValue++して繋がっている個数を設定
// 再設定された位置はここで検索済みとなる
void SearchPosition(Vector2Int currentPosition, Vector2Int searchPosition, List<Vector2Int> positions)
{
foreach (var position in new Vector2Int[] { Vector2Int.up, Vector2Int.down, Vector2Int.left, Vector2Int.right })
{
if (!data.ContainsKey(searchPosition + position)) continue;
if (data[currentPosition].color == data[searchPosition + position].color && !data[searchPosition + position].searched)
{
data[currentPosition].connectedValue++;
data[searchPosition + position].searched = true;
positions.Add(searchPosition + position);
SearchPosition(currentPosition, searchPosition + position, positions);
}
}
}
// 繋がりを検索する
void SearchStart()
{
int id = 0;
for (int y = 0; y < 18; y++)
{
for (int x = 0; x < 6; x++)
{
var key = new Vector2Int(x, y);
List<Vector2Int> connectedPositions = new List<Vector2Int>();
if (!data.ContainsKey(key)) continue;
if (data[key].searched) continue;
SearchPosition(key, key, connectedPositions);
data[key].searched = true;
if (connectedPositions.Count > 3) id++;
foreach (var position in connectedPositions)
{
data[position].connectedValue = data[key].connectedValue;
if (data[key].connectedValue > 3)
{
data[position].chainId = id;
falled = true;
}
}
}
}
}
// 全ての位置情報を回す
void FallStart()
{
falled = false;
for (int y = 0; y < 18; y++)
{
for (int x = 0; x < 6; x++)
{
if (data.ContainsKey(new Vector2Int(x, y)))
{
Fall(new Vector2Int(x, y));
}
}
}
}
// 下方向、最下段、もしくは下にpuyoが無くなるまで回す
void Fall(Vector2Int position)
{
var falledPosition = new Vector2Int(position.x, position.y - 1);
if (position.y < 1) return;
if (!data.ContainsKey(falledPosition))
{
data.Add(falledPosition, data[position]);
data[falledPosition].gameObject.transform.position = new Vector3(falledPosition.x, falledPosition.y, 0);
data.Remove(position);
falled = true;
Fall(falledPosition);
}
}
}