쿠키런 스타일 2D 러너 게임 제작
페어 프로그래밍으로 진행
유니런(11~13장)에서 배운 내용을 활용하여, 유니런 에셋을 재활용해 쿠키런 스타일의 2D 러너 게임을 새 씬에서 처음부터 만든다.
진행 방식
- 2인 1팀, 드라이버(코드 작성)와 네비게이터(검토/방향 제시)로 나누어 진행한다.
- 닷지 과제에서 맡았던 역할의 반대 역할로 진행한다.
- 유니런 프로젝트의 에셋(스프라이트, 오디오 등)을 기본으로 사용한다.
- 부족한 에셋(코인, 장애물 등)은 팀별로 직접 검색하여 추가한다.
- 유니런의 기존 씬과 스크립트를 복사하지 않고, 새 씬에서 스크립트를 직접 작성한다.
단계 1. 기본 러너 구조
- 새 씬(CookieRun) 생성.
- 배경 무한 반복 스크롤 구현.
- 낙사를 감지하는 데드존 구현
단계 2. 캐릭터 액션
- 점프 / 이단 점프 구현.
- 슬라이드(숙이기) 구현:
- 슬라이드 중 콜라이더 크기를 줄여 공중 장애물 회피.
- 슬라이드 키를 떼면 원래 크기로 복귀.
- 각 상태에 맞는 애니메이션 적용. (Run, Jump, Die)
- 슬라이드 애니메이션은 Die 애니메이션으로 대체한다.
- 애니메이터 컨트롤러에서 파라미터와 전이를 직접 구성.
단계 3. 발판 생성 & 장애물 & 코인
- 발판 + 장애물 + 코인이 조합된 Prefab을 여러 종류 만든다. (예: 빈 발판, 바닥 장애물 발판, 공중 장애물 발판, 코인 발판, 낙사 구간(구멍) 등)
- 오브젝트 풀링으로 Prefab들을 미리 생성해두고, 랜덤으로 하나를 골라 배치한다.
- 장애물 최소 2종 구현:
- 바닥 장애물: 점프로 회피
- 공중 장애물: 슬라이드로 회피
- 코인은 트리거 충돌로 획득 처리.
단계 4. 에너지 시스템 & 게임 매니저 & UI
- 에너지 게이지 구현:
- 시간이 지남에 따라 에너지가 자동으로 감소한다.
- 장애물에 충돌하면 에너지가 크게 감소한다.
- 코인 획득 시 에너지가 소량 회복된다.
- 낙사(구멍) 시 에너지가 대량 감소한다.
- 에너지가 0이 되면 게임오버.
- 게임 전체를 관리하는 GameManager 구현. (점수, 에너지, 게임오버/재시작 관리)
- UI 구성: 코인 수 표시, 에너지 게이지, 게임오버 화면 + R키로 재시작.
모든 코드를 작성하기엔 너무 복잡할 것 같아 처음 사용하는 코드들만 정리해보겠다.
1단계 ~ 2단계 의 2단 점프 까지는 UinRun 에서 구현해봤으므로 넘어가지만 슬라이드(숙이기)가 추가 되었다.
슬라이드(숙이기) 구현
[SerializeField]
private Vector2 colliderSlidingOffset;
[SerializeField]
private Vector2 colliderSlidingSize;
private Vector2 colliderOriginalOffset;
private Vector2 colliderOriginalSize;
colliderSlidingOffset: 슬라이드 중 Collider의 위치 오프셋colliderSlidingSize: 슬라이드 중 Collider의 크기colliderOriginalOffset: 원래 Collider의 위치 오프셋colliderOriginalSize: 원래 Collider의 크기
playerCollider = GetComponent<BoxCollider2D>();
colliderOriginalSize = playerCollider.size;
colliderOriginalOffset = playerCollider.offset;
Awake()에서 실행하며, 슬라이드하기 전의 Collider 크기와 위치를 저장한다.
if(Input.GetButton("Slide") && isGrounded)
{
StartSlide();
}
if(Input.GetButtonUp("Slide") || !isGrounded)
{
EndSlide();
}
Input.GetButton("Slide"): 슬라이드 버튼을 누르고 있는지 확인isGrounded: 플레이어가 바닥에 있는지 확인StartSlide(): 슬라이드 시작Input.GetButtonUp("Slide"): 슬라이드 버튼을 놓았는지 확인!isGrounded: 플레이어가 공중에 있는지 확인EndSlide(): 슬라이드 종료
private void StartSlide()
{
animator.SetBool("Sliding", true);
playerCollider.offset = colliderSlidingOffset;
playerCollider.size = colliderSlidingSize;
}
Sliding애니메이터 변수를true로 설정한다.- Collider의 오프셋을 슬라이드용 값으로 변경한다.
- Collider의 크기를 슬라이드용 크기로 변경한다.
private void EndSlide()
{
animator.SetBool("Sliding", false);
playerCollider.offset = colliderOriginalOffset;
playerCollider.size = colliderOriginalSize;
}
Sliding애니메이터 변수를false로 설정한다.- Collider의 오프셋을 원래 값으로 복구한다.
- Collider의 크기를 원래 크기로 복구한다.
핵심 코드 관계 정리

