포트폴리오

기술 스택----------------------------- - 언어 : C/C++, C#, python, java - 엔진 : Unity, Unreal, OpenTK | GL - 네트워크 : photon, TCP, UDP 를 통한 실시간 통신 게임과 게임 내 채팅 구현 가능

포트폴리오 | 만들래-thumbnail

기술 스택-----------------------------

- 언어 : C/C++, C#, python, java

- 엔진 : Unity, Unreal, OpenTK | GL

- 네트워크 : photon, TCP, UDP 를 통한 실시간 통신 게임과 게임 내 채팅 구현 가능

- 렌더링/그래픽: URP, Unity 쉐이더 그래프, HLSL, OpenGL에서 렌더링 직접 제어 해봄

- UI: UI 연출 애니메이션, 씬 트렌지션, 버튼, 드롭다운, 인풋필드, 스크롤뷰 등등 Unity에 있는 기능 전부 사용해 봄

- 데이터 관리: Json, SupaBase를 통해 로컬 저장 게임, 클라우드 저장 게임 제작 경험이 있음

- 협업 툴: GitHub Desktop, Fork, Git 가능

- 버전 관리: 디스코드 웹 후크와 GitHub의 레포지토리를 연결해서 버전 관리를 많이 해본 경험이 있음

프로젝트-----------------------------

Lost Memory

기억을 잃은 주인공이 기억을 찾아 헤매며 자원을 수집하고 장비를 장착하며 싸워서 살아남는 2D 플랫포머 크래프팅 액션 서바이벌 게임

1. 개요

개발 기간 : 3개월

개발 인원 : 1명

장르 : 2D 플랫포머 크래프팅 액션 서바이벌 게임

플랫폼: PC (콘솔 추 후 지원)

사용 기술: Unity 2D, C#, Unity Physics 2D(Rigidbody2D, Collider2D), Animator, Unity UI, GraphicRaycaster, SceneManager, Coroutine, JsonUtility(JSON 저장/불러오기), UnityWebRequest(CSV 데이터 로드), GitHub

깃허브 링크: https://github.com/inseog1234/Lost_Memory

영상 링크: https://www.youtube.com/watch?v=xCEIaPaGmbg

2. 내가 맡은 역할

1인 개발 프로젝트로, 플레이어 이동/전투 시스템, 몬스터 AI, 인벤토리 및 장비 UI, 저장/불러오기 시스템, 맵 전환, 로딩 UI, 타이틀 저장 슬롯 UI까지 전반적인 게임 시스템을 직접 구현했습니다.

내가 직접 구현한 것

1. 플레이어 이동, 점프, 대시, 기본 공격/연계 공격과 애니메이션 연동

2. 몬스터 추적/공격/피격/사망 로직과 드랍 처리

3. 맵 디자인, 건물 안으로 들어갈 때 카메라 컷신

4. 인벤토리, 장비 슬롯, 드래그 앤 드롭 UI 및 장비 제한 처리

5. JSON 기반 세이브/로드, 타이틀 저장 슬롯 표시, 맵 전환 및 로딩 UI 구현

3. 핵심 기능

프로젝트에서 가장 보여주고 싶은 기능이 뭔가요?

인벤토리, 장비, 세이브 데이터가 연결된 플레이 지속 시스템

왜 이 기능을 만들었나요?

이 프로젝트는 자원을 수집하고 장비를 정리하며 생존하는 흐름이 핵심입니다. 단순히 아이템을 줍는 데서 끝나는 것이 아니라, 획득 → 보관 → 장착 → 저장 → 재로드 후 복원까지 이어지는 전체 흐름을 완성하는 것이 중요하다고 판단했습니다.

구현 방식

플레이어 인벤토리는 InventorySlot 구조로 관리했고, 장비/소모품/재료를 동일한 데이터 구조 안에서 처리할 수 있도록 구성했습니다.

UI는 일반 슬롯과 장비 슬롯을 분리하고, GraphicRaycaster 기반 드래그 앤 드롭을 구현했습니다.

저장 기능은 PlayerData, MonsterData, MapData, SaveData로 나누어 JSON으로 직렬화했습니다. 불러오기 시 플레이어 상태, 필드 아이템, 몬스터 상태, 맵 정보를 모두 복원하도록 구현했습니다.

구현 과정의 어려움

가장 어려웠던 부분은 장비 슬롯 예외 처리와 저장 데이터 복원 시 상태 동기화였습니다.

무기 타입에 따라 한 손/양손 장착 규칙이 달라졌고, 저장 후 로드 시 인벤토리 상태와 맵 오브젝트 상태가 어긋나지 않도록 맞추는 과정이 까다로웠습니다.

해결 방법

아이템 타입과 장착 가능 슬롯을 조건문으로 명확히 분리했습니다. 양손 무기의 경우 관련 슬롯을 동시에 갱신하도록 처리했습니다.

