【Unity】テトリス作り方流れ

__【素材インポート】__
Tetorisプロジェクト(2D)作成
project > Spritesフォルダ作成、素材(block,enpty)インポート
素材のinspector > PixsilPerUnit 256に設定

__【カメラ、背景設定】__
画面解像度設定
Game > fullyAspect(fullHD1080×1920)
BackgroundCollar変更
カメラサイズ変更(14.7)
x(4.5)、y(12)、z(-2)、

__【プレファブ作成】__
Prefabsフォルダ作成
enptyプレファブ作成
テトリスブロックプレファブ(7個)作成
　　　作成方法
　　　 1、Hierarchie　> Brock_Iフォルダ作成
　　 　２、１へブロック素材を入れる
　　　 ３、Control＋D複製、position設定

__【①Board作成】__
１、project > Sprictsフォルダ作成
２、project > Sprictsフォルダ < Boardスプリクト作成
３、関数生成
　(変数)
　　ボード基盤用の四角枠格納用(インスペクタ呼び出し可能、型（位置、回転、大きさを表す）変数emptySprite)
　　ボードの高さ(30)/ボードの幅(10)/ボードの高さ調整用数値(8)（インスペクタ呼び出し可能、型（整数））

　（関数）
ボードの生成
>メソッド名CreateBoard、型（何もない）
四角枠に格納するには、高さは0位置から始まり調整した高さに達するまで繰り返す。
x(左右)が0マス目からwidthの間で処理する。
どっちも達したらプレファブ(emptySprite)を生成。(回転なし)して変数(Transform clone(子))へ格納する。
transformの親プロパティも四角枠へ格納する。

(スタート)作成した関数を呼び出す

わかりやすくまとめた記事
https://qiita.com/hanatan079/items/8d26a031f6a333f4bd76

ゲームオブジェクト作成
4、Hierarchie　> Boardフォルダ作成、position (0,0,0)
５、BoardフォルダへBoardスプリクトアタッチ
6、Purefabs > empty を　Hierarchie　> Board　> EmptySpriteへアタッチ


__【②ブロックのスポーン機能作成】__
1、Hierarchie　> Spawnerフォルダ作成
2、Spawnerフォルダ　position（4.25,25,-1)
3、project > Spawner、Blockスプリクト作成、Spawnerアタッチ
４、関数生成(Spawner.cs)
(配列)
生成するブロックすべて格納(インスペクタ呼び出し可能、配列名Blocks)
（関数）
ランダムなブロックを1つ選ぶ関数
>型(ブロック)、メソッド名GetRandomBlock
0〜配列内のブロックをランダムに選んでiへ格納する
ブロック格納用にブロックはあるのか。
あるならそのブロックを渡して、ないなら空を返す。

>選ばれたブロックを生成する関数
呼び出し可能、ブロック型、メソッド名SpawnBlock
GetRandomBlock()へオブジェクトを生成、変数名blockとする。ブロック型
blockがある場合blockを返す。ない場合は空を返す。

わかりやすくまとめ
https://qiita.com/hanatan079/items/ab4c6baddf8b4e9d54db

5、Assetas > Prefabs ブロック全てAdd、Blockスクリプトアタッチ
６、Hierarchie　> Spawner　> インスペクタBlocks　にPrefabsのブロック全て入れる
７、Hierarchie　> GameManagerフォルダ作成
８、position(0,0,0)
９、 Assetas > GameManagerスプリクト、アタッチ
10、関数生成(GameManager.cs)
(変数)
スポナー/ 生成されたブロック格納(スポナー型、変数名spawner)
スポナーオブジェクトをスポナー変数に格納するコード(ブロック型、変数名block)
スポナークラスからブロック生成関数をよんで変数に格納する


__【③ブロック自動落下機能の作成(Block.cs)】__
1、変数、関数作成
(変数)
回転していいブロックか(インスペクタ呼び出し可能、変数名canRotate、bool型使用)
(関数)
移動用
>オブジェクトの移動をする。引数moveDirectionとする。
現在地へ引数を加算代入する。

移動関数を呼ぶ（4種類）(呼び出し可能)
>　上下左右4種類作成
　位置を指定して、移動用関数を生成

　　　回転用（2種類）(呼び出し可能)
>左右回転2種類作成
　回転して良いブロックの場合zを90度回転

~~２、GameManeger.cs書く~~
3、落下速度制限の実装(GameManeger.cs)
(変数)
　　　次のブロックが落ちるまでのインターバル時間(インスペクタ呼び出し可能、変数dropIntervalが0.25f)
　　　次にブロックが落ちるまでの時間(変数nextdropTimer)
（関数呼び出し）
時間判定をして判定次第で落下関数を呼ぶ(アップデート)
>現在の時間よりブロックの落下時間が早い場合は、現在時間にインターバル時間を加算する。ブロックが格納されているなら、そのブロックを下へ。


