개?발/Unity 혼공

벽 미끄러짐 및 지상 감지 방식(Collider 2D,platform effector 2D, side friction)

YUEIC 2023. 10. 25. 17:44

문제점 : 벽 오브젝트와 충돌 시 벽이 존재하는 방향으로 입력을 지속하면 플레이어 오브젝트가 벽 오브젝트와 붙어 중력의 영향을 받지 않고 붙어버리는 현상이 발생.

 

단순히 ray를 이용해 벽이 감지되면 friction항목을 0으로 만들고 감지되지 않으면 원래 값으로 복구할 생각이었으나 friction항목은 Physics material 파일을 따로 생성후 collider inspector에 삽입하는 방식이라 직접적인 접근이 불가했다.

 

 

 

[유니티 강좌] 2D RPG 게임 만들기 - 8 / 벽에 붙는 현상

안녕하세요. 오랜만에 포스팅입니다. 그동안 댓글로 응원해주신 분들 모두 감사드리고 죄송합니다! 현재까지 진행된 프로젝트 압축 파일은 구글 드라이브에 올려놨습니다. 혹시 막히시면 참고

hoil2.tistory.com

이후 알아보니 Platform Effector 2D 컴포넌트를 이용해 측면 마찰을 비활성화 시킬 수 있는 방법을 적용해보았다.

but, 어째서인지 딱 달라붙던 오브젝트가 서서히 내려오는 정도로만 변화가 있을 뿐 마찰이 비활성화 되지 않았다.

수 번 시도해본 뒤 한가지 예상은 아래의 지면을 감지하는 함수때문이지 않을까 싶었다.

 

문제가 예상된 코드는 다음과 같다.

void GroundCheck(){
        isGround = Physics2D.OverlapCircle(checkPos.position, checkRadius, LayerMask.GetMask("groundMask"));
}

위 함수는 플레이어 오브젝트를 중심으로 원을 그린다.

void Move(){
        if(isSlope && isGround && !isJump){	//경사면에 있고 지면이 감지됐을 때
            rigid.velocity = perp * moveSpeed * inputX * -1;
        }else if(!isSlope && isGround){		//경사면이 아니고 지면이 감지됐을 때
            rigid.velocity = new Vector2(inputX * moveSpeed, 0);
        }else if(!isGround){				//지면이 아닐 때
            rigid.velocity = new Vector2(inputX * moveSpeed, rigid.velocity.y);
        }
        Jump();
        
        rigid.velocity = new Vector2(inputX * moveSpeed, rigid.velocity.y);
    }

그 뒤 Move함수에 의해 y값의 속도가 0으로 고정되기 때문이 아닌가 싶었다.

 

그래서 지면을 감지하는 방식을 Raycast로 변경했다.

void GroundCheck(){
        //isGround = Physics2D.OverlapCircle(checkPos.position, checkRadius, LayerMask.GetMask("groundMask"));
        RaycastHit2D isGroundBox = Physics2D.BoxCast(groundChckBoxCol.bounds.center, groundChckBoxCol.bounds.size, 0, Vector2.down, 0, LayerMask.GetMask("groundMask"));
        if(isGroundBox){
            Debug.Log(isGroundBox.collider.name);	//감지된 오브젝트 확인용
            if(isGroundBox.collider.tag == "Land"){	//감지된 오브젝트가 지면일 때
                isGround = true;					//isGround를 참으로 변경
            }
        }else{
            isGround =false;						//지면이 감지되지 않은 경우 isGround를 거짓으로 변경
        }
    }

위 코드와 같이 BoxCast를 사용했고 그 위치와 크기는 plyaer오브젝트 하위에 생성한 빈 오브젝트의 collider와 동일하게 했다.

이 BoxCast에 지면이 감지되면 isGround의 값은 true가 되고 반대의 경우 false로 변경된다.

오브젝트 하단의 초록색 박스가 groundCheckBox이며 해당 오브젝트는 collider 컴포넌트만을 갖고 있다.

 

이후 의도했던 대로 벽면과의 마찰이 사라졌다.

 

이것을 위해 시도했던 것

 

1.플레이어 하위에 빈 오브젝트를 하나 더 생성한다

2.위와 같이 콜라이더를 조정해 준 뒤 콜라이더에 friction이 0으로 설정된 Physics Material 2D파일을 넣는다.

3.isTrigger로 설정한다.

4.이 콜라이더의 크기와 동일하게 BoxCast를 생성한 뒤 벽이 감지되면 isTrigger를 비활성화하여 물리적 충돌을 일으킨다. - friction이 0으로 설정되어 있기 때문에 마찰을 일으키지 않고 미끄러질 것이라고 예상

5.라고 생각하여 코드를 짜보았지만 결국 OverlapCircle만 바꿔준 것으로 문제가 해결되어 코드는 삭제했다.(내 3시간...)