저장 데이터는 플레이어/맵/몬스터 단위로 분리해 필요한 상태를 명확히 저장하도록 구성했습니다. 씬 전환 후에는 매니저 참조를 다시 연결해 로드 타이밍 문제를 해결했습니다.

개선된 결과

아이템을 획득하고 장착한 뒤 게임을 종료해도, 다시 실행했을 때 이전 진행 상태를 자연스럽게 이어갈 수 있게 되었습니다.

덕분에 단순 액션이 아니라 성장과 누적 플레이 경험이 유지되는 서바이벌 구조를 완성할 수 있었습니다.

4. 기술

사용한 패턴 및 구조

플레이어와 몬스터는 enum 기반 상태 분기 방식으로 관리했습니다. 플레이어는 이동, 점프, 공격 상태로 나누어 처리했고, 몬스터는 Idle, Move, Attack, Damaged, Dead 상태를 기준으로 동작하도록 구현했습니다. 전체 구조는 Game_Manager, UI_Manager, Data_Manager, Map_Manager, Item_Manager처럼 역할별로 매니저를 분리하여 구성했습니다.

데이터 관리 방식

아이템 데이터는 Google Sheets CSV를 UnityWebRequest로 불러와 파싱한 뒤 런타임에서 사용했습니다. 세이브 데이터는 JsonUtility를 이용해 로컬 JSON 파일로 저장했으며, 플레이어 능력치, 인벤토리, 맵 위치, 몬스터 상태, 필드 아이템 정보를 구분하여 관리했습니다.

UI 구조 방식

Unity UI 기반으로 인벤토리, 장비 슬롯, HP/ST/MT 바, ESC 메뉴, 타이틀 저장 슬롯 UI를 구성했습니다. 인벤토리는 GraphicRaycaster를 이용해 드래그 앤 드롭 방식으로 구현했으며, 아이템 종류에 따라 장비 가능한 슬롯을 제한했습니다.

씬 및 게임 상태 관리 방식

Game_Manager에서 튜토리얼, 컷신, 몬스터 스폰, 플레이 타임을 관리했고, Map_Manager에서 맵 전환, 카메라 경계, 배경 패럴랙스, 구역 이름 표시를 관리했습니다. Loading_UI에서는 비동기 씬 로딩과 페이드 전환을 처리했으며, Data_Manager는 DontDestroyOnLoad로 유지되도록 구성했습니다.

성능 최적화 경험

긴 맵을 자연스럽게 표현하기 위해 배경을 계속 생성하는 대신, 패럴랙스 배경 오브젝트의 위치를 재배치하는 방식으로 처리했습니다. 저장 및 로드 시 필요한 몬스터와 필드 아이템만 다시 생성하여 불필요한 중복 생성을 방지했습니다.

디버깅 경험

씬 전환 직후 FindWithTag로 참조하던 오브젝트가 아직 생성되지 않아 null 참조가 발생하는 문제가 있었습니다. 저장 데이터를 불러올 때 몬스터나 필드 아이템이 중복 생성되지 않도록 로드 순서를 점검해야 했습니다. 이 과정에서 참조 재연결, 로드 타이밍 분리, 중복 방지 플래그 처리의 중요성을 배웠습니다.

5. 트러블

문제 상황

양손 무기를 장착할 때 슬롯 하나만 갱신되거나, 장착 해제 후 인벤토리 데이터가 꼬이는 문제가 발생했습니다.

원인

일반 인벤토리 이동 로직을 장비 슬롯에도 그대로 적용했기 때문입니다. 한 손 무기, 양손 무기, 방어구처럼 장착 규칙이 다른 아이템을 동일한 방식으로 처리하면서 예외 상황이 발생했습니다.

해결 과정

아이템 타입과 세부 타입을 기준으로 장착 가능한 슬롯을 구분했습니다. 양손 무기의 경우 관련된 슬롯을 동시에 갱신하도록 별도 처리했습니다. 또한 장비 해제 시에도 한쪽만 비우는 것이 아니라 연결된 슬롯을 함께 초기화하도록 수정해 데이터 불일치를 방지했습니다.

배운 점

UI에서 보이는 상태와 실제 게임 데이터는 항상 분리해서 생각해야 한다는 점을 배웠습니다. 특히 인벤토리처럼 예외 케이스가 많은 시스템은 데이터 규칙을 먼저 명확히 정한 뒤 UI를 구현하는 방식이 더 안정적이라는 점을 체감했습니다.

충돌 및 이슈 해결 경험

씬 로딩 직후 매니저 참조가 비어 있는 문제와 저장 데이터 로드 타이밍 문제를 겪었습니다. 이를 해결하기 위해 DontDestroyOnLoad를 사용해 핵심 매니저를 유지하고, 씬 전환 후 필요한 참조를 다시 연결하는 방식으로 안정성을 높였습니다.

Git 사용 방식