４、ブロックの位置を調整する
>現在地を丸めて、spawner.transform.positionへ格納する


わかりやすくまとめ
https://qiita.com/hanatan079/items/0a91c8ceda7be8d45727


__【④ブロックが下で止まるようにする実装】__
1、関数作成(Board.cs)
枠内にあるのか判定する関数
>型(真偽値)、メゾット名BoardOutCheck、引数xy
x軸は０以上with未満であり、　y軸は0以上であること。全て条件が成立していればtrueを返す。

ブロックが枠内にあるのか判定する関数を呼ぶ関数
>呼び出し可能、型(真偽値)、メゾット名CheckPosition、引数名blockとしてブロックを渡す。
ブロックの数分だけ繰り返しループする。変数名item
itemのxyを丸めて、変数名posに格納する。
xyが枠内にない(はみ出ている)のかの判定。


２、変数作成(GameManeger.cs)
ボードのスクリプトを格納(変数board)

ボードをスプリクト格納する用の変数に格納(スタート)
>全てのオブジェクトからBoardコンポーネントを探してboard変数へ格納する。

(関数)
Boardクラスの関数を呼び出してボードから出ていないか確認(アップデート)
>変数CheckPosition、格納したブロックが枠内にない場合、ブロックを上へあげる。格納したブロックを生成する。

わかりやすくまとめ
https://qiita.com/hanatan079/items/6d1c9caeccc486af83cf

__【⑤数値を丸めるスクリプトの作成】__
１、Assetas > Roundingスプリクト作成
２、public class Rounding : MonoBehaviour →
public static class Rounding 変更
３、丸める関数作成
>呼び出し可能、メソッド名Round
丸める関数を何回でも使いまわせるようにVector2、Vector3をiとする。

４、ファイルの呼び出し(Board.cs)
>ブロックが枠内にあるのか判定する関数を呼ぶ関数のときの丸める処理コードを消去して、ファイルを呼び出す

わかりやすくまとめ
https://qiita.com/hanatan079/items/dc5d92fe2ea44fbe912c


__【⑥ブロックが落ちた場所を記録して重ならないようにする実装】__
(Board.cs)
１、２次元配列の作成（変数grid）
２、関数作成
移動先にブロックがないか判断する関数
>型(真偽値)、メソッドBlockCheck、引数にxyとブロックを渡す
２次元配列xyが空でない時は他のブロックあり。
親が同じでない時は他のブロックがある。
上記2つがtrueの時にtrue

CheckPositionに追記
>BlockCheck関数呼び出し、移動先にブロックかないか確認


ブロックが落ちたポジションを記録する関数
>呼び出し可能な、型(何もないことを意味する)メソッド(SaveBlockInGrid)ブロックを渡す。
変数itemとしてブロックオブジェクトの分だけ繰り返す。
itemの場所を丸めて、変数posへ格納。
itemをgrid(２次元配列)のxyポジションへ格納する。

グリッドを生成する
>スタートよりも早く生成
ブロックが落ちたポジションを記録する関数の呼び出す。引数で格納されたブロックを渡す。

ブロックが落ちたポジションを記録する関数を呼び出す(GameManager.cs)
>Boardクラスの関数を呼び出してボードからはみ出ていないか確認する関数内、引数(activeBlock)

わかりやすくまとめ
https://qiita.com/hanatan079/items/582800b8d235e746f631


__【⑦ブロックを操作可能にする(移動、回転)実装】__
１、(GameManeger.cs)
(変数)
入力受付タイマー(3種類(下がる用、左右用、回転用))
>型(小数)、変数名nextKeyDownTimer、nextKeyLeftRightTimer、nextKeyRotateTimer

インターバル（3種類、インスペクタ呼び出し可能）
>型　(小数)、nextKeyDownInterval, nextKeyLeftRightInterval, nextKeyRotateInterval;

タイマーの初期設定(スタート)

>初期タイマー（受付タイマー）は、インターバル＋現在時間とする

（関数）
キーの入力を検知してブロックを動かす関数
>何もない型、メソッド名PlayerInputとする。
(D)が押されて左右の受付タイマーより現在時間が大きくなった時か、またはボタンが押された瞬間を感知する。
その場合は、格納されているブロックを右へ動かす。
初期設定時間を設定。
もし枠内にない場合は格納されたブロックを左へ動かす。
逆バージョンを(A)として行う。
(E)が押されて回転受付タイマーより現在時間が大きくなった時は、ブロックを右に回転する。
枠内にない場合は左に回転する。
(S)が押されて左右の受付タイマーより現在時間が大きくなった時か、自動落下時間より現在時間がおきくなったら。
ブロックをしたへ、初期設定時間を設定。
ブロックが次に落ちてくる時間を設定。(現在時間と次のブロックが落ちるまでのインターバル時間を足した時間)
枠内にない場合は、ボードの底についた時に次のブロックを生成する関数を呼び出す。

