요약
루빅스 큐브 층 회전 이론을 통해 Raycast 순서를 서로 다른 층에 다르게 적용하기 위해 서로 다른 좌표를 가진 배열 2개를 만들었다. 그 후 Raycast() 속성의 layerMask를 통해 불필요한 충돌을 방지했다. 충돌된 오브젝트는 cubeState.cs에 저장되어 활용된다.
알고리즘
Ray를 그림과 같이 생성하기 위해 다음과 같은 코드를 작성하였다
ReadCube.cs
public class ReadCube : MonoBehaviour
{
// Ray의 위치를 할당 받을 변수
public Transform tUp;
public Transform tDown;
public Transform tLeft;
public Transform tRight;
public Transform tFront;
public Transform tBack;
// 복제된 Ray를 저장할 변수
private List<GameObject> frontRays = new List<GameObject>();
private List<GameObject> backRays = new List<GameObject>();
private List<GameObject> upRays = new List<GameObject>();
private List<GameObject> downRays = new List<GameObject>();
private List<GameObject> leftRays = new List<GameObject>();
private List<GameObject> rightRays = new List<GameObject>();
private int layerMask = 1 << 8;
CubeState cubeState;
public GameObject emptyGo;
int[,] XY = { { -1, 0 }, { -1, 1 }, { 0, 1 }, { 1, 1 }, { 1, 0 }, { 1, -1 }, { 0, -1 }, { -1, -1 }, { 0, 0 } };
int[,] mirrorXY = { { 1, 0 }, { 1, 1 }, { 0, 1 }, { -1, 1 }, { -1, 0 }, { -1, -1 }, { 0, -1 }, { 1, -1 }, { 0, 0 } };
void Start()
{
SetRayTransforms();
cubeState = FindObjectOfType<CubeState>();
ReadState();
}
해당 코드에서 눈에 띄는 부분은 layerMask와 mirrorXY 배열일 것이다. layerMask는 Raycast() 속성을 통해 앞에 있는 물체가 가려도 해당 layerMask에만 충돌하도록 설정할 수 있다. mirrorXY 배열은 루빅스 큐브 층의 회전 방향을 맞추기 위해 서로 다른 소환 위치를 정의한 것이다.
// 업데이트 된 위치에서 인식하여 색상을 읽어오는 함수
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);
}
// Ray의 방향과 위치를 확인하여 BuildRays통해 복제하는 함수
void SetRayTransforms()
{
upRays = BuildRays(tUp, new Vector3(90, 90, 90), true);
downRays = BuildRays(tDown, new Vector3(270, 90, 90));
leftRays = BuildRays(tLeft, new Vector3(0, 180, 90), true);
rightRays = BuildRays(tRight, new Vector3(0, 0, 270));
frontRays = BuildRays(tFront, new Vector3(0, 90, 0));
backRays = BuildRays(tBack, new Vector3(0, 270, 0), true);
}
Start()에서 보이는 함수들은 Ray를 배치하고 색상을 가져와 CubeState 클래스에 저장하는 역할을 하고 있다. 해당 클래스는 특별한 기능은 없으며, 단순히 데이터만 저장한다.
//Ray를 복제하는 함수
List<GameObject> BuildRays(Transform rayTransform, Vector3 direction, bool mirror = false)
{
int rayCount = 0;
List<GameObject> rays = new List<GameObject>();
// -1, 1 | 0, 1 | 1, 1
// -1, 0 | 0, 0 | 1, 0
// -1,-1 | 0,-1 | 1,-1
// 위의 방식으로 큐브를 생성
// 순서는 XY배열로 생성됨
// 거울처럼 반대로 되게 하기 위해여 mirror배열순서로 생성함
if (mirror)
{
for (int i = 0; i < 9; i++)
{
Vector3 startPos = new Vector3(rayTransform.localPosition.x + mirrorXY[i, 0], rayTransform.localPosition.y + mirrorXY[i, 1], rayTransform.localPosition.z);
GameObject rayStart = Instantiate(emptyGo, startPos, Quaternion.identity, rayTransform);
rayStart.name = rayCount.ToString();
rays.Add(rayStart);
rayCount++;
}
}
else
{
for (int i = 0; i < 9; i++)
{
Vector3 startPos = new Vector3(rayTransform.localPosition.x + XY[i, 0], rayTransform.localPosition.y + XY[i, 1], rayTransform.localPosition.z);
GameObject rayStart = Instantiate(emptyGo, startPos, Quaternion.identity, rayTransform);
rayStart.name = rayCount.ToString();
rays.Add(rayStart);
rayCount++;
}
}
// 방향에 맞게 Ray을 돌림
rayTransform.localRotation = Quaternion.Euler(direction);
return rays;
}
먼저 BuildRays를 통해 생성하는 순서에 맞춰 Ray 위치를 생성하고 있는 것이 보인다. 다만, 회전과 반대 방향에 해당하는 Ray들은 그에 맞는 mirrorXY 배열을 통해 생성되는 것을 볼 수 있다.
// Ray를 통해 색상을 읽어 내는 함수
public List<GameObject> ReadFace(List<GameObject> rayStarts, Transform rayTransform)
{
List<GameObject> facesHit = new List<GameObject>();
// Ray가 위치한 앞부분에 색상값(타일)을 인식하는 역할
foreach (GameObject reyStart in rayStarts)
{
Vector3 ray = reyStart.transform.position;
RaycastHit hit;
// Ray를 통해 facesHit에 색상을 넣어줌
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;
}
}
충돌된 오브젝트를 반환하는 역할을 한다. 특이한 점은 충돌이 발생하지 않는 경우 색상을 통해 이를 알려주는 역할도 하고 있다는 것이다.
'Unity > 루빅스 큐브 개발 일지' 카테고리의 다른 글
[Unity] 루빅스 큐브 층 회전 알고리즘 (0) | 2025.01.20 |
---|---|
[Unity] 루빅스 큐브 층 확인 알고리즘 (0) | 2025.01.20 |
[Unity] 루빅스 큐브 층 회전 이론 (0) | 2025.01.19 |
[Unity] 루빅스 큐브 회전 (0) | 2025.01.19 |
[Unity] 루빅스 큐브 오브젝트 만들기 (0) | 2025.01.19 |