본문 바로가기

Unity 2D 미니 프로젝트 - 🕹️ Sparta Metaverse

@코야딩구2025. 7. 28. 13:24

🔧 주요 기능

🚶 캐릭터 이동 및 맵 탐색

- WASD 키를 통해 캐릭터가 자유롭게 맵을 이동하도록 구현했다.
- Tilemap 기반의 맵 위를 자연스럽게 탐험할 수 있도록 했다.

🗺️ 맵 설계 및 상호작용 영역

- 간단한 2D 맵을 설계하고, 특정 영역에 진입했을 때 상호작용 이벤트가 발생하도록 구성했다.
- 특정 영역에서는 미니게임 씬으로 자동 전환되도록 처리했다.

🎯 미니게임 종류

- Flappy Plane: 장애물을 피하며 가능한 멀리 날아가는 것을 목표로 하는 횡스크롤 액션 게임

- The Stack: 좌우로 움직이는 블록을 타이밍에 맞춰 쌓아 올리는 집중력 기반의 스택 게임

- 탑다운 미니 던전: 적을 처치하며 층을 돌파해 나가는 탑다운 방식의 간단한 던전 게임

🎮 미니 게임 점수 시스템

- 미니게임 진행 중에는 점수를 실시간으로 UI에 반영되도록 했다.

🔁 게임 종료 및 복귀

- 미니게임 종료 시에는 자동으로 메인 맵으로 복귀하도록 구성했다.
- 결과 UI를 통해 현재 점수와 최고 기록을 동시에 출력하도록 구현했다.

🎥 카메라 추적 기능

- 플레이어가 이동하면 카메라가 자연스럽게 따라오도록 했다.
- 맵 경계를 벗어나지 않도록 제한 처리를 추가했다.

🧑‍🤝‍🧑 NPC와의 대화 시스템

- NPC 근처에 접근하면 대화창이 자동으로 활성화되도록 했다.
- E 키를 입력하면 대화가 시작되도록 구성했다.

🎨 캐릭터 외형 변경

- 특정 NPC와 상호작용하면 플레이어 캐릭터의 외형(스프라이트)을 변경할 수 있도록 구현했다.


🧩 트러블슈팅

1. 비활성화된 GameObject에서 코루틴 실행 실패

🧭 배경

- UI 전환 기능을 구현하던 중, 특정 GameObject를 SetActive(false)로 비활성화한 상태에서 코루틴을 실행했는데 정상적으로 동작하지 않는 문제가 발생했다.

🚨 문제

- Unity에서는 비활성화된 GameObject에서 StartCoroutine()을 호출해도 내부 로직이 실행되지 않는다.

// UI.cs 
gameObject.SetActive(false); 
StartCoroutine(SomeCoroutine());
IEnumerator SomeCoroutine() 
{ 
// ❌ 작동하지 않음 
yield return new WaitForSeconds(1f); 
Debug.Log("코루틴 내부 로직"); 
}

✅ 해결

- 코루틴은 활성화된 GameObject에서만 안정적으로 실행되기 때문에, 코루틴 실행은 별도의 Manager 객체에서 처리하도록 구조를 분리했다.
- 이 경험을 통해 기능별 책임 분리와 GameObject의 생명주기 관리의 중요성을 인식하게 되었다.


2. 캐릭터 변경 시 SpriteRenderer 및 Animator가 교체되지 않음

🧭 배경

- NPC와의 상호작용을 통해 플레이어의 외형을 커스터마이징할 수 있도록,
- 다른 캐릭터 프리팹에서 SpriteRenderer와 Animator를 가져와 현재 플레이어에 적용하는 기능을 구현했다.

🚨 시도

- 프리팹을 참조해 내부에 포함된 SpriteRenderer 및 Animator 컴포넌트를 현재 플레이어 오브젝트에 직접 할당했다.

// 프리팹 charBase에 캐릭터의 SpriteRenderer와 Animator 설정 
SpriteRenderer tmpSP = GetComponentInChildren<SpriteRenderer>(); 
tmpSP = charBase.characterRenderer; // ❌ 변수만 바뀜, 실제 적용되지 않음 
Animator tmpAnim = GetComponentInChildren<Animator>(); 
tmpAnim = charBase.characterAnimator; // ❌ 변수만 바뀜, 실제 적용되지 않음

🔍 문제 발견

- 위 코드는 단순히 로컬 변수의 참조만 바꾼 것이고,
플레이어 오브젝트의 SpriteRenderer 및 Animator 컴포넌트 자체에는 아무런 영향을 주지 못했다.
- Unity에서는 컴포넌트를 직접 교체할 수 없고, 내부 속성만 변경 가능한 구조임을 간과했다.

✅ 해결

- 기존 컴포넌트를 그대로 유지하면서, 필요한 속성만 덮어쓰는 방식으로 수정했다.

SpriteRenderer playerRenderer = GetComponentInChildren<SpriteRenderer>();
playerRenderer.sprite = charBase.characterRenderer.sprite;

Animator playerAnimator = GetComponentInChildren<Animator>();
playerAnimator.runtimeAnimatorController = charBase.characterAnimator.runtimeAnimatorController;

🏁 결말

- Unity의 구조적 특성상 컴포넌트를 직접 바꾸는 것이 불가능하다는 점을 인지했고,
속성만 변경하는 방식으로 커스터마이징 기능을 안정적으로 구현할 수 있었다.


🛠️ 사용한 기술 스택

- Unity 2022.3.17f1

- C#

목차