ボードの底についた時に次のブロックを生成する関数
>型(何もない)、メソッド名BottomBoard
底についたらブロックを上にあげる
ブロックが落ちたポジションを記録する。
ブロックを生成し格納する。
現在の時間を初期化する。

２、GameManeger.csの~~スタート~~アップデートをコメントアウトして、 PlayerInput();を呼び出す

わかりやすくまとめ
https://qiita.com/hanatan079/items/991a743d70a601cb28d5

__【⑧消去して一段下がる実装】__
１、関数作成(Board.cs)
全ての行をチェックする関数
>型(真偽値)、メソッド名IsComplateとして引数yを渡す。
0から横幅が埋まるまで繰り返す。
２次元配列が空の場合は処理を抜ける。1つでも埋まっていない場合はfalseを返す。

消去する関数
>型(何も返さない)、メソッド名ClearRowとして引数yを渡す。
0から横幅が埋まるまで繰り返す。
２次元配列が空でないとき(埋まっている時)は、配列に格納されているゲームオブジェクトを破壊する。
次に２次元配列のデータを空にする。

上にあるブロックを１段下げる関数
>型(何も返さない)、メソッド名ShiftRowsDownとして、引数startYとする。
startYから始まり高さを超えるまで繰り返し処理する。
高さが超えたら、0から横幅が埋まるまで繰り返す。
２次元配列が空でないとき(埋まっている時)は、配列を−１して１段下に登録する。
下に下げて配列を空にする。
ベクトル３で新たに生成して(高さ−1)、１段下げた２次元配列に格納する。

全ての行をチェックして埋まっていれば消去する関数
>呼び出し可能、型(何もない)、メソッド名ClearAllRows
高さが超えるまで繰り返し処理する。
超えたら、すべての行をチェックする。
チェックして全て埋まっているなら消去する。
上にあるブロックを１段下げてyを正常な位置へ。

２、GameManeger.cs(BottomBoard関数内)で呼び出す

わかりやすくまとめ
https://qiita.com/hanatan079/items/63920a8aabaac3a37426

__【⑨ゲームオーバーの実装】__
１、Hierarchie　>UI > panel >GameOverPanel作成
２、Canvas > CanvasScaler >ScaleWithScreenSize変更
３、Vector2(1080,1920)/Match0.5
4、GameOverPanel > UI > Text > GameOverText作成
５、GameOverPanel > UI > Button > Replay作成
６、４５のサイズやカラー位置の調整
７、変数、関数作成（GameManeger.cs）
(ライブラリ)
　　　シーン移動
(変数)
　　　パネル格納
>インスペクタ呼び出し可能、変数名gameOverPanel

　　　ゲームオーバー判定
>型(真偽値)、変数名gameOver

　　　ゲームオーバーパネルの非表示設定(スタート)
>パネルがヒエラルキーで表示されているのか
されているなら、パネルを非表示にする

（関数）
　　　ゲームオーバーになったらパネルを表示する
>型(何もない)メソッド名GameOver、格納されたブロックを一段上にあげる。
~~もしゲームオーバーパネルが表示されていたら非表示にする。表示されていなかったらtrue~~
パネルがヒエラルキーで表示されていないならパネルを表示する

　　　シーンを再読み込みする（ボタン読み込み）
>呼び出し可能、型（何もない）、メソッド名Replay
サンプルシーンを呼び出す

８、ゲームオーバーの時はプレイヤーの受付をしないようにするコード記述(アップデート)

９、線を超えたかどうかを判定する関数(Board.cs)
>呼び出し可能、型（真偽値）、メソッド名OverLimitで引数でブロックを渡す。
型(位置、回転、大きさ)、ブロック配列が枠からはみ出るまで繰り返す。
ボードの高さ-高さ調整用数値よりブロック配列が高くなったらtrue。

10、OverLimitを呼び出し(GameManeger.cs)
>CheckPosition関数内で。ブロックが枠内にない場合。
線を超えたのか判断、超えた場合はゲームオーバーパネルを表示する。
超えていないなら、次のブロックを生成する。

１１、Hierarchie　>GameManeger >GameOverPanelアタッチ
１２、Hierarchie　> Replay >OnClickにGameManegerアタッチ
１３、NoFunction　> GameManeger > Replayに設定

わかりやすくまとめ
https://qiita.com/hanatan079/items/252009cee370bf92d7ff



★★★★★
2022.11.22追記
２０２２.１１.２８追記