1인 프로젝트였기 때문에 대규모 협업 브랜치 전략보다는 기능 단위 커밋 중심으로 관리했습니다. 플레이어 시스템, UI, 세이브/로드, 버그 수정처럼 작업 목적이 명확히 드러나도록 커밋을 나누어 기록했고, GitHub를 통해 버전 관리와 백업을 함께 진행했습니다.

6. 아쉬운 점과 개선점

FindWithTag 의존도를 줄이고, 매니저 참조 구조를 더 명확하게 정리해 유지보수성을 높이고 싶습니다.

아이템과 장비 규칙을 더 데이터 중심적으로 분리해, 인덱스 기반 예외 처리보다 확장성 있는 구조로 개선하고 싶습니다.

몬스터, 드랍 아이템, 이펙트는 오브젝트 풀링을 도입해 성능과 관리 효율을 더 높이고 싶습니다.

---------------------------------------------------------------

사랑과 정의의 이름으로

마법 소녀 주인공이 사랑과 정의의 이름으로 몬스터를 단죄 해나가는 턴제 카드 게임

1. 개요

개발 기간 : 2일

개발 인원 : 3명

장르 : 턴제 카드 게임

플랫폼: PC

사용 기술: Unity 2D, C#, Animator, Unity UI, SceneManager, Coroutine, GitHub

깃허브 링크: https://github.com/inseog1234/Lost_Memory

2. 내가 맡은 역할

담당 파트 : 프로그래밍

내가 직접 구현한 것

1. 타이틀

2. 스테이지 선택, 로딩 구현

3. 카드 펼치기, 카드 덱 관련

4. 카드로 공격, 효과 구현

5. 카드 선택 이펙트

6. 효과 텍스트 구현

3. 핵심 기능

카드 시스템 전반

개발 이유

게임의 메인 시스템이자 가장 중요한 부분이라고 판단했기 때문입니다.

구현 방식

리스트를 활용해 카드 데이터를 구성했고, UI로 다양한 연출을 구현했습니다.

어려웠던 점

카드를 펼칠 때 UI 순서 때문에 Horizontal Layout Group을 썼지만

호버 된 카드를 가장 앞에 렌더링 되도록 하면 호버된 카드의 위치가 자동으로 바뀌어서

이것을 해결하는데 어려움을 겪었습니다.

해결 방법

멘토님께서 Horizontal Layout Group을 업데이트하는 코드가 있다고 알려주셔서, Layout Group을 비활성화하고 필요할 때만 업데이트하도록 수정했습니다.

개선된 점

이 과정에서 카드 위치를 원래 자리로 복구하던 불필요한 코드를 제거하고 최적화도 함께 진행했습니다. 버그도 해결되어 전반적인 작업 속도가 빨라졌습니다.

4. 기술

사용한 패턴 및 구조

전투 시스템은 TurnManager, CardSystem, Player, Enemy로 역할을 나눈 매니저 중심 구조로 설계했습니다. 플레이어 턴 여부, 전투 종료 상태, 적 행동 순서는 상태값으로 관리했고, 스테이지 선택은 Stage_Manager 싱글톤으로 유지해 씬 전환 시에도 스테이지 정보를 유지하도록 했습니다. 카드 사용, 로딩, UI 애니메이션 같은 연출은 코루틴으로 구현해 순차적으로 처리했습니다.

데이터 관리 방식

카드 데이터는 HaveCard 구조를 통해 이름, 설명, 코스트, 고정 수치, 랜덤 수치 범위를 관리했습니다. 공격/방어/회복/버프/가챠 카드 타입을 분리해 카드 종류에 따라 다른 효과를 적용하도록 구성했습니다. 적과 플레이어의 능력치(HP, DEF, ATK, 디버프 수치 등)는 각각 데이터로 관리해 전투 계산에 활용했습니다.

UI 구조 방식

UI는 Unity UI와 TextMeshPro로 구성했습니다. 카드 UI는 RectTransform, HorizontalLayoutGroup, LayoutElement를 사용해 펼쳐지는 형태로 배치했고, 마우스 호버 시 카드가 확대되고 위로 올라오도록 연출했습니다. 효과 안내 텍스트, 코스트 표시, 체력/공격력/방어력 UI, 디버프 표시 UI를 분리해 전투 정보를 직관적으로 볼 수 있도록 만들었습니다.

씬 및 게임 상태 관리 방식

타이틀 → 스테이지 선택 → 로딩 → 전투 씬으로 이어지는 흐름으로 구성했습니다. Stage_Manager가 스테이지 번호를 유지하고, Loading_Scene에서는 비동기 로딩과 진행도 UI를 표시하도록 구현했습니다. 전투 씬에서는 적을 모두 처치하면 스테이지 선택 씬으로 돌아가고, 플레이어가 사망하면 게임 오버 연출 후 씬이 전환되도록 처리했습니다.

성능 최적화 경험

