프로젝트/건즈앤 레이첼스

[유니티 프로젝트] A* 알고리즘을 이용한 맵 생성 (로직 변경)

Bueong_E 2023. 4. 5. 23:01
반응형
SMALL

맵 생성 알고리즘에 수정사항이 있었다. 이유는 간단하다 수치 밸런스를 잡다보니 짧고 빠르게 끝나는 방이 여러개 있는 것 보다 적은 양의 퀄리티 높은 방으로 맵을 생성하는 편이 게임의 재미 측면에서 더 좋을 것 같다는 결론이 나왔기 때문이다.

 

걱정되었던 부분은 일반룸(흰색)이 줄어드니 맵의 배열 모습이 다양하지 못할것 같다는 것이 있었고 히든룸(노란색) 의 등장을 필수로 하였기 때문에 이전처럼 랜덤한 위치 보단 일반룸에서 먼저 전투를 치룬 뒤 접근 할수 있게 하는 것이 좋다는 생각이 있었기 때문이다

 

다행히도 맵 생성기는 배열의 크기에 따라 다양한 모습이 나올수 있었고 히든룸의 생성 위치는 일반룸들중에서 시작지점과 가장 먼 지점을 골라 생성하는 방식으로 해결할수 있었다. 

 

아래는 맵의 생성수를 6개로 고정한뒤 배열의 인덱스 구성 만을 변경하여 생성한 맵 구성이다.

 

3X3 그리드일 경우
3X3
3X3
2X4
4X2

이렇게 한 테마(스테이지) 에서 다양한 배열을 랜덤하게 사용하면 다양한 모습을 가질수 있고 맵의 모습에 따라 다르지만 대부분 보스방(빨간색)을 들어가기 전 최소 1번의 전투 이후 안전가옥(초록색)과 히든룸(노란색)을 방문할수 있게 되었다.

 

수정된 코드는 아래와 같다.

 

  // 원하는 룸 갯수가 나올때 까지 돌아갑니다. (맵 배열의 모습에 따라 룸의 배치가 바뀝니다.)
        while (true)
        {
            for (int i = 0; i < this.generator.wholeRoomList.Count; i++) Destroy(this.generator.wholeRoomList[i]);
            this.generator.Init();
            //맵 룸 수 조절하는 부분
            if (this.generator.wholeRoomList.Count == 6 && this.generator.normalRoomCount != 0) break;
        }
    private void MakeHiddenRoom()
    {
        //히든룸 생성
        var hiddenGO = UnityEngine.Object.Instantiate(this.hiddemRoom);
        //히든 룸 생성 후 전체룸 리스트에 추가
        this.wholeRoomList.Add(hiddenGO);
        //히든룸 포지션 변수에 시작 룸 위치와 가장 거리가 먼 노말 룸 위치 할당.
        this.hiddemRoomPos = this.FindFurtherNormalRoomFromStart(this.startRoomPos, this.normalRoomList);
        // 히든룸 위치 잡아주기.
        hiddenGO.transform.position = this.hiddemRoomPos;
        // 기존 위치에 있던 노말룸 파괴 (노말룸 리스트에서 찾기)
        GameObject targetNoramlRoom = this.normalRoomList.Find(x => (Vector2)x.transform.position == this.hiddemRoomPos);
        // 찾은 노말룸 파괴
        Destroy(targetNoramlRoom);
        // 리스트에서 게임 오브젝트 인스턴스 제거
        this.normalRoomList.Remove(targetNoramlRoom);
        this.wholeRoomList.Remove(targetNoramlRoom);
    }

    private Vector2 FindFurtherNormalRoomFromStart(Vector2 start, List<GameObject> list)
    {
        float maxDistance = 0f;
        Vector2 maxDistanceVector = Vector2.zero;
   
        for (int i = 0; i < list.Count; i++)
        {
            float distance = Vector2.Distance(start, list[i].transform.position);
            if (distance > maxDistance)
            {
                maxDistance = distance;
                maxDistanceVector = list[i].transform.position;
            }
        }     
        return maxDistanceVector;
    }

 

 

반응형
LIST