개인과제로 진행하는 메타버스 만들기 프로젝트에서 미니게임으로 FlappyBird와 같은 게임을 만들어보았다.
플레이어가 이동하는 것이 아닌 배경이 움직이는 것으로 구현해보고자 하였고,
장애물들을 일정 거리마다 반복 재배치하여 무한히 스크롤되는 느낌을 주는 구조를 구현해보았다.
[SerializeField] Obstacle[] obstacles;
[SerializeField] float scrollSpeed = 3f;
[SerializeField] int startIdx_Ob; // 오른쪽 끝
[SerializeField] int endIdx_Ob = 0;
private float camWidth;
void Start()
{
// 오른쪽 끝 인덱스
startIdx_Ob = obstacles.Length - 1;
camWidth = Camera.main.orthographicSize;
Vector3 lastObstacle = Vector3.zero;
// 장애물 초기 배치
foreach (var ob in obstacles)
{
lastObstacle = ob.SetRandomPosition(lastObstacle);
}
}
void Update()
{
if (isGameOver) return;
foreach (Obstacle ob in obstacles)
{
ob.transform.Translate(Vector3.left * scrollSpeed * Time.deltaTime);
}
ScrollObstacles();
}
void ScrollObstacles()
{
// 제일 왼쪽에 있는 장애물이 카메라의 범위를 벗어나면 이동
if (obstacles[endIdx_Ob].transform.position.x < -camWidth)
{
Vector3 frontPos = obstacles[startIdx_Ob].transform.localPosition;
obstacles[endIdx_Ob].SetRandomPosition(frontPos);
int pre_startIndex = startIdx_Ob;
startIdx_Ob = endIdx_Ob;
// 인덱스가 범위를 벗어나면 다시 범위 안으로 조정
endIdx_Ob = pre_startIndex - 1 == -1 ? obstacles.Length - 1 : pre_startIndex - 1;
}
}
장애물은 계속해서 왼쪽으로 이동하게 하고,
제일 왼쪽 끝에 있는 장애물은 endIdx_Ob 오른쪽 끝을 startIdx_Ob로 설정하고 카메라의 범위를 벗어나면 다시 오른쪽 끝으로 배치하는 방식으로 구현을 하였다.
그런데 여기서 장애물이 3개일 때는 잘 반복하던 코드가 4개 이상이 되자 순차적으로 진행되지않는 현상이 발생하였다.
인덱스 계산이 꼬이면서 순환 순서가 어긋나게 되버린 것이다.
int pre_startIndex = startIdx_Ob;
startIdx_Ob = endIdx_Ob;
// 인덱스가 범위를 벗어나면 다시 범위 안으로 조정
endIdx_Ob = pre_startIndex - 1 == -1 ? obstacles.Length - 1 : pre_startIndex - 1;
문제는 이 부분에서 인덱스를 지정해주는 부분이 문제였다.

가장 왼쪽에 있는 장애물이 카메라의 범위를 벗어났을 때 0번 인덱스 장애물이 startIdx_Ob (가장 오른쪽) 장애물이 되고 1번 장애물이 다음 endIdx_Ob(가장 왼쪽) 인덱스가 되어야하는데 3번 인덱스가 다음 endIdx_Ob 장애물이 되어버리며 문제가 발생.
먼저 가독성을 위해 인덱스 변수의 이름을 leftIdx_Ob와 rightIdx_Ob로 바꿔 주었다.
void ScrollObstacles()
{
if (obstacles[leftIdx_Ob].transform.position.x < -camWidth)
{
Vector3 frontPos = obstacles[rightIdx_Ob].transform.localPosition;
obstacles[leftIdx_Ob].SetRandomPosition(frontPos);
int pre_leftIndex = leftIdx_Ob;
rightIdx_Ob = leftIdx_Ob;
leftIdx_Ob = pre_leftIndex + 1 > obstacles.Length - 1 ? 0 : pre_leftIndex + 1;
}
}
그런 후 인덱스의 순환을 왼쪽부터 하나하나 순환하도록 수정해주었다.
가장 왼쪽에 있는 인덱스를 하나씩 증가시켜주고 최대 길이를 넘게되면 다시 처음으로 돌아오는 식으로 구현하였다.

처음에 왜 역방향으로 생각하고 작성했는지 잘 기억이 나지 않는다...
어찌됐든 해결하고 앞으로 다시는 저러지 않아야 겠다고 다짐을 하는 오늘이다.!