728x90
반응형

아직도 정해지지 않은 썸네일 이미지...

미리보기

구현 기능

1. 좌우이동

2. 점프/이단점프

3. Camera Following

 

목차

     

    머리말

    기획은 어느정도 했으니 본격적으로 프로그래밍에 들어가보자

    자세한 기획은 비공개

    2D Platformer는 예전에 만들었던 적이 있으니 참고자료를 꽤 찾아놨다.

    https://www.youtube.com/playlist?list=PLy78FINcVmjA0zDBhLuLNL1Jo6xNMMq-W 

     

    2D Platformer Controller

     

    www.youtube.com

     

    위 영상들을 기반으로 제작할 예정이다.

     

    1. Setting Up Map

    먼저 Test Map을 만들어 준다.

    Asset에 있는 기본 2D Platform을 기반으로 여러가지 동작을 테스트할 Object들을 추가한다.

     

    2. Horizontal Movement

    2-1. Input to move

    단순하게 Horizontal Input을 받아서 movementInputDirection에 저장하고 Rigidbogy의 velocity에 적용시켰다.

    movementInputDirection = Input.GetAxisRaw("Horizontal");
    rb.velocity = new Vector3(movementSpeed * movementInputDirection, rb.velocity.y, 0);

     

    2-2. Player Facing

    다음은 Player의 바라보는 방향을 바꿔준다.

    isFacingRight와 movementInputDirection을 체크해서 Flip()한다.

    if(isFacingRight && movementInputDirection < 0)
    {
        Flip();
    }
    else if(!isFacingRight && movementInputDirection > 0)
    {
        Flip();
    }

     

    3. Jump

    점프 또한 마찬가지로 Rigidbody의 속도를 설정한다.

    rb.velocity = new Vector3(rb.velocity.x, jumpForce, rb.velocity.z);

    크게 2가지 문제가 보인다.

    - 느린 낙하

    - 무한점프

     

    3-1. 느린 낙하 Fix

    가장 먼저 떠오르는 해결책은 Mass 증가

    영상에서는 Rigidbody2D의  Gravity Scale을 조절했지만 Rigidbody(3D)에는 없다.
    왜인지 모르겠으나 전혀 달라지지 않았다...

    Mass를 1에서 1000000으로 증가시켜도 딱히 달라지는 게 없다.

    Asset의 애니메이션에 문제가 있는 듯 하다.

     

    다음 방법은 Gravity Scale을 직접 만들어주는 것

    Gravity.cs을 만들고 아래 코드를 FixedUpdate()에 넣은 뒤 Player에 추가했다.

    rb.AddForce(new Vector3(0, gravityScale, 0));

    적당히 gravityScale을 -50, JumpForce를 25로 해주니 그럭저럭 괜찮아 보인다.

     

    3-2. 무한점프 Fix

    무한점프는 현재 땅이 있는지 없는지 체크하고 점프 가능여부를 판단하게 하면 된다.

    Player에 GroundCheck라는 GameObject를 추가하고 거기서부터 땅이 있는지 체크하게 한다.

    isGrounded라는 bool 변수를 만들고 특정 LayerMask를 가진 GameObject가 감지되면 true로 한다.

    isGrounded = Physics.Raycast(groundCheck.position, Vector3.down, distanceToGround, whatIsGround);

     

    또한 Gizmos를 이용해 어디까지 체크하고 있는지 확인하자.

    private void OnDrawGizmos()
    {
        Gizmos.color = Color.red;
        Gizmos.DrawLine(groundCheck.position, groundCheck.position + Vector3.down * distanceToGround);
    }

    Gizmos가 잘 안보여서 잠시 Light off

     

    4. Double Jump

    Doube Jump를 구현하기 위해 amountOfJumps와 amountOfJumpLefts라는 변수를 선언한다.

    각각 가능한 Jump 회수, 남은 Jump 회수이다.

    그리고 canJump라는 bool 변수를 추가한다.

     

    isGrounded가 true이면 amountOfJumpLefts에 amountOfJumps를 할당하고

    amountOfJumpLefts가 0보다 클 때 canJump를 true로 한다.

    또한 Jump가 실행되면 amoutOfJumpLefts--; 한다.

        private void CheckCanJump()
        {
            if (isGrounded && rb.velocity.y <= 0)
            {
                amountOfJumpsLeft = amountOfJumps;
            }
    
            if(amountOfJumpsLeft <= 0)
            {
                canJump = false;
            }
            else
            {
                canJump = true;
            }
        }
        private void Jump()
        {
            if(canJump)
            {
                rb.velocity = new Vector3(rb.velocity.x, jumpForce, rb.velocity.z);
                amountOfJumpsLeft--;
            }
        }

     

    5. Camera Following

    지금은 카메라가 고정되어 있어 캐릭터가 화면 밖으로 나가면 안보인다.

    스크립트를 만드는 것도 괜찮지만 Unity에서 제공하는 Cinemachine을 사용하면 간단하게 구현할 수 있다.

    5-1. Cinemachine

    Cinemachine은 캐릭터를 따라가는 카메라를 구현할 수 있는 Package이다.

     

    지금은 3D 환경에서 2D 게임을 구현하고 있으니 GameObject - Cinemachine - 2D Camera를 생성한다.

    이름은 Player Camera로 지정했다.

    그러면 자동으로 Main Camera에 Cinemachine이 추가된다.

     

    이후 Player Camera에서 Follow에 Player를 넣어준다.

     

    5-2. Offset and Damping

    괜찮기는 하지만 2D Platfomer 게임에서 캐릭터가 정중앙에 위치하고 있지 않는다.

    CinemachineVirtualCamera의 Tracked Object Offset을 조절해주자.

     

    그리고 따라가는 것 중에서 Y축을 조금 느리게 하기 위해 Damping을 조절했다.

     

    6. Animation

    이제 아무것도 안하고 이동만 하는 캐릭터에 애니메이션을 적용한다.

    Animation Controller Diagram

            anim.SetBool("isRunning", isRunning);
            anim.SetBool("isGrounded", isGrounded);
            anim.SetFloat("y_velocity", rb.velocity.y);
            anim.SetInteger("AmountOfJumpsLeft", amountOfJumpsLeft);

     

    Input과 Rigidbody 등을 animator의 Parameter에 적용시킨다.

    각 애니메이션들을 Parameter에 따라 변경한다.

     

    7. 기타 잡버그

    7-1. Platform Stick

    캐릭터와 Platform 사이에 마찰 때문에 이동키를 누르고 있으면 벽에 달라붙어 있는다.

     

    Physic Material를 만들어서 Friction을 모두 0으로 만들고 Platform과 Player에 적용시켜준다.