搭建場景
使用任意方塊、純色瓦片或者其他圖形作為背景,設置其大小與目標大小一致或者更大,設置左下角為場景頂點,并放置在(0,0)處。調整攝像機至合適位置。
制作游戲預制體
每個方塊預制體包含有4個小方塊以及一個圍繞旋轉的節點。先設置一個小方塊的坐標為(0,0),在此基礎上擺放其他小方塊,設置一個合適的旋轉節點。
腳本
思路
實現方塊自由下落? ? ? ? ->?Block.cs
實現方塊左右移動、加速下落、旋轉??????? ->?Block.cs
限制方塊移動范圍???????? ->?Block.cs
把方塊加入到場景中????????->?Board.cs
禁用該方塊的腳本 ? ? ? ->?Block.cs
檢測方塊是否滿行?????????->?Board.cs
滿行則消除該行?????????->?Board.cs
下移該行上面的方塊????????->?Board.cs
實現代碼
Block.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum MoveType
{Move,Rotate,MoveDown,MoveRight,MoveLeft,Stop
}public class Block : MonoBehaviour
{private float timer = 0;private float moveSpeed = 0.8f;private float moveDownSpeed = 0.2f;private bool isCanMove = true;private Transform rotatePoint = null;private MoveType moveType = MoveType.Move;private void Start(){Init();}private void Update(){if (isCanMove){if (Input.GetKeyDown(KeyCode.W)){controlMove(MoveType.Rotate);}if (Input.GetKeyDown(KeyCode.S)){controlMove(MoveType.MoveDown);}if (Input.GetKeyUp(KeyCode.S)){controlMove(MoveType.Move);}if (Input.GetKeyDown(KeyCode.A)){controlMove(MoveType.MoveLeft);}if (Input.GetKeyDown(KeyCode.D)){controlMove(MoveType.MoveRight);}TryMove(MoveType moveType);}}// 初始化方塊public void Init(){// 初始化旋轉點rotatePoint = transform.GetChild(transform.childCount - 1);}// 改變移動類型private void controlMove(MoveType moveType){if (isCanMove){this.moveType = moveType;}}// 方塊移動private void TryMove(MoveType moveType = MoveType.Move){switch (moveType){case MoveType.Move:MoveFall();break;case MoveType.Rotate:Rotate();break;case MoveType.MoveDown:MoveDown();break;case MoveType.MoveLeft:MoveLeft();break;case MoveType.MoveRight:MoveRight();break;case MoveType.Stop:Stop();break;}}// 檢查方塊是否可以移動private bool IsCanMove(){// 檢查是否超出邊界for (int i = 0; i < transform.childCount - 1; i++){int roundX = Mathf.RoundToInt(transform.GetChild(i).position.x);int roundY = Mathf.RoundToInt(transform.GetChild(i).position.y);if (roundY < 0 || roundX < 0 || roundX >= 10){return false;}// 檢查是否與其他方塊重疊if (Board.grid[roundX, roundY] != null){return false;}}return true;}// 方塊下落private void MoveFall(){timer += Time.deltaTime;if (timer >= moveSpeed){transform.position += Vector3.down;if (!IsCanMove()){transform.position -= Vector3.down;moveType = MoveType.Stop;}timer = 0;}}// 方塊加快下落private void MoveDown(){timer += Time.deltaTime;if (timer >= moveDownSpeed){transform.position += Vector3.down;if (!IsCanMove()){transform.position -= Vector3.down;moveType = MoveType.Stop;}timer = 0;}}// 方塊向左移動private void MoveLeft(){transform.position += Vector3.left;if (!IsCanMove()){transform.position -= Vector3.left;}moveType = MoveType.Move;}// 方塊向右移動private void MoveRight(){transform.position += Vector3.right;if (!IsCanMove()){transform.position -= Vector3.right;}moveType = MoveType.Move;}// 方塊旋轉private void Rotate(){transform.RotateAround(rotatePoint.position, Vector3.forward, -90);if (!IsCanMove()){transform.RotateAround(rotatePoint.position, Vector3.forward, 90);}moveType = MoveType.Move;}// 方塊停止private void Stop(){isCanMove = false;// Debug.Log("Stop");for (int i = 0; i < transform.childCount - 1; i++){int roundX = Mathf.RoundToInt(transform.GetChild(i).position.x);int roundY = Mathf.RoundToInt(transform.GetChild(i).position.y);// 添加方塊到Board中Board.Instance.AddBlock(roundX, roundY, transform.GetChild(i));}// 檢查游戲是否結束Debug.Log("檢查游戲是否結束!");Board.Instance.IsGameOver(transform);// 消除行Debug.Log("檢查是否消除行!");Board.Instance.CheckLine();// 生成新方塊Board.Instance.SpawnBlock();enabled = false;}
}
Board.cs
這里繼承了一個單例模式的泛型類,簡而言之就是這里需要創建單例模式。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Board : SingletonMono<Board>
{public static int width = 10;public static int height = 15;public static Transform[,] grid = new Transform[width, height + 5];private int randIndex; // 隨機生成方塊的索引private float timer = 0f; // 計時器private float countdown = 1f;// 倒計時private GameObject generatorPoint;private Vector3 createPos;private GameObject[] blocks;private List<GameObject> blockList;protected override void Awake(){base.Awake();Init();}private void Start(){// Debug.Log(blockList.Count);SpawnBlock();}private void Update(){timer += Time.deltaTime;if (timer >= countdown){ClearNullBlock();timer = 0;}}// 初始化private void Init(){generatorPoint = new GameObject();createPos = new Vector3(width / 2 - 1, height + 1, 0);generatorPoint.transform.position = createPos;// generatorPoint.transform.parent = transform;blockList = new List<GameObject>();blocks = Resources.LoadAll<GameObject>("Prefabs/Block");foreach (GameObject block in blocks){blockList.Add(block);}}// 生成方塊public void SpawnBlock(){randIndex = Random.Range(0, blockList.Count);if (blockList[randIndex].GetComponent<Block>() == null){blockList[randIndex].AddComponent<Block>();}Instantiate(blockList[randIndex], generatorPoint.transform.position, Quaternion.identity, transform);}// 添加方塊public void AddBlock(int x, int y, Transform block){grid[x, y] = block.transform;}// 檢查游戲是否結束public void IsGameOver(Transform block){if (block.position.y >= createPos.y){Debug.Log("Game Over");}}// 檢查是否有可以消除的行public void CheckLine(){for (int i = height - 1; i >= 0; i--){if (IsLineFull(i)){RemoveLine(i);}}}// 檢查行是否滿private bool IsLineFull(int y){for (int i = 0; i < width; i++){if (grid[i, y] == null){return false;}}return true;}// 消除方塊public void RemoveLine(int x){for (int i = 0; i < width; i++){Destroy(grid[i, x].gameObject);grid[i, x] = null;}MoveBlockdown(x);}// 下移方塊public void MoveBlockdown(int h){for (int i = h; i < height; i++){for (int j = 0; j < width; j++){if (grid[j, i] != null){grid[j, i - 1] = grid[j, i];grid[j, i] = null;grid[j, i - 1].position += Vector3.down;}}}}// 清理空對象private void ClearNullBlock(){for (int i = 1; i < transform.childCount; i++){if (transform.GetChild(i).childCount == 1){Destroy(transform.GetChild(i).gameObject);}}}
}
了解更多
【日志】unity俄羅斯方塊(一)——邊界限制檢測-CSDN博客【日志】unity俄羅斯方塊(二)——方塊碰撞檢測-CSDN博客