1. 프로젝트 개요
마법사가 우연히 던전앞에서 주운 룬스톤으로 던전의 비밀을 밝혀 보물을 찾는다는 컨셉의 퍼즐 탈출 게임입니
- 게임명 : Rune Dungeon
- 장르 : 2D, 퍼즐, 탈출
- 플랫폼 : PC Web / Windows
- 핵심 기술 : Unity, C#
- 개발기간 : 2025.11.21 ~ 2025.11.27 ( 1주 )
- 프로젝트 깃허브 주소 : https://github.com/Dokkaeb/RuneDungeon
시연영상
2. 클래스 설계
이번 프로젝트에서 사용한 클래스들과 사용한 주요 기술들입니다
- 플레이어 : 상태 패턴을 이용하여 각 상태 분리
- 매니저 : 싱글톤을 이용하여 매니저 설계
- 적(함정) : BT를 이용한 적 AI관리
- UI : MVC 패턴을 사용하여 구현
- 카메라 : 시네머신 사용
3.기능 설명
A. 플레이어
플레이어의 행동을 분리해서 상태패턴으로 구현했습니다.
- Witch클래스는 입력만 받고 행동은 각 상태에서 구현해서 새로운 상태추가나 로직분리를 쉽게 설계했습니다.
- 상호작용을 인터페이스로 설계해 다양한 곳에 상호작용이 가능하게 설계했습니다.
- 뉴 인풋 시스템을 이용해 설계해서 다양한 기기 대응, 새로운 액션 추가가 쉽게 설계했습니다.

B. 마스크기능, 드래그 앤 드랍
스프라이트 마스크를 이용해 마스크 내부에서만 사물이 보이게 하는 기믹을 주 기믹으로 사용했습니다.
- 스프라이트 마크스크 기능을 사용해서 룬스톤 주변에서만 주 기믹이 보이게 설계하였습니다
- SO데이터를 참조하는 아이콘을 인벤토리에서 드래그 하면 월드에 프리팹이 소환되고 플레이어가 상호작용키를 누르면 다시 인벤토리로 복귀하게 설계하였습니다.

C. 암호 입력
키패드 버튼을 클릭해서 암호를 맞추면 열리는 시스템을 구현했습니다.
- 플레이어가 키패드로 입력한 값을 리스트에 저장하고 입력값과 설정해둔 비밀번호의 길이가 같아지면 비교 로직을 실행하게 설계했습니다.
- 답이 틀리면 리스트를 비우고 버튼을 다시 활성화 시켜 재실행을 하게하고 , 정답일 경우 문을 활성화 시키게 설계했습니다.

D. 부활 지점
플레이어의 현재 위치와 체력을 저장해서 사망시 저장한 위치로 돌아오게 구현하였습니다
- 게임 규모가 짧고 간단해서 JSON이나 CSV를 활용한 세이브로드 대신 플레이어의 상태호출과 게임매니저를 이용해서 사망시 세이브 지점에서 부활하는 형식으로 구현하였습니다
- 상호작용 키를 이용해서 저장할 수 있게 하였고, 저장시 색 변화를 주어 저장 여부를 구현했습니다.

E. 드래그 앤 런치
드래그 앤 드랍 기능을 활용하여 물체를 날려 맞추는 기믹을 구현했습니다.
- 드래그로 당긴 거리에 비례해 발사 거리를 계산하고 당긴 거리만큼 트레일을 표시하게 하여 당긴 정도를 표시하게 구현하였습니다
- 시네머신 카메라로 발사체가 발사될 시 따라가게 구현하였습니다

F. 적(함정) AI
BT를 이용하여 적(함정)의 추격, 탐지 공격 AI를 구현하였습니다
- 적이 플레이어를 탐지, 추격, 공격하는 AI를 BT그래프를 이용하여 설계하였습니다.
- 플레이어가 탐지범위 안에 들어오면 추격을 시작하고 탐지 범위를 벗어나면 추격을 종료하고 비활성화되게 설게하였습니다.
- 시네머신을 활용해 추격에 긴장감을 높이는 연출을 추가하였습니다.