짧은 개발 기간 안에 플레이 가능한 루프를 만드는 것이 우선이었기 때문에, UI와 전투 로직을 분리해 과도한 연산을 줄이는 방향으로 구현했습니다. 로딩 화면에서는 비동기 씬 로딩을 사용해 씬 전환 시 끊김을 줄였고, 카드 연출은 코루틴과 간단한 보간 처리로 구성해 가볍게 동작하도록 했습니다.

디버깅 경험

전투 중에는 카드 입력, 적 행동, UI 연출이 동시에 일어나기 때문에 순서가 꼬이면 버그가 발생하기 쉬웠습니다. 카드 선택 중 입력 제한, 전투 종료 시 코루틴 중단, 타겟이 없을 때 안내문 출력 등 예외 상황을 분리해서 처리했습니다. 특히 카드 사용 직후와 적 턴 진입 시점의 흐름을 점검하면서 턴제 게임에서는 상태 관리가 가장 중요하다는 점을 배웠습니다.

5. 트러블

문제 상황

전투 중 플레이어가 사망하거나 적이 모두 제거되는 순간에도 일부 연출 코루틴이 계속 실행되어 카메라 이동이나 UI 애니메이션이 어색하게 남는 문제가 발생했습니다.

원인

공격, 피격, 안내 UI, 카메라 줌 같은 연출이 각각 독립적인 코루틴으로 동작했기 때문에, 전투 종료 시점을 공통으로 제어하지 않으면 이미 끝난 전투에서도 일부 동작이 계속 이어졌습니다.

해결 과정

전투 종료 여부를 나타내는 상태값을 추가하고, 적 행동 코루틴과 안내 UI 애니메이션 내부에서 해당 상태를 확인해 즉시 종료되도록 처리했습니다. 또한 플레이어 사망 시에는 필요한 UI만 남기고 나머지를 비활성화해 게임 오버 연출이 깔끔하게 보이도록 정리했습니다.

배운 점

턴제 게임은 단순히 기능이 작동하는 것보다 상태 전환 시점을 명확하게 관리하는 것이 완성도를 좌우한다는 점을 배웠습니다. 특히 여러 연출이 동시에 실행되는 구조에서는 종료 조건을 한 곳에서 통제하는 것이 중요하다는 것을 경험했습니다.

6. 협업 경험

협업 여부: O

다른 팀원 직군

프로그래밍, 그래픽

충돌 및 이슈 해결 경험

2일이라는 짧은 게임잼 일정이었기 때문에, 긴 회의보다 바로 구현 가능한 단위로 작업을 나누고 자주 공유하는 방식으로 협업했습니다. 저는 프로그래밍 파트를 맡아 타이틀, 스테이지 선택, 로딩, 카드 시스템, 전투 효과를 담당했고, 그래픽 담당자와는 카드 연출과 전투 UI가 실제 리소스와 어울리도록 수시로 확인하며 맞췄습니다. 큰 문제가 발생하지 않았던 이유는 각자 맡은 범위를 명확히 정하고 필요한 부분을 빠르게 공유했기 때문이라고 생각합니다.

Git 사용 방식

GitHub로 프로젝트를 버전 관리했고, 짧은 일정 안에서 작업 내용이 섞이지 않도록 기능 단위로 자주 커밋하고 수시로 공유했습니다. 특히 씬, UI 프리팹처럼 충돌 가능성이 높은 작업은 먼저 담당 범위를 조율한 뒤 반영해 불필요한 충돌을 줄였습니다.

7. 아쉬운 점과 개선점

지금 다시 만든다면 개선하고 싶은 부분:

1. 카드 데이터를 ScriptableObject로 분리해 확장성을 높이고, 카드 추가와 밸런스 조정을 더 쉽게 만들고 싶습니다.

2. 카드 효과 처리 로직을 모듈화해, 새로운 카드나 특수 효과를 추가할 때 분기문이 늘어나지 않도록 구조를 개선하고 싶습니다.

3. 짧은 개발 기간으로 핵심 루프 구현에 집중했기 때문에, 이후에는 덱 구성, 카드 획득, 적 패턴 다양화 등 메타 시스템을 확장해 게임성을 더 깊게 만들고 싶습니다.

-----------------------------

Loop-Effect

과거로 돌아간 시장이 3일 동안 선택을 반복하며, 도시의 운명을 바꾸는 스토리 중심 선택형 시뮬레이션 게임

1. 개요

개발 기간 : 3개월

개발 인원 : 1명

장르 : 2D 플랫포머 크래프팅 액션 서바이벌 게임

플랫폼: PC (콘솔 추 후 지원)

사용 기술: Unity 2D, C#, Unity Physics 2D(Rigidbody2D, Collider2D), Animator, Unity UI, GraphicRaycaster, SceneManager, Coroutine, JsonUtility(JSON 저장/불러오기), UnityWebRequest(CSV 데이터 로드), GitHub