3단계 역시 UniRun에서 대부분 제작해본 부분이며 Coin이 추가 되었지만 단순한 구현으로 제작되었으므로 넘어가도록 하겠다.
4단계에서 에너지 게이지를 구현하는 부분을 설명하도록 하겠다.
에너지 게이지 구현
[Header("HP")]
[SerializeField]
private int playerMaxHp = 100;
private int playerCurrnetHP = 100;
playerMaxHp: 플레이어의 최대 체력playerCurrnetHP: 플레이어의 현재 체력[Header("HP")]: Unity Inspector에서 체력 관련 변수를 구분하는 제목[SerializeField]: private 변수도 Inspector에서 확인하고 수정할 수 있도록 설정
playerCurrnetHP = playerMaxHp;
Awake()에서 실행하며, 플레이어의 현재 체력을 최대 체력으로 설정한다.
[Header("Damage")]
[SerializeField]
private int hitDamage = 25;
[SerializeField]
private int fallingDamage = 50;
[SerializeField]
private int heal = 5;
hitDamage: 장애물 등에 부딪혔을 때 받는 피해량fallingDamage: 낙하 시 받는 피해량heal: 코인을 획득했을 때 회복하는 체력
public void OnHit(int damage)
{
playerCurrnetHP = Math.Clamp(playerCurrnetHP + damage, 0, 100);
gameManager.UpdateHpBar((float)playerCurrnetHP / playerMaxHp);
if(playerCurrnetHP <= 0)
{
Die();
}
}
OnHit(int damage): 현재 체력을 변경하는 함수playerCurrnetHP + damage: 현재 체력에 전달받은 값을 더함Math.Clamp(..., 0, 100): 체력이 0보다 작아지거나 100을 초과하지 않도록 제한UpdateHpBar(...): 변경된 체력에 맞춰 HP바를 갱신playerCurrnetHP <= 0: 체력이 0 이하라면 사망 처리
private void OnTriggerEnter2D(Collider2D collision)
{
if(collision.tag == "Dead")
{
OnHit(-fallingDamage);
jumpCount = 0;
playerRigid.linearVelocity = Vector2.zero;
gameManager.PlayerRespawn();
}
if(collision.tag == "OnHit")
{
OnHit(-hitDamage);
}
if(collision.tag == "Coin")
{
OnHit(heal);
}
}
| 조건 | 실행되는 구문 | 결과 |
|---|---|---|
Dead 태그와 충돌 | OnHit(-fallingDamage) | 체력 50 감소 |
OnHit 태그와 충돌 | OnHit(-hitDamage) | 체력 25 감소 |
Coin 태그와 충돌 | OnHit(heal) | 체력 5 회복 |
private void Die()
{
playerRigid.linearVelocity = Vector2.zero;
playerRigid.simulated = false;
animator.SetTrigger("Die");
dieSound.Play();
gameManager.OnPlayerDead();
}
- 플레이어의 이동을 중단
- Rigidbody2D 물리 시뮬레이션 비활성화
- 사망 애니메이션 재생
- 사망 사운드 재생
- GameManager에 사망 사실 전달
핵심 코드 관계 정리

점점 유니티 엔진을 만지며 재미를 느끼고 있는 것 같다.
얼른 다음 게임도 만들어보고 싶어지고 내가 기획하는 게임도 만들어 보고 싶다.
오늘은 이론 수업도 배웠지만 이론 수업은 아직 머릿속에 정리가 되지 않았기에 더 정리 후에 글을 적도록 하겠다.
오늘 선생님께서 초반부터 면접에 대한 질문들을 미리 숙지해두는 것이 좋다고 말씀하셨다.
주말에는 지금 까지 배웠던 단어, 사용법 등을 정리하여 실제 면접에서 어떻게 대답하면 좋을지 정리해보는 시간을 가지려 한다.



