# Day 13 | 魔術方塊AR遊戲開發Part2 - 魔術方塊偵測 ###### tags: `Unity` `AR手遊` 在上一篇文章中,我們完成魔術方塊的建立及旋轉,今天我們要來完成魔術方塊的偵測。 > **目錄** > 魔術方塊的偵測 > 讀取面狀態 ## 魔術方塊的偵測 ### 魔術方塊狀態 建立CubeState()用來儲存魔術方塊目前狀態,新增List分別儲存各面物件 ``` public List<GameObject> front = new List<GameObject>(); ``` ### 射線設置 首先要在Scene中新增好射線起始位置,新增Empty GameObject,並將外觀設定成點。 ![](https://i.imgur.com/7rZpkmd.png) 並且為魔術方塊的每個面都新增一個射線,並將其位置放在各面的正上方。 ![](https://i.imgur.com/RlLjHzS.png) 將這些射線放在群組下(Rays)。 建立射線程式: * 為各射線都宣告一個變數儲存射線位置 `public Transform tUp;` * 魔術方塊的面為3x3,因此射線也宣告成3x3的形式,宣告rayCount做為控制迴圈變數 * 並利用迴圈生成射線,生成射線順序從左上到右下: |0|1|2| |3|4|5| |6|7|8| * 為射線命名完後,設定旋轉數值,並回傳射線 ``` public GameObject empty; //射線起始的位置 List<GameObject> BuildRays(Transform rayTransform, Vector3 direction) { int rayCount = 0; List<GameObject> rays = new List<GameObject>(); for (int y = 1; y > -2; y--) { for (int x = -1; x < 2; x++) { Vector3 startPos = new Vector3( rayTransform.localPosition.x + x, rayTransform.localPosition.y + y, rayTransform.localPosition.z); GameObject rayStart = Instantiate(empty, startPos, Quaternion.identity, rayTransform); rayStart.name = rayCount.ToString(); //射線編號 rays.Add(rayStart);//新增射線 rayCount++; } } rayTransform.localRotation = Quaternion.Euler(direction); return rays; } ``` 為魔術方塊的不同面,分別建立3x3的射線 ``` void SetRayTransforms() { upRays = BuildRays(tUp, new Vector3(90, 90, 0)); downRays = BuildRays(tDown, new Vector3(270, 90, 0)); leftRays = BuildRays(tLeft, new Vector3(0, 180, 0)); rightRays = BuildRays(tRight, new Vector3(0, 0, 0)); frontRays = BuildRays(tFront, new Vector3(0, 90, 0)); backRays = BuildRays(tBack, new Vector3(0, 270, 0)); } ``` ## 讀取面狀態 ### Raycast運用 為了防止射線偵測到其他物體,需要新增一個圖層,並將各魔術方塊的面圖層都改成該圖層。 並在程式碼中新增圖層遮罩。 ``` private int layerMask = 1 << 8; ``` 讀取面程式運用到Unity中的Physics.Raycast * 新增faceHit儲存射線碰撞的所有面 * 建立Raycast,並判斷是否與魔術方塊面相交 * 使用DrayRay,將射線畫出來,方便後續除錯 ``` public List<GameObject> ReadFace(List<GameObject> rayStarts, Transform rayTransform) { List<GameObject> facesHit = new List<GameObject>(); foreach (GameObject rayStart in rayStarts) { Vector3 ray = rayStart.transform.position; RaycastHit hit; if (Physics.Raycast(ray, rayTransform.forward, out hit, Mathf.Infinity, layerMask)) { Debug.DrawRay(ray, rayTransform.forward * hit.distance, Color.yellow); facesHit.Add(hit.collider.gameObject); } else { Debug.DrawRay(ray, rayTransform.forward * 1000, Color.green); } } return facesHit; } ``` ### 讀取面的狀況 使用ReadState讀取各面目前狀況 ``` public void ReadState() { cubeState = FindObjectOfType<CubeState>(); cubeState.up = ReadFace(upRays, tUp); cubeState.down = ReadFace(downRays, tDown); cubeState.left = ReadFace(leftRays, tLeft); cubeState.right = ReadFace(rightRays, tRight); cubeState.front = ReadFace(frontRays, tFront); cubeState.back = ReadFace(backRays, tBack); } ``` --- 以上就是魔術方塊的偵測,下一篇會是魔術方塊面的旋轉,明天見!