본문 바로가기
게임 프로그래밍/유니티 활용

[유니티 활용] Rigidbody2d 를 이용한 캐릭터의 이동과 점프

by 레오란다 2022. 12. 21.
반응형

캐릭터의 이동과 점프 구현에는 다양한 방법이 존재합니다. 이 번 글에서는 다른 오브젝트와의 상호작용을 처리하기에 좋은 물리엔진을 이용해 아래와 같이 캐릭터의 이동과 점프를 구현하는 방법에 대해 알아보도록 하겠습니다.

 

결과 미리보기

 

 

▶ 준비사항

필요 에셋: SunnyLand 무료 에셋 (없으신 분은 여기를 클릭해 받아주세요)

환경: Android, 1920x1080 landscape

 

 

▶ 바닥 만들기

캐릭터가 밟고 있을 바닥을 만드는 작업입니다. 여러 가지 방법이 있지만 여기서는 Quad 를 이용한 방법으로 만들어 보도록 하겠습니다. 

 

  ▷ 객체 생성

  • Hierarchy 창에서 마우스 우클릭 [3D Object > Quad] 를 선택해 만들고 이름은 Ground 로 변경해 줍니다.
  • Ground 객체의 Transform 설정을 다음과 같이 해줍니다.

Ground 객체의 Transform 설정

  • Ground 객체의 Layer 를 다음과 같이 새롭게 만들어 설정해 줍니다.

Ground 객체에 새로운 Layer 생성

  • 이렇게 하면 새로운 Layer 를 생성할 수 있는 창이 나타납니다. 빈 칸에 Ground 라고 입력하고 다시 Hierarchy 창에서 Ground 객체를 선택합니다.
  • 다시 Inspector 창에서 Layer (위 이미지의 첫 번째 빨간 테두리 부분을 누르면 됩니다.) 를 Ground 로 변경합니다.

 

  ▷ Ground 객체에 사용할 새 Material 생성

  • Project 창에서 Assets의 하위 폴더로 Materials 폴더를 생성합니다. 
  • Materials 폴더에서 마우스 우클릭 [Create > Material] 로 새 material 을 생성하고 이름을 MatGround 로 해줍니다.
  • MatLand 의 Shader 를 [Unlit > Transparent] 로 변경합니다.
  • MatLand 의 Texture 에 경로 [Assets > SunnyLand Artwork > Environment > props] 에 있는 "block-big" 을 연결합니다.
  • "block-big" 이미지의 Wrap Mode 를 Repeat 로 변경 합니다. (block-big 선택 후 Inspector 창에 보면 있습니다. 변경 후 [Apply] 버튼을 눌러야 합니다.)

 

  ▷ Ground 객체에 MatGround 적용

  • Proejct 창에서 경로 [Assets > Materials] 에 있는 MatGround 를 드래그하여 Hierarchy 창에 있는 Ground 객체에 놓으면 Ground 객체의 material 이 MatGround 로 변경됩니다.
  • MatGround 를 펼치고 다음과 같이 설정합니다.

MatGround 세부 설정

* Texture 의 타일 설정을 x 축으로 25 개  y 축으로 5개 한다는 의미입니다. 이 값은 Ground 객체의 Scale 값과 동일합니다.

 

▷ Collider 재설정

  • Ground 객체를 클릭하고 Inspector 창에서 다음과 같은 방법으로 Mesh Collider 를 제거합니다.

Mesh Collider 제거 방법

  • [Add Component > Physics2D] 에서 BoxCollider2D 를 추가합니다.

* Quad 에서 Mesh Collider 를 제거하고 BoxCollider2D 를 추가하는 이유는 Mesh Collider 는 Rigidbody2D 와는 충돌 처리가 되지 않기 때문입니다.

 

 