4. 설계 패턴과 수치화된 이득
1. State Pattern — IWitchState / IdleState / InteractState
사용 이유: 플레이어(Witch)의 상태(이동, 점프, 상호작용 등)를 객체로 분리해 각 상태가 스스로 전이 조건을 관리하게 함.
| 지표 | 미적용 시 | 적용 후 | 개선 |
| 상태 추가 시 수정 파일 수 | Update() 1개에 모든 if-else → 1개 파일 전체 수정 | 새 State 클래스 1개만 추가 | 수정 범위 ~80% 감소 |
| 버그 발생 가능성 | 중첩 조건문으로 사이드 이펙트 높음 | 상태가 격리되어 타 상태 영향 없음 | 유지보수성 대폭 향상 |
| 코드 라인 수 | 예상 50~100줄 | 각 State 파일 15줄 이하 | 단일 함수 복잡도 70%↓ |
2. Interface Pattern — IInteractable
사용 이유: Warp, SavePoint, GameClear, Guide, NextStage 등 다양한 상호작용 오브젝트를 동일한 인터페이스로 통일. Witch는 IInteractable만 호출하면 됨.
| 지표 | 미적용 시 | 적용 후 | 개선 |
| Witch 클래스의 Interact 조건 분기 | 오브젝트 종류만큼 if (tag == ...) 필요 → 현재 6종이면 6개 분기 | 분기 0개 (인터페이스 호출만) | 분기 제거율 100% |
| 새 상호작용 오브젝트 추가 비용 | Witch 코드 직접 수정 필요 | 새 클래스만 IInteractable 구현 | OCP 준수, 기존 코드 무수정 |
| 테스트 단위 | Witch 전체 테스트 필요 | 각 Interactable 독립 테스트 가능 | 테스트 격리성 확보 |
3. Singleton Pattern — GameManager, UIManager, SoundManager
사용 이유: 게임 전반에서 접근이 필요한 매니저 클래스를 전역 단일 인스턴스로 유지. DontDestroyOnLoad로 씬 전환 시에도 상태 보존.
| 지표 | 미적용 시 | 적용 후 | 개선 |
| 씬 간 데이터 전달 방식 | PlayerPrefs 또는 씬마다 재초기화 필요 | 인스턴스 직접 참조 | 데이터 유실 리스크 제거 |
| 매니저 탐색 비용 | FindObjectOfType<>() 매 프레임 호출 가능성 | Instance 정적 참조 → O(1) 접근 | CPU 탐색 비용 제거 |
| 리스폰 포인트 유지 | 씬 리로드 시 초기화됨 | _respawnPoint 씬 넘어 보존 | 플레이어 경험 연속성 보장 |
4. Event/Delegate Pattern — HpBarView (OnHpChanged)
사용 이유: HP가 변경될 때만 UI를 갱신하도록 이벤트 기반으로 연결. 매 프레임 체크 방식 대비 효율적.
| 지표 | 미적용 시 (Update 폴링) | 적용 후 (이벤트) | 개선 |
| UI 갱신 호출 횟수 (60fps 기준) | 3,600회/분 | HP 변경 시만 호출 → 평균 수 회/분 | 호출 횟수 99%↓ |
| Witch-UI 결합도 | Witch가 직접 UI 참조 필요 | 이벤트 구독으로 완전 분리 | 결합도 제거 |
| 컴포넌트 제거 시 안전성 | NullRef 발생 위험 | OnDestroy에서 구독 해제 → 메모리 누수 방지 | 안정성 확보 |
5. Behavior Tree (BT) — DetectAction / ChaseAction
사용 이유: 적 AI의 행동 로직을 노드 단위로 분리해 조합 가능하게 설계. 감지 → 추적을 독립 액션으로 분리.
| 지표 | 미적용 시 (단일 스크립트 AI) | 적용 후 (BT) | 개선 |
| 동 추가 시 기존 코드 영향 | 기존 조건문 전체 검토 필요 | 새 노드 추가만으로 완결 | 확장 비용 ~70% 감소 |
| 로직 재사용성 | 적마다 스크립트 복제 | DetectAction을 여러 적에 공유 | 코드 중복 제거 |
| 디버깅 편의성 | 실행 흐름 파악 어려움 | BT 그래프로 시각적 디버깅 가능 | 디버그 시간 단축 |
6. ScriptableObject — ItemData
사용 이유: 아이템 데이터(ID, 프리팹)를 코드에서 분리해 에셋으로 관리. 디자이너도 수정 가능.
| 지표 | 미적용 시 (하드코딩) | 적용 후 (SO) | 개선 |
| 아이템 추가 시 코드 수정 여부 | 필수 | 불필요 (에셋만 추가) | 코드 수정 리스크 제거 |
| 리팹 참조 방식 | Resources.Load 또는 직접 연결 | Inspector에서 드래그 앤 드롭 | 참조 오류 방지 |
| 런타임 메모리 | 씬에 종속 | 씬 독립적으로 공유 가능 | 메모리 중복 로딩 방지 |
종합 요약
| 패턴 | 주요 이득 | 핵심 수 |
| State Pattern | 상태 관리 복잡도 감소 | 수정 범위 80%↓ |
| Interface (IInteractable) | 확장성·결합도 개선 | 분기 100% 제거 |
| Singleton | 전역 접근 및 씬 지속성 | 탐색 비용 O(1) |
| Event/Delegate | UI 갱신 최적화 | 불필요 호출 99%↓ |
| Behavior Tree | AI 확장성 | 행동 추가 비용 70%↓ |
| ScriptableObject | 데이터-코드 분리 | 코드 수정 리스크 제거 |
5. 회고
개선, 추가하고 싶은 사항
- 세이브 로드 부분을 JSON을 통해 제대로 만들어 보고 싶었는데 프로젝트 기간과 규모로 무산된점이 아쉬웠습니다
- SO를 이용해서 데이터 관리를 좀더 넓게 써보고 싶었는데 제대로된 구현은 몇개 없어서 아쉬웠습니다.
- 다양한 이펙트를 추가해서 오브젝트 풀링을 사용하고 싶었는데 못해 아쉬웠습니다.
배운점
- 디자인 패턴의 중요성
- 첫 설계시에 견고함의 중요성
- 짧은 기간 (1주) 정도의 프로젝트에서 규모를 어느정도로 설정하고 기능구현을 해야할 지 잘 알게되었습니다
'프로젝트 > 개인' 카테고리의 다른 글
| [Portfolio] 2D .io 장르 네트워크 게임 : Gravity Eater 개발기 (0) | 2026.02.05 |
|---|