스토어 링크: https://store.onstove.com/games/103823

영상 링크: https://www.youtube.com/watch?v=VJY4bO_XVfg&t=35s

2. 내가 맡은 역할

담당 파트 : 프로그래밍

내가 직접 구현한 것

1. Day3 스테이지 구현

2. Day3 상호작용 오브젝트 및 NPC 대사/분기 로직 연결

3. Day3에서 발생하는 선택지별 지표 변화 수치 적용

4. Day3 플레이 흐름과 엔딩 연결 구간 점검

5. 팀 프로젝트 마무리 단계에서 스토브 등록/출시 경험 참여

3. 핵심 기능

선택형 상호작용 스테이지 구현

Loop Effect는 플레이어의 작은 선택이 세계 상태와 엔딩에 영향을 주는 구조가 핵심입니다. 스토브 페이지 설명에 따르면 Day 1부터 Day 3까지 플레이가 진행되며, 모든 선택이 환경·경제·치안·행복 수치에 직접 영향을 주고, Day 3 종료 시 여러 엔딩으로 이어집니다.

제가 맡은 Day3는 플레이어가 마지막 결정을 내리고 그 결과를 체감하는 구간입니다. 따라서 전체 게임 인상을 좌우하는 중요한 파트라고 생각했습니다.

어떻게 구현했는가

맵 안의 오브젝트와 NPC에 상호작용 지점을 배치했습니다. 플레이어가 접근 후 입력하면 대화 UI가 열리고, 선택지에 따라 다른 대사와 지표 변화가 적용됩니다.

대사 데이터는 PropData와 DialogueData로 관리되며, 일반 대사·분기형 대사·랜덤 대사를 구분할 수 있도록 구성했습니다. 환경·경제·행복·치안 4개 수치는 GuageManager에서 관리되며, 선택 결과에 따라 UI에 즉시 반영되고 최종적으로 엔딩 분기로 이어집니다. 이 4개 핵심 수치와 멀티 엔딩 구조는 스토브 페이지에서도 핵심 시스템으로 소개되어 있습니다.

어려웠던 점

Day3는 게임의 마지막 날이기 때문에 단순히 오브젝트를 배치하는 것만으로는 부족했습니다. 이전에 쌓인 세계관 분위기와 마지막 선택의 무게가 함께 느껴져야 했습니다.

또한 여러 상호작용 오브젝트가 각기 다른 수치를 변화시키기 때문에, 한 선택이 특정 수치만 과하게 흔들지 않도록 밸런스를 맞추는 부분이 까다로웠습니다.

해결 방법

상호작용 오브젝트마다 선택지를 분리하고, 각 선택이 환경·경제·행복·치안 중 어떤 축에 영향을 주는지 명확히 나누어 설계했습니다.

예를 들어 Day3에는 정전 상황에서 전력을 어디에 공급할지, 약탈된 트럭 물자를 어떻게 분배할지, 도시의 마지막 희망 같은 오브젝트를 보호할지 활용할지 등 서로 다른 가치 충돌이 담겨 있었습니다. 이 선택들이 각기 다른 수치 증감으로 이어지도록 구현했습니다.

단순 분기 대사가 아니라, 플레이어가 "무엇을 우선할지" 고민하게 만드는 구조로 정리했습니다. 스토브 소개에서도 이 게임은 윤리 vs 효율, 작은 선택이 만드는 장기적 결과를 핵심 주제로 삼고 있다고 설명합니다.

결과적으로 좋아진 점

Day3가 단순한 마지막 스테이지가 아니라, 플레이어가 그동안 쌓아온 선택의 방향성을 마무리하는 구간으로 기능하게 되었습니다.

덕분에 엔딩 직전의 몰입감이 살아났고, 팀 프로젝트에서 제가 맡은 범위 안에서도 게임의 핵심 메시지를 직접 전달하는 파트를 구현할 수 있었습니다.

4. 기술

사용한 패턴/구조

대화와 상호작용은 PropData, DialogueData, DialogueBranch를 기반으로 한 데이터 중심 구조로 관리했습니다. DialogueSystem, GuageManager, EndingDataManager처럼 역할별 매니저를 분리해 대사 출력, 수치 변화, 엔딩 분기를 각각 독립적으로 처리했습니다.

데이터 관리 방식

상호작용 데이터는 ScriptableObject 형태의 PropData로 관리했습니다. 오브젝트별로 대사, 선택지, 결과 대사를 분리해 넣어, 코드 수정 없이도 Day3 선택형 이벤트를 확장하거나 조정할 수 있었습니다.

UI 구조 방식

대사 UI는 캐릭터 이름, 본문 텍스트, 선택지 버튼으로 구성했습니다. 버튼형 선택지는 상황에 따라 활성화되도록 만들었고, 환경·경제·치안·행복 4개 지표는 슬라이더 UI로 표시해 플레이어가 선택 결과를 직관적으로 확인할 수 있도록 했습니다.