▶ Player (캐릭터) 객체 만들기

  • 먼저 Project 창에서 경로 [Assets > SunnyLand Artwork > Sprites > player > idle] 로 이동합니다.
  • player-idle-1 을 선택하고 Inspector 창에서 Pixel Per Unit 의 값을 100 > 33 으로 변경합니다.
  • player-idle-1 을 Hierarchy 창에 끌어다 놓으면 Sprite 객체가 생성됩니다. 이름을 Player 로 변경합니다.
  • Player 객체의 [Add Component > Physics 2D] 에서 Rigidbody2D 와 BoxCollider2D 를 추가해 줍니다.
  • Rigidbody2D 의 설정을 다음과 같이 해줍니다.

  • Player 객체에 새로운 스크립트를 추가합니다. 이름은 Player 로 해주세요.
  • 다음은 여기까지 진행했을 때 Player 객체의 Inspector 창입니다.

  • Player 스크립트를 다음과 같이 작성해 줍니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour
{
   Rigidbody2D rig;

   public float moveSpeed;
   public float maxSpeed;
   public float jumpPower;

   // Start is called before the first frame update
   void Start()
   {
      rig = GetComponent<Rigidbody2D>();
   }

   // Update is called once per frame
   void Update()
   {
      // 왼쪽 화살표를 누르고 있는 경우
      if (Input.GetKey(KeyCode.LeftArrow))
      {         
         // 물체에 왼쪽 방향으로 물리적 힘을 가해줍니다. 즉, 왼쪽으로 이동 시킵니다.
         rig.AddForce(Vector2.left * moveSpeed, ForceMode2D.Impulse);

         // velocity 는 물체의 속도입니다. 일정 속도에 도달하면 더 이상 빨라지지 않게합니다.
         rig.velocity = new Vector2(Mathf.Max(rig.velocity.x, -maxSpeed), rig.velocity.y);

         // scale 값을 이용해 캐릭터가 이동 방향을 바라보게 합니다.
         transform.localScale = new Vector3(-1f, 1f, 1f);
      }
      else if (Input.GetKey(KeyCode.RightArrow)) // 오른쪽 화살표를 누르고 있는 경우
      {         
         rig.AddForce(Vector2.right * moveSpeed, ForceMode2D.Impulse);
         rig.velocity = new Vector2(Mathf.Min(rig.velocity.x, maxSpeed), rig.velocity.y);
         transform.localScale = new Vector3(1f, 1f, 1f);
      }
      else if (Input.GetKeyUp(KeyCode.LeftArrow) || Input.GetKeyUp(KeyCode.RightArrow)) // 이동 키를 뗀 경우
      {
         // x 속도를 줄여 이동 방향으로 아주 살짝만 움직이고 거의 바로 멈추게 합니다.
         rig.velocity = new Vector3(rig.velocity.normalized.x, rig.velocity.y);
      }

      // 스페이스바를 누르면 점프합니다.
      if (Input.GetKeyDown(KeyCode.Space))
      {  
         if (IsGrounded())
            rig.AddForce(Vector2.up * jumpPower, ForceMode2D.Impulse);
      }
   }

   // 캐릭터가 땅을 밟고 있는지 체크
   bool IsGrounded()
   {
      // 캐릭터를 중심으로 아래 방향으로 ray 를 쏘아 그 곳에 Layer 타입이 Ground 인 객체가 있는지 검사합니다.
      var ray = Physics2D.Raycast(transform.position, Vector2.down, 1f, 1 << LayerMask.NameToLayer("Ground"));
      return ray.collider != null;
   }
}
  • rig.AddForce 는 객체에 물리적인 힘을 가하는데 사용됩니다. Vector2.left 는 왼쪽 방향, Vector2.right 는 오른쪽 방향으로 물리적 힘을 가하라는 의미입니다. moveSpeed 를 곱해줘서 방향에 힘의 세기를 적용시킵니다. 힘의 세기에 따라 물체 움직임의 속도가 달라지게 됩니다.
  • Physics2D.Raycast 는 특정 방향으로 ray 를 쏘아 주어진 조건에 만족하는 객체가 있는지 판별할 때 사용합니다. 이 코드에서는 Layer 이름이 Ground 인 객체가 단위 유닛 1 의 범위 안에 있는지 조사합니다.
  • 코드를 작성한 다음 Player 객체의 Inspector 창에서 moveSpeed, maxSpeed, jumpPower 의 값을 설정해 주어야 합니다. 저는 차례대로 0.5, 5, 5 를 설정하였습니다. 

 

완성입니다. Play 해보시면 좌우 화살표키로 캐릭터를 움직일 수 있고 스페이스바로 점프할 수 있습니다. 점프 상태에서도 좌우로 이동이 가능합니다.

 

이 방식의 캐릭터 이동과 점프는 아마도 플랫포머 게임에서는 가장 많이 구현하는 방식이 아닐까 생각합니다. 여러 가지 설정을 바꿔 보면서 테스트 해보시면 구현 원리를 쉽게 이해하실 수 있으리라 생각합니다. 

 

 

반응형

댓글