게임 개발 일지/유니티 엔진 공부

11. 유니티 2D 게임 제작 - 점프 구현

인텔리킴 2024. 4. 19. 16:29

물리력을 이용한 점프

먼저 점프는 단발적인 입력에 속하기 때문에 Update 함수를 이용해 구현해야함

 

    if (Input.GetButtonDown("Jump"))
    {
        rigid.AddForce(new Vector2(0, jumpPower), ForceMode2D.Impulse);
    }

 

먼저 이동과 같은 방법으로 구현해봄

 

 

중력과 공기저항과 같은 문제로 인해 떨어지는 속도가 매우 느리게 떨어짐

 

 

첫번째 방법으로는 ProJect Setting 의 Physics에서 변경해서 가능

 

혹은 Rigidbody에서 Gravity Scale을 변경함으로써 가능

 

점프 애니메이션 적용

현재는 점프할때 그냥 공중으로 올라갈뿐이기 때문에 점프 애니메이션을 추가할 필요성이 생김

 

먼저 이전과 같이 애니메이터 편집

 

        if (Input.GetButtonDown("Jump"))
        {
            if (isJump == false)
            {
                animator.SetBool("isJumping", true);
                rigid.AddForce(new Vector2(0, jumpPower), ForceMode2D.Impulse);
                isJump = true;
            }
        }

이후 점프를 다루는 if 문에 

setBool을 이용해 애니메이션 재생시킴

 

하지만 이 코드를 이용하면 공중에서 무한으로 점프가 가능해지는 문제가 생김

이를 해결하기위해 레이캐스트 사용

 

레이캐스트

*RayCast : 오브젝트 검색을 위해 Ray를 쓰는 방식

 

Debug.DrawRay(rigid.position, Vector3.down, new Color(0, 1, 0));

Editor 상에서 Ray가 그려짐

먼저 코드를 입력해 레이가 그려지는것을 확인해봄

 

        RaycastHit2D rayHit = Physics2D.Raycast(rigid.position, Vector2.down, 1);

        if (rayHit.collider != null ) {
            Debug.Log(rayHit.collider.name);
        }

*RayCastHit : Ray에 닿은 오브젝트의 정보를 저장

레이를 쏘고 레이에 맞은 오브젝트의 정보를 불러옴

 

그러나 RayCastHit는 관통이 되지 않기 때문에 플레이어의 중심점으로부터 나온

Ray는 플레이어의 RigidBody에 맞기 떄문에 플레이어의 정보가 불러와지게 됨

 

*LayerMask : 물리효과를 구분하는 정수값

물리에서 필터와 같이 작용하는 Layer를 이용

tag는 string과 같이 간단한 식별자지만 Layer는 다른 레이어끼리 부딫히지 않게 설정할 수 있는 식별자

 

tag와 같은 방식으로 레이어를 새로 하나 작성

 

RaycastHit2D rayHit = Physics2D.Raycast(rigid.position, Vector2.down, 1, LayerMask.GetMask("Platform"));

*LayerMask.GetMask("레이어이름") : 특정 레이어에게만 레이가 부딫힐수 있게 함

 

이를 이용하면 레이가 특정 레이어에게만 반응해서 정보를 불러오는것을 볼 수 있음

 

        if (rayHit.collider != null ) {
            {
                if(rayHit.distance < 0.5f)
                {
                    Debug.Log(rayHit.collider.name);
                }
            }
        }

.distance : Ray에 닿았을 때의 거리 

 

 

distance를 이용하면 거리가 가까워지지않는다면 로그가 발생하지 않는것을 볼 수 있음

이를 이용해 점프 애니메이션 재생 코드 작성

 

        RaycastHit2D rayHit = Physics2D.Raycast(rigid.position, Vector2.down, 1, LayerMask.GetMask("Platform"));

        if (rayHit.collider != null ) {
            {
                if(rayHit.distance < 0.5f)
                {
                    animator.SetBool("isJumping", false);
                }
            }
        }

하지만 이대로 빌드하면

플레이어가 이미 바닥과 닿고 있는 상태에서 점프하기 때문에

위 코드가 상시 실행되어 isJumping가 항상 false상태가 되어있기에

점프 애니메이션이 아예 실행이 되지않음

 

        if(rigid.velocity.y < 0)
        {
            RaycastHit2D rayHit = Physics2D.Raycast(rigid.position, Vector2.down, 1, LayerMask.GetMask("Platform"));

            if (rayHit.collider != null)
            {
                {
                    if (rayHit.distance < 0.5f)
                    {
                        animator.SetBool("isJumping", false);
                    }
                }
            }
        }

점프 애니메이션 재생

if 플레이어가 하강하고 있을 때(y축 속도가 0이하일 때) 라는 조건을 추가함으로써

하강을 하다 바닥과 가까워 졌을때만 isJumping이 false가 되어 idle 애니메이션으로 돌아가게 함

 

하지만 이경우에 아직 무한점프는 된다는 문제점이 있음

 

무한 점프 해결

        //점프
        if (Input.GetButtonDown("Jump") && !animator.GetBool("isJumping"))
        {
                animator.SetBool("isJumping", true);
                rigid.AddForce(new Vector2(0, jumpPower), ForceMode2D.Impulse);
        }

 

animator의 매개변수 상태도 if문의 조건으로 가져올 수 있음

*.GetBool : bool 매개변수의 값을 가져옴

 

정리

레이캐스트

가상의 빔을 쏴서 오브젝트를 검색하는 기능

RaycastHit2D rayHit = Physics2D.Raycast(rigid.position, Vector2.down, 1, LayerMask.GetMask("Platform"));

 

RaycastHit 변수를 이용해서 특정 레이어에 반응하는 방향이 정해진 ray를 발사할 수 있음

LayerMask.GetMask("레이어이름") : 특정 레이어에게만 레이가 부딫힐수 있게 함

레이캐스트변수.distance : Ray가 닿았을때의 거리

animator의 매개변수 상태도 불러올 수 있음