씬/게임 상태 관리 방식

프로젝트는 타이틀 → Day0 → Day1 → Day2 → Day3 → Ending 구조로 이어집니다. 페이드 매니저를 통해 장면 전환 연출을 처리하고, 게임 전체 언어 설정 및 엔딩 데이터는 싱글톤 매니저로 유지했습니다. 스토브 페이지에서도 게임이 Day 1~Day 3 구조와 멀티 엔딩을 갖는다고 소개하고 있습니다.

성능 최적화 경험

게임잼 프로젝트 특성상 대규모 최적화보다는, 한정된 시간 안에 데이터 기반 구조를 유지해 수정 비용을 줄이는 방향에 집중했습니다. 대사와 선택지 로직을 오브젝트별 데이터로 관리해 반복 구현 없이 빠르게 콘텐츠를 추가하고 조정할 수 있도록 했습니다.

디버깅 경험

선택지 버튼이 잘못된 대사로 이어지거나 수치 반영 타이밍이 어긋나면 게임의 의도가 크게 흔들릴 수 있었습니다. 따라서 Day3에서는 대사 흐름, 선택 후 결과, UI 갱신, 엔딩 연결을 반복 점검했습니다. 이 과정을 통해 스토리형 게임에서는 화려한 시스템보다 분기 흐름의 정확성이 완성도를 좌우한다는 점을 배웠습니다.

5. 트러블

문제 상황

게임잼 특성상 짧은 시간 안에 여러 명이 동시에 작업하다 보니, 기획 의도와 실제 구현 내용이 어긋나면 마지막 날 콘텐츠의 밀도가 떨어질 위험이 있었습니다.

원인

스토리 게임은 단순히 기능만 동작한다고 완성되는 것이 아닙니다. 대사 흐름, 분위기, 선택의 결과가 한 방향으로 정리되어야 합니다. 특히 엔딩 직전 구간인 Day3에서는 작은 어색함도 크게 느껴질 수 있었습니다.

해결 과정

Day3 파트에서는 상호작용 오브젝트와 선택지를 명확하게 나누고, 각 선택이 어떤 수치에 영향을 주는지 기준을 정리한 뒤 구현했습니다. 팀원들과 수시로 공유하며 대사 분위기와 시스템 결과가 자연스럽게 연결되도록 조율했습니다.

배운 점

팀 프로젝트에서는 맡은 범위가 작더라도, 그 안에서 기획 의도를 정확히 구현하고 다른 파트와 자연스럽게 연결하는 능력이 중요하다는 점을 배웠습니다.

6. 협업 경험

협업 여부: O

팀 구성

그래픽 1명, 기획 1명, 프로그래밍 4명

역할 분담 및 이슈 해결

인원이 많은 게임잼 팀이었기 때문에 담당 범위를 명확히 나누고 각자 맡은 파트를 빠르게 완성하는 방식이 중요했습니다. 저는 Day3 구현에 집중했고, 다른 프로그래머가 만든 공용 시스템 위에 제가 맡은 스테이지 콘텐츠를 연결하는 형태로 작업했습니다. 이 과정에서 팀 단위 개발에서는 "내가 전부 만드는 것"보다 "공용 구조를 이해하고 맡은 범위를 정확히 얹는 것"이 중요하다는 점을 배웠습니다.

Git 사용 방식

여러 명이 동시에 개발하는 환경이었기 때문에 담당 범위 중심으로 작업하고 기능 단위로 커밋했습니다. 공용 시스템을 수정할 때는 팀원과 먼저 공유하고, 스테이지 및 콘텐츠 단위로 충돌을 줄이는 방향으로 작업했습니다.

7. 아쉬운 점과 개선점

지금 다시 만든다면 개선할 부분

1. Day3의 선택 결과가 이후 엔딩 연출에서 더 직접적으로 체감되도록 피드백을 강화하고 싶습니다.

2. 선택지별 수치 변화만 보여주는 것을 넘어, 화면 연출이나 오브젝트 변화까지 연결해 결과 체감을 더 크게 만들고 싶습니다.

3. 팀 프로젝트였던 만큼 공용 데이터 규칙과 작업 가이드를 더 명확하게 정리해, 협업 효율을 높이고 싶습니다.

------------------------------------------

WeZard

1. 개요

개발 기간 : 3개월

개발 인원 : 1명

장르 : 멀티 뱀서라이크

플랫폼: PC (콘솔 추 후 지원)

사용 기술: Unity 2D, C#, Unity Physics 2D(Rigidbody2D, Collider2D), Animator, Unity UI, GraphicRaycaster, SceneManager, Coroutine, JsonUtility(JSON 저장/불러오기), UnityWebRequest(CSV 데이터 로드), GitHub

깃허브 링크: https://github.com/inseog1234/2026_First_Project

