본문 바로가기
# 게임/# Unity

유니티 개발일지 + Procedural Dungeon Generation in Unity #3

by 쁘레레레레레 2020. 7. 27.

이전 글 : Procedural Dungeon Generation in Unity #2

https://atli-yeondi.tistory.com/30

 

Procedural Dungeon Generation in Unity #2

이전 글 : https://atli-yeondi.tistory.com/29 Procedural Dungeon Generation in Unity #1 https://atli-yeondi.tistory.com/28 [완성] Procedural Dungeon Generation 참고 : https://github.com/a327ex/blog/i..

atli-yeondi.tistory.com

위 링크된 이전 글에 이어서 공부, 개발하고 있습니다.

 

나와있진 않지만 cocos2d-x에서 개발하던걸 유니티로 일부만 옮겨왔고 이식을 대략 완료했을 때 랜덤 맵 생성에 대해 관심이 생겨 공부한 후 올린 글이 Procedural Dungeon Generation in Unity #1 , #2 입니다.

Procedural Dungeon Generation in Unity #1 : https://atli-yeondi.tistory.com/29

Procedural Dungeon Generation in Unity #2 : https://atli-yeondi.tistory.com/30

 


아직 알고리즘 자체엔 손 볼 곳이 있지만 일단 마저하던 개발에 착수하려 했다.

기존에 쓰던 파일 말고 그냥 단순하게 작고 귀엽고 무료인 캐릭터를 에셋스토어에서 구해서 테스트하고 있었는데

문제가 생겼다.

 

이전 글 #2를 보면 사다리를 타일 맵 형식이 아닌 개별 오브젝트를 생성하고 이미지와 콜라이더를 따로 넣어준 탓에 코드에 적어둔 내 의도대로 동작을 안 하는데

일단 이미지를 첨부하고 설명을 덧붙이자면

캐릭터가 사다리를 만나 올라가는데 몇 칸 안 올라가고 떨어져 버린다.

이유는 간단한데

    private void OnTriggerEnter2D(Collider2D collision)
    {
//점프 및 기타 코드 생략
        if(collision.gameObject.tag == "ladder")
        {
            canClimb = true;
        }

    }   
   
   private void OnTriggerStay2D(Collider2D collision)
    {
        if (collision.gameObject.layer == 10 && rb2D.velocity.y < 0)
        {
            grounded = true;
        }
        canClimb = true;
    }

    private void OnTriggerExit2D(Collider2D collision)
    {
        grounded = false;
        if (canClimb && rb2D.gravityScale == 0.0f)
        {
            canClimb = false;
            rb2D.gravityScale = 1.0f;
        }
    }

바로 OnTrigger를 써서 그렇다.

트리거를 체크한 후 캐릭터가 오브젝트와 만나 트리거가 Enter 될 경우 코드와 같이 bool형식의 canClimb가 참이 되고 W를 눌러 올라갈 수 있는데, 문제는 오브젝트마다 각각의 콜라이더가 존재하고 또 맨 밑 사다리 오브젝트의 콜라이더와 만나 올라가다가, 바로 위 사다리 오브젝트와 만나면 자동적으로 맨 밑 콜라이더에서 OnTriggerExit2D를 만나 땅으로 떨어져 버리니 당연히 이런 방식으로는 복잡한 상태다.

 

사실 기존에 작업하던 원본? 프로젝트에 같은 일은 아니어도 예전에 콜라이더를 묶어서 작업을 해준 적이 있는데

사실 트리거를 안 쓰고 태그로 따로 선별해서 작업을 해줘도 돌아가긴 하지만 더 쉬운 방법은 타일 맵을 생성해서 깔아준 후 Composite Collider로 묶어버려서 그곳에서 트리거를 생성해 작업해주는 편이 더 편하다고 생각해서 그 방법을 이용할 생각이다.


 

이전 짤과 현재 짤의 진행과정을 보자면

이전 짤에서 문제점은 일단 키 입력 한 번당 한 번씩만 이동한다는 것, 그리고 일정 칸 이동하면 떨어진다는 것인데

 

1. 한 번씩 이동?

이것은 설계의 문제였는데

update함수에 넣은 상태라 문제없겠거니 했었는데  if문으로 W가 눌렸느냐 사다리와 겹쳐있느냐 등등 계속 if문으로 체크를 하니 그랬던 것 같다.

그냥 단순히 바로 climb함수를 호출하고 axisRaw("Vertical")로 상하를 판단해서 오르내리게 했다.

 

    private void climb()
    {
        rb2D.gravityScale = 0.0f;
        movement.y = Input.GetAxisRaw("Vertical");
        bool isClimb = false;
        Vector3 moveVelocity = new Vector3(0, 0, 0);
        if (movement.y > 0)
        {
            moveVelocity = Vector3.up;
            isClimb = true;
        }
        else if (movement.y < 0)
        {
            moveVelocity = Vector3.down;
            isClimb = true;
        }
        if (isClimb && canClimb)
        {
            animator.SetInteger(animationState, (int)CharacterStates.climb);
        }
        transform.position += moveVelocity * movementSpeed * Time.deltaTime;
    }

