1분반-자이로드롭
프로젝트 개요
기술개발 과제
- 국문: 협동심 증진 및 공감각 발달을 위한 게임 ‘자이로드롭’ 개발
- 영문: Gyrodrop: A Game for Boosting Teamwork and Enhancing Multisensory Development
과제 팀명
자이로드롭
지도교수
황혜수 교수님
개발기간
2025년 3월 ~ 2025년 6월 (총 4개월)
구성원 소개
- 서울시립대학교 컴퓨터과학부 2020920058 조성채(팀장)
- 서울시립대학교 컴퓨터과학부 2020920051 이현제(팀원)
- 서울시립대학교 컴퓨터과학부 2019920037 이성호(팀원)
서론
개발 과제의 개요
개발 과제 요약
- 모바일 디바이스의 자이로센서 데이터를 이용해 게임 내 플랫폼을 기울여 캐릭터의 위치를 조작하는 3D-Platformer, 퍼즐 게임 개발
- 1인 모드(전체 축 조작)와 2인 모드(Pitch, Roll 축 분담) 지원으로 협동성 극대화
- 호스트 중심 물리 연산 + WebRTC P2P 네트워킹으로 플레이어 간 멀티 플레이 지원
- 크로스 플랫폼(Windows, macOS) + 모바일 웹 컨트롤러 지원으로 접근성 확대
개발 과제의 배경 및 효과
- 모바일 VR·센서 기반 인터랙션 시장 확대, 캐주얼 협동 게임의 수요 증가
- 기기 내장 자이로센서 활용으로 별도 디바이스 없이 본인의 스마트폰 사용 가능
- 실시간 P2P 멀티플레이 지원으로 원격지의 사용자와 협동 플레이 가능
- 교육·재활(노인 치매 예방, 협동 훈련) 등 파생 활용 가능
개발 과제의 목표와 내용
- 협동 플레이를 유도하는 게임 맵 디자인 - 하나의 축만을 이용하여 게임을 클리어하기 어렵도록 설계
- 원격지 멀티 플레이 실시간성 확보 – 게임 클라이언트 간 실시간 동기화 지연 시간을 30ms 내외로 유지
- 다양한 기믹 요소(열쇠, 발판, 점프대, 이동 플랫폼, 부숴지는 발판 등)를 구현하여 게임의 난이도와 긴장도를 높임
- 9개의 맵(3가지 난이도, 각 난이도별 3개의 맵) 개발
- 웹 컨트롤러 연동으로 별도의 컨트롤러 없이도 PC에서 플레이 가능하도록 설계 – 컨트롤러 지연 시간은 100ms 내외로 유지
개발과제의 기술적 기대효과
- 자이로 데이터 실시간 취합 및 클라이언트(피어) 간 실시간 동기화 기술 개발
- WebRTC 기반의 P2P 게임 상태 동기화 기술 구현
개발과제의 경제적 및 사회적 파급효과
- 친구 및 가족과 2인 협동으로 가볍게 즐길 수 있는 소셜 게임
- 협동심 증진 및 공감각 발달에 도움을 주어 노인 치매 예방 프로그램으로 활용 가능
관련 기술의 현황
관련 기술의 현황 및 분석(State of art)
- 자이로 센서
- 자이로 센서는 각속도를 측정하여 회전 방향과 속도를 정확히 감지하는 역할을 한다. 최근의 자이로 센서 기술은 MEMS(미세전자기계 시스템) 기반으로 소형화 및 고정밀화가 이루어졌으며, 현실 세계와 가까운 가상 환경 경험을 제공할 수 있기에 스마트폰, VR 기기, 게임 컨트롤러 등 다양한 분야에서 필수적인 기술로 자리 잡았다.
- 최근 자이로 센서는 가속도 센서와 결합하여 6축 센서를 구성하며, 여기에 자기장 센서를 추가해 9축 센서로 발전하였다. 이를 통해 더욱 정확한 공간 인식과 자세 추적이 가능해졌다.
- 최신 자이로 센서는 초당 300~2000 DPS(degrees per second)의 정밀한 각속도 측정 범위를 제공하며, 모바일 게임 환경에서 미세한 움직임까지 정확히 감지할 수 있게 되었다.
- 게임 엔진
- 게임 개발 및 실시간 시뮬레이션 구현을 위한 대표적인 기술로는 Unity Engine과 Unreal Engine이 있다.
- Unity Engine
- Unity는 직관적인 인터페이스와 높은 접근성을 바탕으로, 다양한 플랫폼에서의 실시간 콘텐츠 개발을 지원하는 범용 게임 엔진이다.
- 모바일, 데스크탑, 웹, 콘솔, XR(VR/AR) 등 크로스 플랫폼 개발에 최적화되어 있으며, 하나의 프로젝트로 다수의 플랫폼에 쉽게 빌드할 수 있는 기능을 제공한다.
- 기술적으로는 NVIDIA의 PhysX 엔진을 기반으로 한 3D 물리 시뮬레이션과, Box2D 기반의 2D 물리 엔진을 내장하고 있어 물리 기반 상호작용 구현이 용이하다. 또한 DOTS(Data-Oriented Technology Stack) 및 ECS(Entity-Component-System) 구조를 통해 성능 중심의 대규모 데이터 처리 및 병렬 연산을 지원한다.
- Unity는 시각적 툴(Shader Graph, Visual Effect Graph, Timeline 등)과 풍부한 Asset Store 생태계를 갖추고 있어 빠른 프로토타이핑과 개발 효율 향상에 유리하다.
- 특히 C# 기반의 스크립팅, 높은 커스터마이징 자유도, 사용자 커뮤니티의 풍부한 기술 자료는 Unity의 장점 중 하나로 꼽힌다.
- Unreal Engine
- Unreal Engine은 Epic Games에서 개발한 고성능 실시간 렌더링 엔진으로, AAA급 게임 및 고품질 비주얼 콘텐츠 제작에 특화되어 있다.
- 특히 최신 버전인 Unreal Engine 5는 Nanite(가상화 지오메트리), Lumen(실시간 글로벌 일루미네이션)과 같은 첨단 렌더링 기술을 도입하여, 실사 수준의 그래픽 구현이 가능하다.
- 고급 물리 효과를 위한 Chaos Physics, Cloth Simulation, Rigid/Soft Body Dynamics 등 다양한 내장 기능을 제공하며, C++ 기반의 강력한 성능 제어와 함께 Blueprint라 불리는 시각적 스크립팅 시스템도 함께 지원되어 비전공자도 게임 로직을 시각적으로 구성할 수 있다.
- Unreal Engine은 높은 성능과 정교한 표현력을 제공하는 대신, 비교적 높은 시스템 요구사항과 학습 난이도를 수반한다. 그럼에도 불구하고 영화, 건축 시각화, 디지털 트윈 등 게임 이외의 산업 분야에서도 널리 사용되고 있다.
관련 시장에 대한 분석
경쟁제품 조사 비교
- Super Monkey Ball: 해당 게임은 키패드나 조이스틱 기반 조작으로 플랫폼 위의 캐릭터를 조종하는 싱글플레이 중심의 게임이다. 멀티플레이 요소는 제한적이며, 자이로 센서를 활용한 조작 방식은 지원하지 않아 실제 기기 움직임과의 연동 경험이 부족하다. 우리 게임은 자이로 기반의 직관적인 조작감과 플레이어 간 협업 설계를 통해 보다 몰입감 있는 플레이를 제공한다.
- Tiltagon: 빠른 템포의 생존형 싱글플레이 게임으로, 키보드나 마우스를 이용한 입력에 의존하며 멀티플레이나 협동 요소는 존재하지 않는다. 이에 반해 우리 게임은 다양한 기믹과 시간 차 협동이 요구되는 퍼즐 요소, 실시간 네트워크 동기화를 통한 협동 경험에 초점을 맞춘 구조를 제공한다.
- Rolling Sky: 터치 드래그 방식의 싱글플레이 게임으로, 자이로 센서를 지원하지 않으며 협동 요소가 없다. 우리 게임은 단순한 반사신경 게임과 달리 두 명이 동시에 조작하지 않으면 클리어할 수 없는 구조로 협동심을 유도하며, 플레이어 간의 조작 축 분리 및 공동 책임 구조를 강조한다.
마케팅 전략
- 대학 커뮤니티(에브리타임·인스타 릴스) 타겟팅 티저 영상 배포
- 자체 렌딩 페이지(gyrodrop.xyz)에 배포
- 게임 스토어(Stove, Steam) 출시
설계
사용자 요구사항
번호 | 요구사항 | D or W | 중요도 |
---|---|---|---|
게임 플레이 | |||
1 | 플레이어가 멀티플레이 룸을 생성 또는 입장할 수 있고, 게임 스테이지를 선택하여 상대방과 게임을 플레이할 수 있다. | D | 대 |
2 | 2명의 플레이어가 자이로 센서를 통해 각각 Pitch/Roll 축을 담당하여 판의 기울기를 조작할 수 있다. | D | 대 |
3 | 게임 내 한 스테이지에서 공이 목표 지점까지 도달하는 최단 거리로 움직이는 시간이 1분 내로 소요되어야 한다. | D | 중 |
4 | 협동 플레이를 유도하도록 맵이 디자인되어야 한다. • 두 축을 동시에 협력하여 기울여야만 통과 가능한 경로 • 시간차를 맞춰 움직여야 클리어 가능한 점프 구조 등 다양하게 설계된 기믹을 바탕으로 다채로운 맵 디자인을 제공 |
D | 대 |
5 | 크로스 플랫폼을 지원하고 기기에 자이로 센서가 없는 경우 이를 지원하는 기기로 컨트롤이 가능해야 한다. | D | 중 |
6 | 레벨 디자이너가 게임 내 스테이지를 생성하기 위한 툴이 제공되어야 한다. | W | 소 |
기술적 요소 | |||
1 | 자이로 센서의 입력에 대한 반응속도를 100ms 이하로 유지한다. | D | 중 |
2 | 게임 서버–클라이언트 간 실시간 동기화 시간을 30ms 이하로 유지한다. | D | 대 |
3 | 렌더링 속도를 60FPS 기준으로 유지하여 매끄러운 플레이를 제공한다. | D | 중 |
4 | CI/CD를 제공하여 빠른 개발과 배포가 가능하도록 한다. | W | 중 |
5 | 게임 서버의 수평적 확장이 가능하도록 오케스트레이션이 가능해야 한다. | W | 소 |
사용자 요구사항 만족을 위한 기능 정의 및 기능별 정량목표
기능 정의
분류 | 기능 명칭 | 설명 |
---|---|---|
GR1 | 게임 룸 생성 | 플레이어가 멀티플레이 룸을 생성할 수 있다. |
GR2 | 게임 룸 입장 | 플레이어가 상대방의 접속 정보를 이용하여 멀티플레이 룸에 입장할 수 있다. |
GR3 | 스테이지 플레이 | 멀티플레이 룸에서 스테이지를 선택하여 게임을 플레이할 수 있다. |
GY1 | 자이로 데이터 취득 | 게임 클라이언트가 구동되는 기기로부터 자이로 센서 데이터를 취득할 수 있다. |
GY2 | 자이로 데이터 대체 취득 | 게임 클라이언트가 구동되는 기기에서 자이로 센서를 가져올 수 없는 경우(예: PC) 이를 지원하는 모바일 기기를 이용하여 컨트롤러 부분만 대체할 수 있다. |
GY3 | 자이로 반응 속도 | 자이로 컨트롤러의 반응이 게임 상에 100ms 이내로 적용된다. |
GY4 | 자이로 데이터 취합 | 두 플레이어의 자이로 데이터를 취합하여 게임 서버에 반영할 수 있다. |
GS1 | 기믹 상호작용 | 점프대, 발판, 열쇠, 부서지는 바닥 등의 기믹 구현 및 상태 변화 처리를 수행한다. |
GS2 | 스테이지 레벨 디자인 | 협동 플레이를 유도하는 맵을 제작한다. 하나의 축만을 이용하여 게임을 플레이할 수 없어야 하며, 두 개의 축을 이용해서 서로 협동하여 스테이지를 클리어 하도록 설계되어야 한다. |
GS3 | 네트워크 동기화 | 게임 서버–클라이언트 간 실시간 동기화 시간이 30ms 이하로 유지되도록 한다. |
GS4 | 렌더링 | 최신 스마트폰을 기준으로 60FPS 렌더링 성능을 보장한다. |
GD1 | 레벨 에디터 도구 | 스테이지 제작 도구를 제공하여 쉽고 빠른 맵 제작이 가능하도록 한다. |
GD2 | 배포 및 서버 관리 | 오케스트레이션 도구(kubernetes, docker 등)를 이용하여 CI/CD 및 수평 확장을 고려한 설계를 한다. |
기능별 정량목표
분류 | 기능 명칭 | 목표 기준치 | 평가 방식 | 중요도 계수 |
---|---|---|---|---|
GR1 | 게임 룸 생성 | 구현됨 | 개발 여부 (개발: 1, 미개발: 0) | 0.07 |
GR2 | 게임 룸 입장 | 구현됨 | 개발 여부 | 0.07 |
GR3 | 스테이지 플레이 | 구현됨 | 개발 여부 | 0.07 |
GY1 | 자이로 데이터 취득 | 구현됨 | 개발 여부 | 0.07 |
GY2 | 자이로 대체 컨트롤 | 구현됨 | 개발 여부 | 0.07 |
GY3 | 자이로 반응 속도 | ≤ 100ms | max(0, 1 - (반응속도 / 100)) | 0.12 |
GY4 | 자이로 데이터 취합 | 구현됨 | 개발 여부 | 0.07 |
GS1 | 기믹 상호작용 | 구현됨 (3종 이상) | max(1, 구현된 기믹 수 / 6) | 0.08 |
GS2 | 협동형 레벨 디자인 | 협동 기믹 포함 맵 비율 ≥ 80% | 실제비율 / 100 | 0.10 |
GS3 | 네트워크 동기화 | ≤ 30ms | max(0, 1 - (RTT / 30)) *RTT는 교내 무선랜 환경에서 측정 |
0.10 |
GS4 | 렌더링 | ≥ 60FPS | min(1, FPS / 60) *FPS는 평균값 사용 |
0.10 |
GD1 | 레벨 에디터 도구 | 구현됨 | 개발 여부 | 0.02 |
GD2 | 배포 및 서버 관리 | 구현됨 | 개발 여부 | 0.06 |
완료 작품의 평가에서 위의 표의 평가 방식으로 점수를 매기고, ((기능 점수 * 기능 중요도 계수)의 합 * 100)을 계산하여 100점 만점을 기준으로 평가한다.
기능 구현을 위한 세부기술 선택사항
- 게임 룸 생성(GR1), 게임 룸 입장(GR2), 자이로 데이터 취합(GY4) 기능 개발을 위해 Node.js 기반의 NestJS 웹 서버 프레임워크를 선정하였다.
- Node.js의 풍부한 패키지 생태계와 빠른 프로토타이핑 및 개발 속도를 고려하여 선택하였다.
- 플레이어가 상대방의 연결 정보를 직접적으로 알 수 없으므로 중립적이고 안정적인 연결을 보장하기 위해 서버-클라이언트 아키텍처를 도입하고, 이를 통해 게임 룸 및 접속 코드를 생성하고 관리하도록 하였다.
- 스테이지 플레이(GR3) 기능 구현을 위해 게임 엔진으로 Unity를 채택하였다.
- Unity는 직관적인 시각적 개발 툴과 방대한 플러그인 생태계를 제공하여 초기 개발 속도를 크게 향상시킬 수 있으며, 캐주얼 게임 및 실시간 인터랙티브 콘텐츠 제작에 적합하다.
- Unity는 또한 UI 시스템, 물리 기반 시뮬레이션, 경로 탐색, 상태 머신 등 주요 게임 개발 기능을 위한 풍부한 라이브러리와 예제를 제공하여 개발의 재사용성과 유지보수성 측면에서 큰 이점을 제공한다.
- 자이로 데이터 취득(GY1), 자이로 대체 컨트롤(GY2) 구현을 위해 모바일 기기 디바이스의 자이로 정보를 취득하기로 했으며, 별도의 애플리케이션 설치가 필요하지 않도록 웹 기반 애플리케이션을 제공하기로 했다.
- 자이로 센서 데이터를 획득하기 위해 deviceorientation 웹 API를 이용한다.
- React 라이브러리를 사용하여 개발 효율성을 높였고, React의 방대하고 다양한 라이브러리 생태계를 활용하여 인터랙티브한 UI/UX 설계를 실현할 수 있다.
- 자이로 반응 속도(GY3) 요구사항 충족을 위해 실시간 양방향 통신이 가능한 WebSocket을 도입하였다.
- HTTP 통신 대비 헤더 등의 오버헤드를 줄이고 실시간 이벤트 전송 방식을 채택하여 통신 지연을 최소화하였다.
- 기믹 상호작용(GS1), 협동형 레벨 디자인(GS2)은 Unity의 MonoBehaviour를 상속받는 방식으로 구현하였으며, Unity 에셋 스토어에서 유/무료 모델을 활용하여 디자이너가 없는 팀 상황에서도 높은 품질의 게임 디자인을 가능하게 하였다.
- 네트워크 동기화(GS3)를 위해 처음에는 Mirror, FishNet과 같은 서버-클라이언트 구조의 동기화 프레임워크를 고려하였으나, 매 게임마다 Unity Headless 서버 인스턴스를 매번 띄우는 오버헤드와 P2P 위한 Transport 계층의 미구현 및 빈약한 문서화로 인해 최종적으로 WebRTC 기반의 P2P 기술을 채택하였다.
- WebRTC는 서버 연결 없이 Peer 간 직접적인 통신이 가능하고, NAT 및 방화벽을 우회할 수 있으며, 실시간으로 데이터를 전송할 수 있다는 점이 우리의 요구사항에 딱 맞아 떨어진다.
- 클라이언트는 Unity.WebRTC 패키지로 구현하고, 시그널링 서버는 Node.js 및 Socket.io를 사용하였다.
- RPC 기술은 C#의 리플렉션 기술을 이용하여 동일하게 배포된 애플리케이션 내에서 원격지의 메서드를 호출하는 방식으로 구현하였다.
- 렌더링(GS4) 성능 최적화를 위해 Unity의 생명 주기(Update, FixedUpdate)를 명확히 구분하여 사용하였으며, Raycast, 복잡한 물리 연산, 충돌 판정 등 고비용 연산을 FixedUpdate에서만 실행하여 성능을 관리하였다.
- 레벨 에디터 도구(GD1)는 시간과 인력의 제한으로 별도의 도구 개발 없이 Unity 프레임워크 내에서 레벨 디자인을 진행하였다.
- 배포 및 서버 관리(GD2)는 AWS를 활용하여 서비스 안정성을 확보하고, CloudFront를 통해 모바일 웹 컨트롤러의 빠른 접근성을 보장하였다. EC2 인스턴스 앞에 Elastic Load Balancing(ELB)을 배치하여 여러 인스턴스를 스케일링 가능하게 구성하였다.
게임 클라이언트 설계
매니저 클래스 설계
게임 내 스크립트에서 우리 게임의 핵심 서비스 로직에 쉽게 접근할 수 있도록 싱글톤 패턴을 사용하여 전역 접근을 용이하도록 하였다. 또한 매니저 위의 매니저 클래스인 Managers 클래스를 두어 하위 매니저 클래스들의 의존성 주입을 담당하도록 하였고, 각 하위 매니저 클래스들은 책임과 역할을 명확히하여 기능 확장 및 디버깅이 용이하도록 하였다. 아래는 각 클래스들의 역할에 대한 설명이다.
- Managers 클래스
- Singleton 패턴으로 구현된 최상위 매니저 클래스이다.
- 각 서브 매니저(GameManager, RoomManager, SessionManager, UIManager, SoundManager 등)를 소유하며, 전역 접근을 제공한다.
- Dispatch(Action) 메서드를 제공하여 Unity 메인 스레드에서 실행되어야 할 작업을 안전하게 큐잉 및 실행
- GameManager 클래스
- 게임 진행 상태 전반을 관리한다.
- 주요 기능
- 스테이지 클리어 로직 수행(FinishAction)
- 스테이지 로딩(LoadStageScene, LoadMainScene)
- 스테이지 잠금/해금 관리(GetLastUnlockedStage, UnlockLastStage)
- 초기화 및 리셋(Init, Clear)
- RoomManager 클래스
- REST API를 통한 룸 생성, 참가, 자이로 제어 기능을 담당한다.
- 클라이언트가 속한 룸 정보(Current), 현재 자이로 상태(CurrentGyro), 접속 코드(AccessCode) 등을 관리한다.
- 주요 기능
- 룸 생성 및 참가 (OpenAsync, JoinAsync, LoadAsync)
- 자이로 축 점유/해제 (TaskAxisAsync, ReleaseAxisAsync)
- 웹 컨트롤러 URL 제공 (GetWebControllerUrl)
- 전체 초기화 (ResetAsync)
- SessionManager 클래스
- 상대방과 원격 플레이를 위한 세션 연결 관리를 담당한다.
- 연결 흐름의 상태(SessionStatus)를 추적하며, 호스트/게스트 역할에 따라 연결 절차를 처리한다.
- 구체적인 연결 방식은 외부에 노출하지 않기 위해 해당 클래스를 정의하였으며,, 해당 클래스 안에서 WebRTC를 쓸 지 다른 P2P 통신 기법을 사용할지 결정한다.
- 주요 기능
- 호스트로서 게스트를 기다림 (StartWaitForGuest)
- 게스트로서 호스트에 접속 (StartJoinHostRoom)
- 세션 리셋 (ResetAsync)
- 연결 종료 처리 (Dispose)
- SoundManager 클래스
- 게임 내 효과음 및 배경음악 재생을 담당한다.
- 주요 기능
- BGM/SFX 재생 (Play)
- 초기화 및 정리 (Init, Clear)
- UIManager 클래스
- UI 패널 관리를 담당한다(씬 UI, 팝업 UI)
- 주요 기능
- UI 생성 및 표시 (ShowSceneUI<T>, ShowPopupUI<T>)
- 팝업 닫기 (ClosePopupUI, CloseAllPopupUI)
플레이어 이동 설계
기존의 Rigidbody 기반으로 중력으로만 움직이는 설계는 얇거나 기울어진 표면에서 다음과 같은 문제를 유발했다.
- 갑작스럽게 기울어진 바닥에 대하여 공이 바닥 콜라이더를 관통하여 낙하하거나
- 경사진 표면에서 예기치 않게 튕겨 불안정하게 움직이는 현상
이를 해결하기 위해, 기존 물리 기반 이동 방식 대신 표면 정착 및 사영 기반 이동 방식으로 새롭게 움직임을 설계하였다. 구현된 클래스는 플랫폼 회전과 공의 움직임을 자연스럽게 연동하여, 직관적이고 안정적인 조작감을 제공한다.
- 플랫폼(평면) 감지
- Unity의 Raycast 기능을 이용하여 플레이어의 위치에서 중력 방향으로 보이지 않는 광선을 쏘아 충돌된 객체를 바닥으로 인식한다.
- 짧은 순간의 오인식이나 접지 흔들림(jitter)을 방지하기 위해 내부적으로 이전 상태를 기억하고, 접지 손실 여부를 일정 거리 이상 벗어난 경우에만 판단하도록 처리하였다.
- 중력 분해 및 표면 사영 적용
- 인식된 평면의 법선 벡터를 기준으로 중력 벡터를 분해하여, 법선 방향 성분을 제거하고 평면에 평행한 방향의 힘만 공에 가한다.
- 플랫폼이 회전하면 법선 방향도 함께 변하므로, 플레이어는 해당 표면을 따라 자연스럽게 미끄러지는 형태로 이동하게 된다.
- 이를 통해 표면 기울기에 따라 실제 물리적으로 이동하는 느낌을 재현하였다.
- 정확한 위치 조정(접지 보정)
- 공의 중심 좌표를 바닥의 표면에 정사영(수직 사영)하여, 물리 충돌에 의한 튕김이나 겹침을 방지한다.
- 공은 표면에 붙어 있는 듯한 상태로 유지되며, 얇은 구조물이나 미세한 기울기에서도 안정적으로 동작한다.
- 사영 위치는 바닥 기준점에서의 상대 거리와 법선 벡터를 이용하여 계산된다.
- 플레이 경험 향상
- 공의 현재 속도가 최대 속도를 초과할 경우, 반대 방향의 감속력을 추가로 가하여 과도한 가속을 억제한다.
- 게임 공간의 유효 범위를 벗어나면 자동으로 리셋되어 초기 위치로 돌아오며, 상태도 함께 초기화된다.
- 이는 사용자의 실수로 인한 낙사 또는 무한 낙하로부터 빠르게 복구할 수 있도록 하기 위함이다.
기믹 요소 설계
기믹 요소는 게임 내에서 플레이어의 진행을 도와주거나 방해하는 동적인 오브젝트들로 구성되어 있다. 모든 기믹 클래스는 MonoBehaviour(또는 SyncBehaviour)를 상속받으며, 일부는 IClearableGimmic 인터페이스를 구현하여 스테이지 리셋 시 상태 복원이 가능하도록 설계되어 있다. 다음은 각 기믹 클래스들의 역할과 기능이다.
- BrokenBoard 클래스
- 플레이어가 바닥에 닿으면 일정 시간 후 바닥이 사라지는 붕괴형 발판 기믹이다.
- 붉은색으로 색상을 바꾼 후 ColliderPlatform을 비활성화하고 자기 자신도 비활성화된다.
- CubeZMover 클래스
- 일정 속도로 X축 또는 Z축을 따라 왕복 운동하는 움직이는 발판이다.
- Mathf.PingPong을 활용하여 자연스러운 반복 이동을 구현하며, 호스트 측에서 위치 동기화를 수행한다.
- HammerSwing 클래스
- Z축을 중심으로 좌우로 회전하며, 회전 방향이나 각도는 설정값을 통해 조정할 수 있다.
- FixedUpdate()에서 회전 동작을 수행하며, 호스트에서만 회전 값을 네트워크로 동기화한다.
- JumpPad 클래스
- 플레이어가 트리거에 진입하면 사전에 설정된 방향으로 힘을 가해 점프시키는 발판이다.
- Rigidbody.AddForce()를 사용하여 물리적 힘을 적용한다.
- KeyTrigger 클래스
- 플레이어가 트리거에 진입하면 해당 컴포넌트에 연결된 문을 열고, 자신은 비활성화된다.
- MovingScrew 클래스
- 톱니 모양의 장애물로, 주기적으로 X축으로 좌우 움직인다.
- PickUp 클래스
- 플레이어가 획득 시 점수 추가, 데스 처리 등의 효과를 발생시키는 수집형 오브젝트이다.
- PickupType 열거형을 통해 타입을 구분하며, Score 및 Death 타입이 구현되어 있다.
- RepeatingCrusher 클래스
- 일정 주기로 전방으로 돌진한 후 다시 원위치로 복귀하는 반복형 해머 기믹이다.
- 돌진 도중 플레이어를 감지하면 플레이어의 BreakDown()을 호출하여 파괴 액션을 취한다.
- TeleportPad 클래스
- 연결된 게임 오브젝트의 위치로 플레이어를 순간이동시키는 패드형 기믹이다.
- 대상 플레이어의 인터페이스(IBallControl)를 통해 위치를 직접 조작한다.
- TriggerPlate 클래스
- 플레이어가 충돌하면 발판이 내려가고 연결된 문이 열리며, 시간이 지난 후 자동으로 복원된다.
UI 설계
게임 내 상태 변화를 UI에 반영하기 위해 옵저버 패턴을 적극 활용하였으며, 이를 위해 ReactiveProperty<T>와 IReadOnlyReactiveProperty<T>라는 구조를 설계에 도입하였다. 모델 내부의 상태 변경을 View(UI)에 자동으로 반영함으로써, 모델-뷰 간 결합을 줄이고, 유지보수성과 확장성을 향상시켰다.
- 설계 개요
- ReactiveProperty<T>는 값이 변경되었을 때 구독 중인 콜백 함수들에게 자동으로 알림을 전달하는 구조로, 옵저버 패턴을 기반으로 구현되었다.
- 외부에서는 IReadOnlyReactiveProperty<T>를 통해 읽기 및 구독만 허용하며, 직접 값 변경은 불가능하도록 캡슐화하였다.
- Unity 환경의 특성상, 이벤트 콜백은 항상 메인 스레드에서 실행되어야 하므로, 내부적으로 Managers.Dispatch()를 사용해 UI 이벤트를 안전하게 실행하도록 하였다.
- 적용 방식 및 흐름
-
- 모델(Model)에서의 상태 정의
- 모델 클래스(예: GameManager, SessionManager)에서는 관리하고자 하는 상태 프로퍼티들을 ReactiveProperty<T>로 래핑하여 정의하였다.
- 외부에는 IReadOnlyReactiveProperty<T> 형태로 노출하여, 구독만 가능하도록 구성하였다.
- 뷰(View)에서의 상태 구독
- UI 요소에서는 상태의 변경을 구독(Subscribe)하고, 변경 시 등록한 콜백 함수가 호출되어 화면을 새로 렌더링한다.
- 이 방식으로 모델 내부에 UI 로직이 들어가지 않도록 분리함으로써 관심사의 분리가 가능해졌다.
- 컨트롤러(Controller)에서의 상태 조작
- 사용자의 입력이나 이벤트에 따라 컨트롤러가 모델의 상태를 변경하며, 이 변경은 자동으로 UI 반영으로 이어진다.
-
- 설계 효과
- 모델과 뷰 간의 의존성을 제거하여 유지보수가 쉬워졌다.
- 상태 변경이 있을 때만 UI가 렌더링되어, 렌더링 효율이 향상되었다.
- UI 반영 누락과 같은 오류 가능성을 줄여 내부 상태와 UI 간의 일관성 유지가 가능해졌다.
- 값의 변경과 UI의 갱신이 명확하게 연결되어 있어 디버깅 시 흐름 추적이 쉬워졌다.
P2P 통신 및 RPC 설계
P2P 통신을 위해 WebRTC를 어떻게 구현하였고, 확립된 통신 채널을 이용해 두 Peer 간 동기화를 RPC로 어떻게 구현하였는지 아래에 설명한다.
- WebRTC 시그널링
-
- WebRTC는 NAT(라우터)를 넘어 Peer 간 직접 연결(P2P)을 설정하기 위해 초기 협상 과정인 시그널링(Signaling) 단계를 거친다. 이 과정에서 양쪽 Peer는 Session Description(Offer/Answer)과 ICE Candidate(네트워크 후보군)을 교환하며, 연결을 설정하기 위한 정보를 주고 받는다.
- 서로의 연결 정보를 모르는 상태에서 시그널링을 할 순 없으므로, WebSocket 기반 임시 통신 채널을 열어 WebRTC 시그널링 정보를 터널링하는 서버를 구현했다. 이 서버는 추후 설명할 게임 룸 서버와 통합되어 있어, 게임 룸에 입장한 두 플레이어 간의 정보를 알 수 있으며, 시그널링에 필요한 정보 또한 터널링하여 전송할 수 있다.
- 시그널링 과정은 다음 단계로 구성된다.
- 호스트가 시그널링 서버(룸 서버)에 등록한다.
- 게스트는 호스트의 룸 코드를 입력하여 시그널링 서버(룸 서버)에 참가한다.
- STUN 서버를 통해 호스트 자신의 연결 정보를 수집한다(IP, UDP Port 등).
- 수집된 호스트의 연결 정보를 시그널링 터널링 서버를 통해 게스트로 전송한다.
- 게스트도 마찬가지로 STUN 서버를 통해 게스트 자신의 연결 정보를 수집한다.
- 수집된 게스트의 연결 정보를 시그널링 터널링 서버를 통해 호스트로 전송한다.
- 게스트는 연결 정보를 기반으로 데이터 채널을 생성하여 연결 제안(Offer)를 호스트에게 전송한다.
- 호스트는 게스트의 연결 제안(Offer)를 받고 게스트에 답장(Answer)함으로써 통신 채널이 수립된다(이 단계에서는 더 이상 시그널링 터널링 채널이 필요하지 않는다).
-
- RPC를 통한 게임 상태 동기화
-
- WebRTC로 수립된 데이터 채널을 이용하여 두 Peer 간 정보 교환이 실시간으로 이루어질 수 있게 됐다. 두 Peer는 서로 같은 코드를 공유하고 있다는 가정 하에 RPC(Remote Procedure Call)을 구현하여, 호스트가 필요 시 게스트에게 특정 액션을 취하도록 할 수 있도록 설계했다.
- 호스트에서 모든 물리 연산을 수행하고 난 위치(Position) 및 회전(Rotation) 결과를 게스트에게 실시간으로 전송하여 호스트와 게스트 간 게임 오브젝트의 동기화를 이루고, 게임의 상태(점수 및 클리어 여부) 변경 또한 호스트에서 이루어질 시 동일하게 게스트에도 적용되도록 설계했다.
- 구체적인 동기화 과정은 아래와 같다.
- SyncObjectId가 붙은 게임 오브젝트에 SyncBehaviour를 상속받은 컴포넌트가 SyncRPC 애트리뷰트가 붙은 사용자 정의 RPC 메서드를 호출한다.
- SyncManager는 SyncBehaviour 컴포넌트가 호출한 RPC 메서드를 내부(호스트)에서도 호출하고 이를 직렬화하여 WebRTC로 수립한 데이터 채널을 통해 상대편(게스트)으로 전송한다.
- 이때, NAT Traversal이 되는 상황에서는 UDP 전송을 수행하고, 그렇지 않은 특수한 상황에서는 어쩔 수 없이 외부 TURN 서버로 릴레이하여 fallback 처리한다.
- 상대편(게스트)는 RPC 메시지를 수신하여 역직렬화하여 어떤 게임 오브젝트의 어떤 컴포넌트의 어떤 메서드를 호출해야 하는지 알아내어 이를 호출한다.
-
- 동기화 클래스 설계
-
- SyncManager: 게임 전체에서 RPC 호출 흐름과 동기화 메시지 송수신을 총괄한다.
- 데이터 채널: IDataChannelSync<byte[]> 인터페이스를 통해 외부 통신 채널에 의존하며, SessionManager에 의해 원격지와의 통신이 수립되는 시점에 주입되어 생명주기를 공유한다.
- 메서드 호출: InvokeSyncRPC, FixedSyncRPC 메서드를 통해 실시간 또는 일정 주기마다 RPC 호출을 큐잉하여 원격지에 전송한다.
- 메시지 처리: SyncRPCMessage 객체를 생성, 직렬화 및 역직렬화하여 RPC 메서드를 호출한다.
- 오브젝트 매핑: 내부적으로 SyncObjectId와 컴포넌트 이름을 기반으로 SyncBehaviour를 찾아 호출한다.
- 게스트 준비 상태 추적: 상대 피어의 준비 여부를 확인하고, 필요 시 전송을 지연한다.
- SyncBehaviour: 게임 오브젝트에 부착되는 동기화 대상 컴포넌트이며, 실제로 원격 호출될 메서드를 보유한다.
- 메서드 자동 등록: SyncRPCAttribute로 정의된 메서드를 런타임에 반영(reflection)하여 등록한다.
- 위치/회전 동기화: SyncPosition, SyncRotation 등의 메서드를 통해 Transform을 주기적으로 전송한다.
- 호출 래퍼 제공: InvokeSyncRPC, QueueSyncRPC를 통해 SyncManager를 직접 호출하지 않고 메서드 이름만으로 원격 호출을 가능하게 한다.
- 식별자 기반 연동: SyncObjectId를 통해 고유 식별자를 부여받으며, 두 피어 간 동기화 식별자로 사용된다.
- SyncObjectId: 모든 SyncBehaviour가 부착되는 게임 오브젝트에는 이 컴포넌트가 존재해야 하며, 동기화 대상 객체를 UUID 기반으로 고유 식별한다.
- SyncRPCAttribute: RPC 메서드를 정의할 때 사용되는 커스텀 어트리뷰트(Attribute)이다. 리플렉션을 통해 해당 속성이 부여된 메서드만 실행 가능하도록 한다.
- 반환값은 반드시 void여야 하며, 특정 타입만 파라미터로 허용한다.
- FindMethods(object)를 통해 클래스 단위의 RPC 메서드 매핑을 수행한다.
- SyncRPCMessage: RPC 호출 정보를 담는 구조체로, 네트워크를 통해 전송되는 단위 메시지이다.
- ObjectId, ComponentName, MethodName, Parameters를 포함하며, 버퍼 기반 직렬화 및 역직렬화 기능을 내장한다.
- WriteTo, ReadFrom 메서드를 통해 고정된 크기의 Span<byte>를 사용하여 GC Pressure를 줄이고 성능을 최적화한다.
- IDataChannelSync<T>: WebRTC 등의 데이터 채널을 추상화한 인터페이스로, SyncManager와 외부 간의 통신 계층을 분리한다.
- 송신(SendData)뿐 아니라 수신(SubscribeData), 끊김 감지(SubscribeDisconnected), 종료 처리(SubscribeClosed) 콜백을 모두 제공한다.
- 이 인터페이스는 외부에서 구현되어 SyncManager.Initialize()를 통해 주입된다.
-
게임 룸 서버 설계
- 개요
- 서로 모르는 두 플레이어가 같은 방(room)에 접속하기 위해 중앙에서 관리되는 서버가 필요하다.
- Node.js 기반 NestJS 서버를 통해 Room Manager를 구현하여 각 방의 상태와 두 플레이어의 연결 정보를 한 곳에서 관리한다.
- 각 컨트롤러(웹 또는 게임 클라이언트)는 이 서버를 통해 룸을 생성·입장하고, 지속적으로 자이로 값을 전송한다.
- 서버는 실시간 WebSocket(또는 REST) API를 통해 자이로 데이터를 모아 Single Source of Truth를 유지하며, 필요 시 WebRTC 시그널링도 제공한다.
- 아키텍처 설계
- Repository Layer
- Service Layer
- Controller Layer
-
- GameRoomController: /rooms 경로에서 룸 생성, 조회, 입장/퇴장, 자이로 관련 REST API를 제공한다.
- GameRoomGateway: update-gyro 웹소켓 이벤트를 받아 GameRoomService의 자이로 값 갱신 메서드를 호출한다.
- WebRTCSignalingGateway: /webrtc-signaling 경로에서 register/offer/answer/ice-candidate 등을 처리하여 상대 피어로 전달한다.
- ClientVersionController: /client-version/check 엔드포인트로 클라이언트 버전을 검사한다.
- HealthController: /health 경로에서 단순한 상태 체크 API를 제공합니다.
-
- API 설계
경로 | 메소드 | 설명 | 파라미터 |
---|---|---|---|
/rooms | POST | 게임 룸 생성 | Header: game-client-id |
/rooms/{roomId} | GET | 게임 룸 조회 | Path: roomId Header: game-client-id |
/rooms/{roomId}/join | POST | 게임 룸 입장 | Path: roomId Header: game-client-id |
/rooms/{roomId}/leave | POST | 게임 룸 퇴장 | Path: roomId Header: game-client-id |
/rooms/{roomId}/gyro | GET | 자이로 상태 조회 | Path: roomId |
/rooms/{roomId}/gyro | POST | 자이로 상태 갱신 | Path: roomId Header: game-controller-id Body: GyroDTO |
/rooms/{roomId}/gyro/join/{axis} | POST | 자이로 제어권 요청 | Path: roomId, axis Header: game-controller-id |
/rooms/{roomId}/gyro/release/{axis} | POST | 자이로 제어권 반환 | Path: roomId, axis Header: game-client-id |
/rooms/{roomId}/code | GET | 단축 코드 조회 | Path: roomId Header: game-client-id |
/rooms/code/{shortCode}/join | POST | 단축 코드로 입장 | Path: shortCode Header: game-client-id |
스테이지 레벨 디자인
결과 및 평가
완료 작품 소개
설치 및 실행
- 랜딩 페이지(gyrodrop.xyz) 접속 후 게임 클라이언트 다운로드
-
- 또는 Stove 플랫폼에서도 다운로드 및 설치 가능
-
- 압축 해제 후 폴더를 열어 Gyrodrop 실행
완료작품의 평가
평가 점수
아래의 평가 방식대로 ((기능 점수 * 기능 중요도 계수)의 합 * 100)을 계산하여 100점 만점을 기준으로 평가한다.
분류 | 기능 명칭 | 평가 방식 | 기능 점수 | 중요도 계수 | 종합 점수 |
---|---|---|---|---|---|
GR1 | 게임 룸 생성 | 개발 여부 (개발: 1, 미개발: 0) |
1 | 0.07 | 0.07 |
GR2 | 게임 룸 입장 | 개발 여부 | 1 | 0.07 | 0.07 |
GR3 | 스테이지 플레이 | 개발 여부 | 1 | 0.07 | 0.07 |
GY1 | 자이로 데이터 취득 | 개발 여부 | 1 | 0.07 | 0.07 |
GY2 | 자이로 대체 컨트롤 | 개발 여부 | 1 | 0.07 | 0.07 |
GY3 | 자이로 반응 속도 | max(0, 1 - (반응속도 / 100)) | max(0, 1 - 80/100) = 0.2 | 0.12 | 0.024 |
GY4 | 자이로 데이터 취합 | 개발 여부 | 1 | 0.07 | 0.07 |
GS1 | 기믹 상호작용 | max(1, 구현된 기믹 수 / 6) | max(1, 10/6) = 1 | 0.08 | 0.08 |
GS2 | 협동형 레벨 디자인 | 실제비율 / 100 | 8/9 = 0.89 | 0.10 | 0.089 |
GS3 | 네트워크 동기화 | max(0, 1 - (Latency / 30)) *Latency는 교내 무선랜 환경에서 측정 |
max(0, 1 - 34.378 / 30) = 0 *34.378ms는 우리 목표치에 근접한 수치로, 평가 식을 잘못 세워 위와 0점이 나왔으나, 기준치에는 충족함. |
0.10 | 0 |
GS4 | 렌더링 | min(1, FPS / 60) *FPS는 평균값 사용 |
min(1, 59.547 / 60) = 0.99 | 0.10 | 0.099 |
GD1 | 레벨 에디터 도구 | 개발 여부 | 1 | 0.02 | 0.02 |
GD2 | 배포 및 서버 관리 | 개발 여부 | 1 | 0.06 | 0.06 |
합계 | 1.00 | 0.792 |
100점 만점 중 79.2점을 달성하였다.
자이로 취합 Latency 측정(GY3)
- 자이로 웹 컨트롤러가 자이로 데이터를 보낸 시점을 Unix Timestamp(ms)로 기록하고, Unity 게임 클라이언트에서는 자이로 데이터를 받은 시점을 Unix Timestamp(ms)로 기록하여, 두 시계열 데이터를 분석하였다.
- 자이로 데이터 중 Pitch 정보만 분석하였으며, 두 시계열 데이터를 10ms 단위로 보간하고 정규화(z-score)하여 상호상관(Cross-correlation) 분석하여 가장 유사한 시점의 시간 지연을 추정한다.
- 분석 방식
correlation = correlate(client_z, controller_z, mode='full') lags = np.arange(-len(client_z) + 1, len(client_z)) best_lag = lags[np.argmax(correlation)] delay_ms = best_lag * 10
네트워크 동기화 Latency 측정(GS3)
- 같은 네트워크 내에 있는 서로 다른 두 피어에 Unity 게임 클라이언트를 설치하여, 호스트는 시퀀스 번호를 전송하여 그 시점의 Unix Timestamp를 기록, 게스트는 시퀀스 번호를 받으면 그 시점의 Unix Timestamp를 기록하여 지연 시간을 측정하도록 했다.
- 두 피어(호스트, 게스트)는 같은 NTP 서버를 사용하도록 하였고, 시간 동기화를 1ms 내로 마쳤다.
- 약 10초 정도 측정하였으며, 호스트와 게스트 간의 시퀀스 번호의 Unix Timestamp의 차를 구하여 Latency를 측정하였다.
향후 평가
어려웠던 점
- 물리엔진 기반으로 캐릭터를 움직일 경우, 플랫폼 회전 시 공이 의도치 않게 공중에 뜨는 현상이 발생하였다. 특히, 플랫폼이 반대 방향으로 급격히 회전하는 경우에 해당 문제가 심화되었다. 이를 해결하기 위해 캐릭터 위치를 기준으로 플랫폼에 수직으로 사영(투영)시키는 로직을 도입하여 항상 플랫폼에 접지하도록 처리하였다. 이후 접지 상태에서 속도를 별도로 제어하는 방식으로 안정적인 움직임을 구현하였다.
- 자이로 센서의 서로 다른 축 입력값을 실시간으로 통합하여 하나의 플랫폼 회전값으로 계산하는 시스템을 구현하였다. 센서 입력의 수집 및 연산은 정상적으로 처리되었으나, 계산된 회전값을 멀티플레이어 양측에서 동일하게 재현하는 부분에서 어려움이 발생하였다. 양측 클라이언트 간 동기화 차이를 최소화하기 위해 네트워크 연산 구조를 조정하였다.
- 전담 그래픽 디자이너 부재로 인해, 게임 컨셉에 부합하는 적절한 에셋 확보에 시간이 소요되었다. 확보한 에셋을 실제 맵에 배치하는 과정 역시 미적 감각이 요구되어 그래픽 품질 측면에서 한계가 존재하였다. 최적화된 배치와 반복적인 테스트를 통해 최대한 시각적 완성도를 유지하려 노력하였다.
- 초기 맵 제작 시, 각 플랫폼이 독립적으로 자이로센서 값을 받아 움직이도록 설계하였다. 하지만 실제 게임 진행에서는 모든 플랫폼이 하나의 전역 좌표축을 기준으로 움직여야 플레이 감각이 자연스러웠다. Unity에서 제공하는 4가지 좌표계(Center, Pivot, Global, Local) 중, Pivot + Global 기준으로 맵을 재설계하여 일관된 회전 중심을 설정하였다. 이를 통해 자이로센서 입력에 따른 플랫폼 회전이 전체 맵에서 일관되게 적용되도록 시스템을 개선하였다.
- 멀티플레이 게임을 구현하기 위해 기존의 서버-클라이언트 기반 동기화 프레임워크들(Netcode, FishNet, Mirror 등)을 검토했지만, 우리 게임의 특수한 요구사항에 적합한 P2P 기반 동기화 프레임워크는 존재하지 않아 직접 아키텍처를 설계하고 구현해야 했다. 본 프로젝트는 2인 협동 게임으로, 플레이어 간의 물리 연산 상태가 정밀하게 일치해야 하며, 물리적으로 떨어진 위치에서도 원활하게 플레이할 수 있어야 했다. 이러한 요구를 바탕으로, 서버 없이 동작하는 P2P 구조를 도입함으로써 비용을 절감하고 구조를 단순화할 수 있다는 장점이 있었지만, NAT 환경에서의 연결 문제 등 여러 네트워크 제약을 해결하는 데 어려움이 따랐다. 이러한 문제를 해결하기 위해 WebRTC를 도입하였고, NAT Traversal이 불가능한 환경에서도 안정적인 연결이 가능하도록 TURN 서버를 구성하여 릴레이 방식의 Fallback을 제공하였다. 또한 동기화 과정에서 필요한 원격 프로시저 호출(RPC) 기능도 자체적으로 구현해야 했는데, 이 과정에서 C#의 리플렉션 기능을 활용하여 원격에서 호출할 메서드와 게임 오브젝트를 어떻게 식별하고 실행할지에 대해 많은 시행착오를 겪으며 해결해 나갔다. 전체적으로 네트워크 구조뿐만 아니라 통신 안정성과 동기화 정확도를 확보하는 것이 매우 도전적인 과제였지만, 직접 구현한 경험을 통해 네트워크 아키텍처에 대한 이해를 크게 확장할 수 있었다.
차후 구현할 내용
- 초기 플레이타임이 짧다는 피드백을 수용하여, 스테이지를 추가 구현하여 전체적인 플레이 시간을 확장할 계획이다. 난이도, 기믹 다양성, 컨트롤 난이도를 적절히 조절하여 플레이어의 몰입감을 유지하며 콘텐츠 볼륨을 증가시킬 예정이다.
- 기존 회전 플랫폼의 크기가 커질 경우, 중심 회전축으로부터 거리가 먼 외곽부에서는 기하학적 속도가 과도하게 증가하는 문제가 있었다. 이로 인해 공이 회전 플랫폼 위에서 미끄러지듯 움직이며, 조작감이 저하되는 현상이 발생하였다. 플랫폼 회전 보정 로직을 개선하여, 회전 반경과 공의 상대적 속도를 보다 자연스럽게 보정하고, 플레이어가 플랫폼에 안정적으로 붙어 이동할 수 있도록 조작감을 개선할 예정이다.
- 네트워크 기반 멀티플레이 환경에서 양측 플레이어 간 위치 동기화 및 물리 연산 지연으로 인해 미세한 입력 차이가 발생하는 현상이 확인되었다. 동기화 알고리즘을 최적화하고, 네트워크 패킷 효율화를 통해 보다 부드러운 화면 전환과 입력 반응성을 제공할 예정이다.
- 일부 유저가 게임 시작 시 자이로 센서 축 방향을 직관적으로 파악하기 어려워하는 문제가 발생하였다. 현재 “수평/수직”이라는 텍스트 안내만 제공되어 초기 적응에 혼란이 있었다. 게임 시작 전, 센서 기준 축 방향 및 초기 자세를 그림으로 시각화하여 안내하는 가이드를 추가할 예정이다. 이를 통해 신규 유저의 초기 적응성을 크게 향상시킬 것으로 기대된다.
- 일부 유저가 별도의 외부 컨트롤러가 필요한 것으로 오인하는 사례가 확인되었다. 본 게임이 모바일 기기의 자이로 센서만으로 조작 가능함을 명확히 안내하는 전용 UI를 추가하여, 혼동을 최소화할 계획이다.
개발 사업비 정산
구성원 및 추진체계
구성원
- 조성채(팀장): 게임 클라이언트 개발, 프로젝트 총괄
- 이현제(팀원): 게임 클라이언트 개발, 레벨 디자인
- 이성호(팀원): 게임 클라이언트 개발, 서버 개발
개발 일정
단계별 세부개발 내용 | 담당자 | 3월 | 4월 | 5월 | 6월 |
---|---|---|---|---|---|
프로젝트 주제 및 컨셉 확정 | 전원 | ||||
게임 상세 기획 | 전원 | ||||
그래픽 리소스(에셋 등) 확보 | 전원 | ||||
게임 레벨 디자인 | 이성호, 이현재 | ||||
게임 기능 개발 | 조성채 | ||||
서버 설계 및 개발 | 이성호, 이현재 | ||||
UI 구현 | 조성채 | ||||
설계 보고서 작성 | 전원 | ||||
게임 테스트 | 전원 | ||||
플랫폼 등록 | 전원 | ||||
피드백 및 보완 | 전원 |
소스코드 관리 및 협업 체계
- GitHub Team 기능을 활용하여 모든 코드를 중앙 Repository에서 관리한다.
- 기능 단위 개발은 feature 브랜치에서 진행하며, 완료된 작업은 Pull Request(PR)를 통해 dev 브랜치에 제안한다.
- PR은 팀원 간 코드 리뷰를 통해 Approve된 경우에만 Dev 브랜치에 병합(Merge)할 수 있다.
- 병합 전에는 항상 최신 dev 브랜치 기준으로 Rebase를 수행하여 충돌 가능성을 사전에 방지하고, 커밋 히스토리를 정돈한다.
- 주요 릴리스 시점에는 dev 브랜치를 main 브랜치에 병합하고, 이를 기준으로 최종 배포를 진행한다.
개발사업비 내역서
(단위: 원)
항목 (품명, 규격) | 수량 | 단가 | 금액 계 | 금액 현금 | 비고 |
---|---|---|---|---|---|
개발 관련 온라인 강의 [C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part3: 유니티 엔진 |
1 | 66,000 | 66,000 | 66,000 | |
개발 관련 온라인 강의 [입문자를 위한 UE5] Part1. 언리얼 엔진 블루프린트 |
1 | 55,000 | 55,000 | 55,000 | |
서버 비용 gyrodrop.xyz 도메인, Route 53 |
1 | 26,180 | 26,180 | 26,180 | |
다람쥐 모델 에셋 | 1 | 8,570 | 8,570 | 8,570 | |
벨킨 connect USB C 6in1 멀티 포트 허브 어댑터 AVC008fqSGY V2 |
1 | 49,900 | 49,900 | 49,900 | |
가상 면접 사례로 배우는 대규모 시스템 설계 기초 | 1 | 21,600 | 21,600 | 21,600 | |
가상 면접 사례로 배우는 대규모 시스템 설계 기초 2 | 1 | 32,400 | 32,400 | 32,400 | |
가상 면접 사례로 배우는 머신러닝 시스템 설계 기초 | 1 | 24,300 | 24,300 | 24,300 | |
문구비 | 1 | 3,000 | 3,000 | 3,000 | |
회의 지원금 | 1 | 113,800 | 113,800 | 113,800 | |
합계 | 400,750 | 400,750 | 400,750 |