iT邦幫忙

2021 iThome 鐵人賽

DAY 13
0
Mobile Development

從無到有! Unity AR手遊開發日誌-以山海異聞錄為例系列 第 13

Day 13 | 魔術方塊AR遊戲開發Part2 - 魔術方塊偵測

在上一篇文章中,我們完成魔術方塊的建立及旋轉,今天我們要來完成魔術方塊的偵測。

目錄
魔術方塊的偵測
讀取面狀態

魔術方塊的偵測

魔術方塊狀態

建立CubeState()用來儲存魔術方塊目前狀態,新增List分別儲存各面物件

 public List<GameObject> front = new List<GameObject>();

射線設置

首先要在Scene中新增好射線起始位置,新增Empty GameObject,並將外觀設定成點。

並且為魔術方塊的每個面都新增一個射線,並將其位置放在各面的正上方。

將這些射線放在群組下(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);
    }

以上就是魔術方塊的偵測,下一篇會是魔術方塊面的旋轉,明天見!


上一篇
Day 12 | 魔術方塊AR遊戲開發Part1 - 魔術方塊建立
下一篇
Day 14 | 魔術方塊AR遊戲開發Part3 - 面的旋轉(上)
系列文
從無到有! Unity AR手遊開發日誌-以山海異聞錄為例30

尚未有邦友留言

立即登入留言