그러나 역시 미흡한 코드였다.

일단 문제는 정확하진 않지만 특정 상황에서 미끄러짐이 발생하고  점프를 이용해 사다리에 접근할 경우 W를 땟음에도 불구하고 조금씩 위로 자동으로 올라가는 현상이 발생한다.

게다가 중간에 다른 콜라이더에 접 할 경우 제멋대로 내려온다. 

나중에 본편으로 넘어갔을 경우 먼저 손봐야 할 부분인데 현재는 일단은 쓸 순 있으니 넘어간다.

 

2. 일정 칸 이동 후 떨어짐

그냥 간단하다. 예상했던 대로 onTriggerEnter구문에 중력 관련해서 값을 조절하는 부분을 넣어놨는데

다른 트리거로 넘어가면서 값이 복구됐던 것인데

 

예전에 박스 콜라이더로 장난쳤었나? 하면서 생각을 다시 짚다가 Tilemap Collider를 사용했던걸 기억했다.

문제는 어떻게 스크립트로 생성하냐였는데

차분하게 유니티로 타일 맵 만드는 과정을 떠올리며

게임 오브젝트 생성 -> addComponent로 Grid추가 -> 자식 개체에 오브젝트 생성 -> addComponent로 Tilemap생성 등의 절차를 단계적으로 만들어서 하나의 타일 맵에 전부 찍어내는 식으로 했다.

사실 룸 하나당 하나의 타일 맵으로 구성했었으나 홀이 미완성품이라 그런지 중간에 겹쳐있으면 올라가지지 않더라..

 

그리고 마지막으로 사다리는 연결이 되어있는데 그 길목을 벽들이 막아버리니 어떻게 못하는 상황

두 가지 방법을 생각했는데, 브리지, 즉 홀을 만들 때 콜라이더를 트리거로 만들어 타일을 깔 때 onTrigger 될 경우 설치하지 않는 방법과

기존의 방식처럼 전부 만들어놓고 이후에 철거하는 식으로 생각을 해봤다.

 

일단 아까 공부할 때 매우 배고프고 신경질 난 상태라 그냥 꼴리는 대로 작업했는데

                    if (tmMap.GetTile(new Vector3Int((int)hall.pos.x + i, (int)hall.pos.y + j, 0)))
                    {
                        string str = tmMap.GetTile(new Vector3Int((int)hall.pos.x + i, (int)hall.pos.y + j, 0)).name;
                        Debug.Log("배고파 야발 2 "+ str);
                        tmMap.SetTile(new Vector3Int((int)hall.pos.x + i, (int)hall.pos.y + j, 0), TileForDebug2);
                        continue;
                    }

별 방법을 다 써봤고 결국은 이 작업을 하고 내일 더 손볼 예정이다.

사실 엄청 잘못된 코드긴 한데  내일 고쳐야겠다.

 

아무튼

                    Collider2D hitBox = Physics2D.OverlapBox(new Vector2(hall.pos.x+i, hall.pos.y+j), new Vector2(1,1), 0);
                    if (hitBox != null)
                    {
                        tmMap.SetTile(new Vector3Int((int)hall.pos.x + i, (int)hall.pos.y + j, 0), null);
                        Debug.Log("배고파 야발");
                        continue;
                    }

위와 같은 방법을 썼었으나 계속 null로 나왔고 hitBox에 우연히 걸려도 기존 타일이 삭제가 되지 않았는데

지금 생각해보면 null을 넣었으니 당연한 것...이지만

 

아까 공부했을 때 구글 검색 시 나왔던 DC갤에선 setTile 할 때 좌표 넣고 null을 넣으면 삭제된다라고 쓰여있던 댓글을 너무 믿었었다... 사실 너무 빨리 끝내고 밥 먹으러 가고 싶었기에..

 

밥을 먹고 와서 갑자기 의문이 들어서 노란색 반투명 타일을

tmMap.SetTile(new Vector3Int((int)hall.pos.x + i, (int)hall.pos.y + j, 0), TileForDebug2);

위 코드처럼 넣어주니   

위에 올린 이 짤처럼 대체되었고 무사히 통과되는 모습이다.

 

내일은 사다리 타는 코드를 손 본 후 본 게임에 적용시키지 않을까 예상을 하고 있다.

'# 게임 > # Unity' 카테고리의 다른 글

FSM #1  (0) 2020.08.04
Procedural Dungeon Generation in Unity #4 점검  (0) 2020.07.30
움직임 입력값  (0) 2020.07.29
사다리 만들기  (0) 2020.07.29
Procedural Dungeon Generation in Unity #1  (0) 2020.07.23