빌드 링크: https://drive.google.com/drive/folders/18AkPD1YsTFSg64rlizzbjfVingwWdmcR?usp=drive_link

2. 내가 맡은 역할

프로그래밍, 기획, 서버 개발

주요 구현 내용

1. 싱글플레이 핵심 전투 루프: 플레이어 이동, 레벨업, 스킬 선택, 자동 공격 시스템

2. 전투 콘텐츠: 적 스폰, 미니보스 등장 타이밍, 경험치 오브 드랍, 킬 카운트, 게임 타이머, 결과 UI

3. 오브젝트 풀링: 적, 투사체, 경험치 오브 최적화 구조

4. 멀티플레이 로비: 방 생성/입장/퇴장, 플레이어 목록 갱신, 대기방 채팅 시스템

5. 멀티플레이 네트워크: C# 기반 릴레이 서버(.NET 10)와 UDP 클라이언트 구조 설계 및 구현

3. 핵심 기능

프로젝트에서 가장 보여주고 싶은 기능

TCP 릴레이 서버와 연동한 멀티플레이 로비/대기방/채팅 시스템

왜 만들었는지

WeZard는 여러 마법사가 함께 살아남는 협동형 뱀파이어 서바이버 라이크를 목표로 기획했습니다. 싱글플레이 전투만 구현하는 것을 넘어, 여러 플레이어가 같은 방에 모이고 입장 상태를 공유하며 채팅으로 상호작용하는 멀티플레이 진입 구조가 필요했습니다. 실시간 전투 동기화까지는 완성하지 못했지만, 실제 멀티 게임으로 확장할 수 있는 기반을 먼저 구축하는 데 의미를 두었습니다.

구현 방식

방 목록과 입장 상태는 Supabase REST API로 관리했습니다. 대기방의 실시간 채팅과 입장/퇴장 메시지는 별도로 만든 TCP 릴레이 서버에서 처리했습니다. Unity 클라이언트에서는 LobbyManager, RoomManager, RelayChatClient를 분리해 방 생성 → 입장 → 플레이어 목록 갱신 → 채팅 수신/출력 흐름이 이어지도록 구성했습니다. 서버는 .NET 8 콘솔 애플리케이션으로 작성했으며, ConcurrentDictionary를 사용해 방 세션과 접속 클라이언트를 관리했습니다. 또한 향후 인게임 동기화를 고려해 UDP 클라이언트와 스냅샷 수신 구조도 별도로 설계했습니다.

어려웠던 점

가장 어려웠던 점은 Unity 클라이언트의 UI 흐름과 네트워크 비동기 처리를 안정적으로 연결하는 것이었습니다. 방 생성과 입장 요청이 성공했더라도 채팅 서버 연결이나 플레이어 목록 갱신이 늦어지면 사용자는 정상 입장 여부를 혼란스럽게 느낄 수 있었습니다. 또한 네트워크 수신은 백그라운드 스레드에서 이루어지기 때문에, 이를 바로 Unity UI에 반영하면 메인 스레드 이슈가 발생했습니다.

해결 방법

클라이언트에서는 ConcurrentQueue 구조를 사용해 네트워크 수신 결과를 메인 스레드에서 안전하게 처리하도록 만들었습니다. create_room, join_room 같은 요청에는 별도의 OK 응답 대기 로직을 두어 단순 송신이 아니라 성공 응답을 확인한 뒤 다음 단계로 진행하도록 구성했습니다. 서버에서는 방장 퇴장 시 방을 정리하고 남은 클라이언트에게 시스템 메시지를 브로드캐스트해 세션 정합성을 맞추었습니다.

결과

UDP 기반 인게임 멀티 동기화는 완성하지 못했지만, 플레이어가 실제로 방을 만들고 다른 사용자가 입장하며 대기방에서 채팅하는 단계까지는 동작하는 구조를 만들었습니다. 단순한 싱글플레이 프로토타입이 아니라, 실제 온라인 협동 게임으로 확장 가능한 기반 구조를 직접 설계하고 구현한 프로젝트로 정리할 수 있었습니다.

4. 기술

사용한 패턴/구조

싱글플레이 전투는 Player, Enemy, SkillController, GameTimer, KillManager처럼 역할별로 클래스를 나누어 구성했습니다. 게임 전반은 Player.Instance, GameTimer.Instance, SceneTransitionController.Instance 같은 싱글톤/매니저 구조를 활용했습니다. 스킬은 SkillData ScriptableObject와 ActiveSkill, PassiveSkill 구조로 나누어 확장 가능하게 설계했습니다. 멀티플레이는 로비/방/채팅/인게임 네트워크를 분리하고 TCP와 UDP 역할을 나누는 방식으로 구성했습니다.

데이터 관리 방식

