유니티로 2D 플랫포머 게임 개발에 도전한 초보자 분들 중에, 플레이어의 움직임을 어떤 식으로 구현해야 할 지 막막해 하는 분들이 있습니다. 이런 분들을 대상으로 가장 기본적인 플레이어 움직임을 C# 스크립트로 구현하는 방법을 소개합니다.
프로젝트 생성
제일 먼저 유니티 허브에서 새 2D 프로젝트를 생성합니다.
바닥 스프라이트 생성
다음으로 Assets > Create > 2D > Sprites > Square 를 선택하여 기본 스프라이트를 하나 생성합니다.
이름을 Platform 이라고 지정해 주겠습니다.
드래그해서 씬 하이어라키에 갖다 놓겠습니다. 그리고 가로 스케일을 10으로 늘리겠습니다.
Sprite Renderer에서 색깔을 바꿔 줍니다.
플레이어 스프라이트 생성
이제 같은 요령으로 플레이어 스프라이트를 생성하겠습니다. 이번에는 캡슐(Capsule) 모양을 선택합니다.
이번에는 이름을 Player 로 지정합니다.
하이어라키 뷰로 드래그해서 갖다 놓습니다. 스케일을 0.5로 줄입니다.
색깔을 바꾸고, 위치를 조정해서 플랫폼 위로 옮깁니다.
잘 보면 게임 오브젝트의 이름이 바뀌지 않은 것을 알 수 있습니다. 이 경우 다음과 같이 이름을 바꿔 줍니다. (안 바꿔도 상관은 없습니다)
충돌체와 리지드바디 2D 추가
이제 충돌 감지를 위한 컴포넌트들을 추가하겠습니다. 우선 Player 를 선택하고 Add Component 버튼을 누릅니다. Capsule Collider 2D 를 검색해서 추가합니다.
리지드바디 2D 도 찾아서 붙여 줍니다.
현재 스프라이트는 캡슐 형태라 나중에 좌우로 움직일 때 넘어질 수 있습니다. 이를 방지하기 위해 Rigidbody 2D 의 Constraints 를 열고 Freeze Rotation 을 체크해 줍니다.
다음으로는 Platform 을 선택하고, Box Collider 2D 를 붙여 주겠습니다. 여기에는 리지드바디가 필요 없으니 Box Collider 2D 만 붙여 주시기 바랍니다.
플레이어 캐릭터 동작 스크립트 작성
이 코드에서는 가장 간단한 플레이어 캐릭터 동작만을 구현합니다. 예를 들어 2D 환경에서 플레이어 캐릭터의 좌우 이동 및 점프 기능은 다음과 같은 방식으로 작성할 수 있습니다.
스크립트 생성
먼저, Unity 스크립트를 생성하고 PlayerMovement라는 클래스를 정의합니다.
이제 이 스크립트 파일을 더블 클릭해서 비주얼 스튜디오를 열겠습니다. 기본적으로 MonoBehaviour를 상속받은 빈 스크립트가 생성됩니다.
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
void Start()
{
}
void Update()
{
}
}
필요한 변수 선언
이제 이동 속도를 나타내는 moveSpeed라는 float 변수를 선언하고 기본값을 5f로 지정합니다.
public class PlayerMovement : MonoBehaviour
{
public float moveSpeed = 5f;
void Start()
{
}
...
}
다음으로, 점프 높이를 결정하는 jumpForce라는 float 변수를 선언하고 기본값을 7f로 지정합니다.
public class PlayerMovement : MonoBehaviour
{
public float moveSpeed = 5f;
public float jumpForce = 7f;
void Start()
...
}
점프 가능 여부를 결정하기 위해 groundCheck라는 Transform 변수와 groundLayer라는 LayerMask 변수를 선언합니다.
public class PlayerMovement : MonoBehaviour
{
public float moveSpeed = 5f;
public float jumpForce = 7f;
public Transform groundCheck;
public LayerMask groundLayer;
void Start()
...
}
이제 Rigidbody2D 컴포넌트를 참조할 rb 변수와 땅에 닿았는지 확인하기 위한 isGrounded 불 변수를 선언합니다. 또한, 땅에 닿았는지 확인하는 데 사용되는 원의 반지름을 나타내는 groundCheckRadius 변수를 0.2f로 초기화합니다.
public class PlayerMovement : MonoBehaviour
{
public float moveSpeed = 5f;
public float jumpForce = 7f;
public Transform groundCheck;
public LayerMask groundLayer;
private Rigidbody2D rb;
private bool isGrounded;
private float groundCheckRadius = 0.2f;
...
}
Start 및 Update 메서드 구현
Start() 메서드에서 Rigidbody2D 컴포넌트를 가져와 rb 변수에 할당합니다.
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
Update() 메서드에서 먼저 groundCheck 위치를 중심으로 반지름이 groundCheckRadius인 원이 groundLayer에 겹치는지 확인하여 isGrounded 변수에 할당합니다.
void Update()
{
isGrounded = Physics2D.OverlapCircle(groundCheck.position, groundCheckRadius, groundLayer);
}
이제, 수평 입력을 받아 moveInput 변수에 저장합니다. 이 값은 -1, 0, 또는 1이 될 수 있으며, 각각 왼쪽, 정지, 오른쪽을 나타냅니다.
void Update()
{
isGrounded = Physics2D.OverlapCircle(groundCheck.position, groundCheckRadius, groundLayer);
float moveInput = Input.GetAxis("Horizontal");
}
Rigidbody2D의 속도를 업데이트하여 캐릭터가 좌우로 움직이도록 합니다. moveInput에 moveSpeed를 곱하고, y축 속도는 그대로 유지합니다.
void Update()
{
isGrounded = Physics2D.OverlapCircle(groundCheck.position, groundCheckRadius, groundLayer);
float moveInput = Input.GetAxis("Horizontal");
rb.velocity = new Vector2(moveInput * moveSpeed, rb.velocity.y);
}
마지막으로, 점프 키가 눌렸을 때(Input.GetButtonDown(“Jump”))와 캐릭터가 땅에 있을 때(isGrounded) 점프를 실행합니다. Rigidbody2D의 y축 속도를 jumpForce로 설정하여 캐릭터가 위로 점프하도록 합니다.
void Update()
{
isGrounded = Physics2D.OverlapCircle(groundCheck.position, groundCheckRadius, groundLayer);
float moveInput = Input.GetAxis("Horizontal");
rb.velocity = new Vector2(moveInput * moveSpeed, rb.velocity.y);
if (Input.GetButtonDown("Jump") && isGrounded)
{
rb.velocity = Vector2.up * jumpForce;
}
}
완성된 코드
이제 완성된 코드는 다음과 같습니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public float moveSpeed = 5f;
public float jumpForce = 7f;
public Transform groundCheck;
public LayerMask groundLayer;
private Rigidbody2D rb;
private bool isGrounded;
private float groundCheckRadius = 0.2f;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
void Update()
{
isGrounded = Physics2D.OverlapCircle(groundCheck.position, groundCheckRadius, groundLayer);
float moveInput = Input.GetAxis("Horizontal");
rb.velocity = new Vector2(moveInput * moveSpeed, rb.velocity.y);
if (Input.GetButtonDown("Jump") && isGrounded)
{
rb.velocity = Vector2.up * jumpForce;
}
}
}
Player 에 스크립트 추가
이제 하이어라키 뷰에서 Player를 선택하고, 방금 작성한 PlayerMovement 스크립트를 플레이어 캐릭터의 게임 오브젝트에 추가합니다.
충돌 체크 기준점 추가
다음으로 캐릭터가 서있을 때 땅에 닿는 부분 근처에 새로운 빈 게임 오브젝트를 생성하고, 이 오브젝트를 groundCheck로 지정합니다. 이 오브젝트는 캐릭터가 땅에 닿았는지 확인하는 기준점 역할을 합니다.
먼저 Player 를 선택하고 마우스 우측 버튼 > Create Empty 를 선택해서 빈 게임 오브젝트를 만듭니다.
이름을 groundCheck 로 변경하고 Y 값을 -1로 조정해서 플레이어 캐릭터 바닥에 맞춥니다.
이제 Player 를 선택하고, 방금 만든 groundCheck 를 드래그해서 Player Movement 스크립트의 Ground Check 에 갖다 놓습니다.
Ground 레이어 생성
이제 지면(Platform)에 별도의 레이어 (예: “Ground”)를 지정하여 지상 오브젝트를 분류해야 합니다. 이를 위해 먼저 Platform 을 선택하고, 인스펙터 상단의 Layer 를 선택한 뒤 ‘Add Layer’를 클릭합니다.
빈 레이어를 찾아 Ground 라는 이름을 지정해 줍니다.
다시 Platform 을 선택하고, Layer 를 방금 새로 만든 Ground 로 바꿔 줍니다.
이제 마지막으로 Player 를 선택한 뒤, PlayerMovement 스크립트에서 Ground Layer 변수에 Ground 레이어를 할당합니다. 이 레이어는 캐릭터가 땅에 닿았는지 판단하는 데 사용됩니다.
이제 모든 준비가 끝났습니다. 코드가 원하는대로 동작하도록 설정되면, 플레이어는 좌우 방향키나 A와 D 키를 사용하여 좌우로 움직일 수 있습니다. 또한, 스페이스바를 눌러 점프할 수 있습니다. 이때, 캐릭터가 땅에 닿아 있어야만 점프가 가능하며, 점프 중에는 다시 점프할 수 없습니다. 이 기능들은 2D 플랫포머 게임에서 일반적으로 사용되는 기본 움직임입니다.
게임 플레이 화면
다음은 게임을 실행한 장면의 영상입니다.
더 공부할 자료 - 개발 능력 다양화를 위한 학습의 필요성
유니티 엔진의 대안으로서, 인디 개발자들에게 선풍적인 인기를 끌고 있는 엔진이 바로 고도 엔진입니다. 혹시 고도 엔진을 배워 보려고 하신다면, 다음의 온라인 강의를 체크해 보시기 바랍니다.