Bug修復記錄
項目場景
嘗試使用Unity獨自制作俄羅斯方塊(也許很沒有必要,網上隨便一搜就有教程)
問題描述
俄羅斯方塊的邊緣檢測出錯了,對方塊進行旋轉后,無法到達最左側或者最下側的位置,以及其他問題。演示圖如下所示:
?邊緣檢測代碼如下所示:
// 檢查方塊是否可以移動private bool IsCanMove(){// 檢查是否超出邊界for (int i = 0; i < transform.childCount - 1; i++){Vector3 pos = transform.GetChild(i).position;if (pos.y < 0 || pos.x < 0 || pos.x >= 10){return false;}}return true;}
修復方案
懷疑在旋轉該物體的時候位置發生了輕微偏移,導致檢測結果為超出邊界,但是在視覺上看不出來。通過對坐標的值進行取整處理可以解決這個問題,修復代碼如下:
// 檢查方塊是否可以移動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;}}return true;}
今日收獲
場景擺放
關于場景擺放這真的是一個很頭疼的問題,想必跟我一樣的新手都會考慮如何使方塊每步的移動與方塊的大小一致,然后考慮各種計算方塊大小、這個場景要做多大以及這個場景該怎么限制。
其實這個問題不用想那么多,把每個素材都做成1unity單位的大小就好了,場景先設置成10x15的大小,同時把左下角的位置移到(0,0)的位置,調整相機位置。這樣就把一個沒方向沒大小沒標準的問題變成了一個二維數組的問題,之后的問題就是對這個二維數組進行操作。
方塊創建
方塊的創建有太多種方式了,但是考慮到配置并創建每一種方塊以及旋轉,我選擇了使用預制體,這樣方便旋轉,還能更直觀了解這些方塊在二維數組中的變化。
狀態列表
這個是目前項目中最令人滿意的地方,因為我只是用了一個方法就把輸入系統和方塊的操作聯系了起來(沒錯,這里使用了之前提到的事件系統:Unity筆記——事件中心-CSDN博客)
// 方塊的狀態
public enum MoveType
{Move,Rotate,MoveDown,MoveRight,MoveLeft,Stop
}// 具體的方塊控制邏輯private void Start(){EventCenter.AddListener(EventName.CONTROL_MOVE, controlMove);}private void OnDestroy(){EventCenter.RemoveListener(EventName.CONTROL_MOVE, controlMove);}// 改變移動類型private void controlMove(object[] args = null){moveType = (MoveType)args[0];}// 方塊移動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;}}
// 輸入系統if (Input.GetKeyDown(KeyCode.W)){EventCenter.TriggerEvent(EventName.CONTROL_MOVE, MoveType.Rotate);}if (Input.GetKeyDown(KeyCode.S)){EventCenter.TriggerEvent(EventName.CONTROL_MOVE, MoveType.MoveDown);}if (Input.GetKeyUp(KeyCode.S)){EventCenter.TriggerEvent(EventName.CONTROL_MOVE, MoveType.Move);}if (Input.GetKeyDown(KeyCode.A)){EventCenter.TriggerEvent(EventName.CONTROL_MOVE, MoveType.MoveLeft);}if (Input.GetKeyDown(KeyCode.D)){EventCenter.TriggerEvent(EventName.CONTROL_MOVE, MoveType.MoveRight);}
動態加載組件
這一塊就沒有太多可說的地方了,直接new一個新對象,AddComponent相關腳本或者組件。不過,在動態將所有方塊預制體加入GameObject[]的時候發現其實用List存儲這些預制體其實也都是一樣的,感覺沒有太多差別,直接GameObject[]能直接導入該文件下所有的預制體。
private GameObject[] blocks;private List<GameObject> blocklist;private void Awake(){blockList = new List<GameObject>();generatorPoint = new GameObject();generatorPoint.transform.position = new Vector3(0, 0, 0);generatorPoint.transform.parent = transform;}private void Start(){generatorPoint.transform.position = createPos;blocks = Resources.LoadAll<GameObject>("Prefabs/Block");foreach (GameObject block in blocks){blockList.Add(block);}SpawnBoard();}// 生成方塊public void SpawnBoard(){randomIndex = Random.Range(0, blockList.Count);blockList[randomIndex].AddComponent<Block>();Instantiate(blockList[randomIndex], generatorPoint.transform.position, Quaternion.identity, transform);}