스킬 데이터는 ScriptableObject로 관리해 아이콘, 타입, 기본 스탯, 레벨업 스탯을 에디터에서 조정할 수 있도록 했습니다. 플레이어 프로필은 PlayerPrefs로 고유 ID와 닉네임을 저장했고, 멀티플레이 방 정보와 플레이어 목록은 Supabase REST API로 관리했습니다. 네트워크 메시지는 JSON 기반으로 직렬화/역직렬화해 클라이언트와 서버 간 주고받도록 구현했습니다.

UI 구조 방식

타이틀, 로비, 방, 게임 결과 UI를 분리해 씬 흐름에 따라 필요한 인터페이스만 노출되도록 구성했습니다. 로비에서는 방 목록을 동적으로 생성하고, 비밀번호 입력 팝업과 방 생성 팝업을 구현했습니다. 룸 씬에서는 플레이어 목록과 채팅 로그를 주기적으로 갱신했고, 인게임에서는 HP, 레벨, 경험치, 생존 시간, 결과 통계 UI를 분리해 표시했습니다.

씬 및 게임 상태 관리 방식

타이틀 → 멀티 로비 → 룸 → 게임 씬 순으로 흐르며, 씬 전환은 SceneTransitionController로 페이드와 함께 처리했습니다. 멀티플레이 관련 상태는 Session과 LocalProfile에 저장해 씬이 바뀌어도 현재 방 정보와 플레이어 식별값을 유지하도록 했습니다. 게임 진행 상태는 GameTimer와 KillManager를 중심으로 관리했고, 플레이어 사망 또는 제한 시간 종료 시 결과 UI를 열도록 구현했습니다.

성능 최적화 경험

뱀서라이크 특성상 적, 투사체, 경험치 오브가 계속 생성되기 때문에 ObjectPool 기반 풀링 구조를 적용했습니다. 각 오브젝트 타입마다 전용 풀을 두어 Instantiate/Destroy 반복을 피했고, 이를 통해 전투가 길어져도 오브젝트 생성 비용과 GC 부담을 줄였습니다. 또한 스킬 처리 시 반복 탐색 비용을 줄이기 위해 스킬 맵(Dictionary)과 적 리스트 관리 구조를 활용했습니다.

디버깅 경험

네트워크에서는 연결은 되었지만 UI가 갱신되지 않거나, 비동기 응답 순서 때문에 방 입장 흐름이 꼬이는 문제가 가장 까다로웠습니다. 이를 해결하기 위해 요청-응답 단계를 분리하고, 성공 응답을 받은 뒤 다음 UI 상태로 넘어가도록 구조를 정리했습니다. 전투에서는 적 수가 많아질수록 생성/삭제 비용이 커졌기 때문에, 오브젝트 풀 적용 전후를 비교하며 풀 반환 시점과 상태 초기화를 점검했습니다.

5. 트러블

문제 상황

멀티플레이 대기방 채팅 시스템을 구현할 때 네트워크 수신은 정상적으로 되었지만, Unity UI에 바로 반영하면 흐름이 불안정해졌습니다.

원인

네트워크 수신 루프는 비동기/백그라운드 방식으로 동작했고, Unity의 UI 갱신은 메인 스레드에서 처리되어야 했습니다. 스레드 경계가 섞이면서 문제가 발생했습니다.

해결 과정

수신한 메시지를 바로 UI에 반영하지 않고 ConcurrentQueue에 저장한 뒤, Update()에서 큐를 비우며 메인 스레드에서 안전하게 처리하도록 구조를 변경했습니다. 또한 OK 응답 대기 로직을 따로 두어 방 생성/입장 요청이 실제로 성공했는지 확인한 후 다음 단계로 진행하도록 만들었습니다.

배운 점

게임 네트워크는 단순히 "연결된다"보다, 비동기 통신 결과를 게임 엔진의 메인 루프와 어떻게 연결하느냐가 안정성에 훨씬 중요하다는 점을 배웠습니다. 특히 Unity에서는 스레드 안전성과 UI 갱신 시점을 분리하는 설계가 필수적이라는 것을 경험했습니다.

6. 아쉬운 점과 개선점

지금 다시 만든다면 개선할 부분

1. 현재는 멀티플레이가 대기방/채팅 단계까지만 구현되어 있으므로, 이후에는 서버 권한 구조를 더 명확히 잡아 UDP 기반 인게임 동기화까지 완성하고 싶습니다.

2. 네트워크 메시지 파싱 일부가 문자열 기반으로 처리되어 있어, 이후에는 패킷 구조와 직렬화 방식을 더 체계적으로 정리해 유지보수성을 높이고 싶습니다.

3. 전투와 네트워크 코드가 함께 커지는 구조이므로, 이후에는 게임 로직과 네트워크 동기화 계층을 더 분리해 테스트와 확장이 쉬운 구조로 개선하고 싶습니다.

작성자: MintCat

경력 코드: 100404

조회수: 7

댓글수: 0

좋아요: 1

인기도: 0.001012703389871987

작성일: 6/18/2026}

수정일: 6/18/2026