"1분반-자이로드롭"의 두 판 사이의 차이

cdc wiki
이동: 둘러보기, 검색
(2.6 스테이지 레벨 디자인)
3번째 줄: 3번째 줄:
 
==프로젝트 개요==
 
==프로젝트 개요==
 
=== 기술개발 과제 ===
 
=== 기술개발 과제 ===
''' 국문 : ''' 협동심 증진 및 공감각 발달을 위한 게임 ‘자이로드롭’ 개발
+
* '''국문: 협동심 증진 및 공감각 발달을 위한 게임 ‘자이로드롭’ 개발'''
 
+
* '''영문: Gyrodrop: A Game for Boosting Teamwork and Enhancing Multisensory Development'''
''' 영문 : ''' (Gyrodrop: A Game for Boosting Teamwork and Enhancing Multisensory Development)
 
  
 
===과제 팀명===
 
===과제 팀명===
17번째 줄: 16번째 줄:
  
 
===구성원 소개===
 
===구성원 소개===
서울시립대학교 컴퓨터과학부 2020920058 조성채(팀장)
+
* 서울시립대학교 컴퓨터과학부 2020920058 조성채(팀장)
 
+
* 서울시립대학교 컴퓨터과학부 2020920051 이현제(팀원)
서울시립대학교 컴퓨터과학부 2019920037 이성호(팀원)
+
* 서울시립대학교 컴퓨터과학부 2019920037 이성호(팀원)
 
 
서울시립대학교 컴퓨터과학부 2020920051 이현제(팀원)
 
  
 
==서론==
 
==서론==
 
===개발 과제의 개요===
 
===개발 과제의 개요===
 
====개발 과제 요약====
 
====개발 과제 요약====
· 모바일 디바이스의 자이로센서 데이터를 이용해 게임 내 플랫폼을 기울여 캐릭터의 위치를 조작하는 3D-Platformer, 퍼즐 게임 개발
+
* 모바일 디바이스의 자이로센서 데이터를 이용해 게임 내 플랫폼을 기울여 캐릭터의 위치를 조작하는 3D-Platformer, 퍼즐 게임 개발
 
+
* 1인 모드(전체 축 조작)와 2인 모드(Pitch, Roll 축 분담) 지원으로 협동성 극대화
· 1인 모드(전체 축 조작)와 2인 모드(Pitch, Roll 축 분담) 지원으로 협동성 극대화
+
* 호스트 중심 물리 연산 + WebRTC P2P 네트워킹으로 플레이어 간 멀티 플레이 지원
 
+
* 크로스 플랫폼(Windows, macOS) + 모바일 웹 컨트롤러 지원으로 접근성 확대
· 호스트 중심 물리 연산 + WebRTC P2P 네트워킹으로 플레이어 간 멀티 플레이 지원
 
 
 
· 크로스 플랫폼(Windows, macOS) + 모바일 웹 컨트롤러 지원으로 접근성 확대
 
 
 
====개발 과제의 배경 및 효과 ====
 
· 모바일 VR·센서 기반 인터랙션 시장 확대, 캐주얼 협동 게임의 수요 증가
 
 
 
· 기기 내장 자이로센서 활용으로 별도 디바이스 없이 본인의 스마트폰 사용 가능
 
 
 
· 실시간 P2P 멀티플레이 지원으로 원격지의 사용자와 협동 플레이 가능
 
 
 
· 교육·재활(노인 치매 예방, 협동 훈련) 등 파생 활용 가능
 
  
====개발 과제의 목표 내용====
+
====개발 과제의 배경 효과====
· 협동 플레이를 유도하는 게임 맵 디자인 - 하나의 축만을 이용하여 게임을 클리어하기 어렵도록 설계
+
* 모바일 VR·센서 기반 인터랙션 시장 확대, 캐주얼 협동 게임의 수요 증가
 +
* 기기 내장 자이로센서 활용으로 별도 디바이스 없이 본인의 스마트폰 사용 가능
 +
* 실시간 P2P 멀티플레이 지원으로 원격지의 사용자와 협동 플레이 가능
 +
* 교육·재활(노인 치매 예방, 협동 훈련) 등 파생 활용 가능
  
· 원격지 멀티 플레이 실시간성 확보 – 게임 클라이언트 간 실시간 동기화 지연 시간을 30ms 내외로 유지
+
====개발 과제의 목표와 내용====
 +
* 협동 플레이를 유도하는 게임 맵 디자인 - 하나의 축만을 이용하여 게임을 클리어하기 어렵도록 설계
 +
* 원격지 멀티 플레이 실시간성 확보 – 게임 클라이언트 간 실시간 동기화 지연 시간을 30ms 내외로 유지
 +
* 다양한 기믹 요소(열쇠, 발판, 점프대, 이동 플랫폼, 부숴지는 발판 등)를 구현하여 게임의 난이도와 긴장도를 높임
 +
* 9개의 맵(3가지 난이도, 각 난이도별 3개의 맵) 개발
 +
* 웹 컨트롤러 연동으로 별도의 컨트롤러 없이도 PC에서 플레이 가능하도록 설계 – 컨트롤러 지연 시간은 100ms 내외로 유지
 +
====개발과제의 기술적 기대효과====
 +
* 자이로 데이터 실시간 취합 및 클라이언트(피어) 간 실시간 동기화 기술 개발
 +
* WebRTC 기반의 P2P 게임 상태 동기화 기술 구현
 +
====개발과제의 경제적 및 사회적 파급효과====
 +
* 친구 및 가족과 2인 협동으로 가볍게 즐길 수 있는 소셜 게임
 +
* 협동심 증진 및 공감각 발달에 도움을 주어 노인 치매 예방 프로그램으로 활용 가능
  
· 다양한 기믹 요소(열쇠, 발판, 점프대, 이동 플랫폼, 부숴지는 발판 등)를 구현하여 게임의 난이도와 긴장도를 높임
 
 
· 9개의 맵(3가지 난이도, 각 난이도별 3개의 맵) 개발
 
 
· 웹 컨트롤러 연동으로 별도의 컨트롤러 없이도 PC에서 플레이 가능하도록 설계 – 컨트롤러 지연 시간은 100ms 내외로 유지
 
  
 
===관련 기술의 현황===
 
===관련 기술의 현황===
 
====관련 기술의 현황 및 분석(State of art)====
 
====관련 기술의 현황 및 분석(State of art)====
*전 세계적인 기술현황
+
# 자이로 센서
1) 자이로 센서
+
#* 자이로 센서는 각속도를 측정하여 회전 방향과 속도를 정확히 감지하는 역할을 한다. 최근의 자이로 센서 기술은 MEMS(미세전자기계 시스템) 기반으로 소형화 및 고정밀화가 이루어졌으며, 현실 세계와 가까운 가상 환경 경험을 제공할 수 있기에 스마트폰, VR 기기, 게임 컨트롤러 등 다양한 분야에서 필수적인 기술로 자리 잡았다.
  a) 자이로 센서는 각속도를 측정하여 회전 방향과 속도를 정확히 감지하는 역할을 한다. 최근의 자이로 센서 기술은 MEMS(미세전자기계 시스템) 기반으로 소형화 및 고정밀화가 이루어졌으며,  
+
#* 최근 자이로 센서는 가속도 센서와 결합하여 6축 센서를 구성하며, 여기에 자기장 센서를 추가해 9축 센서로 발전하였다. 이를 통해 더욱 정확한 공간 인식과 자세 추적이 가능해졌다.
현실 세계와 가까운 가상 환경 경험을 제공할 수 있기에 스마트폰, VR 기기, 게임 컨트롤러 등 다양한 분야에서 필수적인 기술로 자리 잡았다.
+
#* 최신 자이로 센서는 초당 300~2000 DPS(degrees per second)의 정밀한 각속도 측정 범위를 제공하며, 모바일 게임 환경에서 미세한 움직임까지 정확히 감지할 수 있게 되었다.
  b) 최근 자이로 센서는 가속도 센서와 결합하여 6축 센서를 구성하며, 여기에 자기장 센서를 추가해 9축 센서로 발전하였다. 이를 통해 더욱 정확한 공간 인식과 자세 추적이 가능해졌다.
+
# 게임 엔진
  c) 최신 자이로 센서는 초당 300~2000 DPS(degrees per second)의 정밀한 각속도 측정 범위를 제공하며, 모바일 게임 환경에서 미세한 움직임까지 정확히 감지할 수 있게 되었다.
+
#* 게임 개발 및 실시간 시뮬레이션 구현을 위한 대표적인 기술로는 Unity Engine과 Unreal Engine이 있다.
 
+
## Unity Engine
2) 게임 엔진
+
##* Unity는 직관적인 인터페이스와 높은 접근성을 바탕으로, 다양한 플랫폼에서의 실시간 콘텐츠 개발을 지원하는 범용 게임 엔진이다.
  a) 게임 개발 및 실시간 시뮬레이션 구현을 위한 대표적인 기술로는 **Unity Engine**과 **Unreal Engine**이 있다.
+
##* 모바일, 데스크탑, 웹, 콘솔, XR(VR/AR) 등 크로스 플랫폼 개발에 최적화되어 있으며, 하나의 프로젝트로 다수의 플랫폼에 쉽게 빌드할 수 있는 기능을 제공한다.
  b) Unity Engine
+
##* 기술적으로는 NVIDIA의 PhysX 엔진을 기반으로 한 3D 물리 시뮬레이션과, Box2D 기반의 2D 물리 엔진을 내장하고 있어 물리 기반 상호작용 구현이 용이하다. 또한 DOTS(Data-Oriented Technology Stack) 및 ECS(Entity-Component-System) 구조를 통해 성능 중심의 대규모 데이터 처리 및 병렬 연산을 지원한다.
      i) Unity는 직관적인 인터페이스와 높은 접근성을 바탕으로, 다양한 플랫폼에서의 실시간 콘텐츠 개발을 지원하는 범용 게임 엔진이다.
+
##* Unity는 시각적 툴(Shader Graph, Visual Effect Graph, Timeline )과 풍부한 Asset Store 생태계를 갖추고 있어 빠른 프로토타이핑과 개발 효율 향상에 유리하다.
      ii) 모바일·데스크탑·웹·콘솔·XR 등 크로스 플랫폼 개발에 최적화되어 있으며, 하나의 프로젝트로 다수의 플랫폼에 쉽게 빌드할 수 있는 기능을 제공한다.
+
##* 특히 C# 기반의 스크립팅, 높은 커스터마이징 자유도, 사용자 커뮤니티의 풍부한 기술 자료는 Unity의 장점 중 하나로 꼽힌다.
      iii) NVIDIA PhysX(3D)·Box2D(2D) 기반 물리 시뮬레이션, DOTS/ECS 구조를 통한 병렬 연산 지원.
+
## Unreal Engine
      iv) Shader Graph·Visual Effect Graph·Timeline 시각적 툴과 방대한 Asset Store 생태계 제공.
+
##* Unreal Engine은 Epic Games에서 개발한 고성능 실시간 렌더링 엔진으로, AAA급 게임 및 고품질 비주얼 콘텐츠 제작에 특화되어 있다.
      v) C# 스크립팅과 활발한 커뮤니티 자료가 강점이다.
+
##* 특히 최신 버전인 Unreal Engine 5는 Nanite(가상화 지오메트리), Lumen(실시간 글로벌 일루미네이션)과 같은 첨단 렌더링 기술을 도입하여, 실사 수준의 그래픽 구현이 가능하다.
  c) Unreal Engine
+
##* 고급 물리 효과를 위한 Chaos Physics, Cloth Simulation, Rigid/Soft Body Dynamics 등 다양한 내장 기능을 제공하며, C++ 기반의 강력한 성능 제어와 함께 Blueprint라 불리는 시각적 스크립팅 시스템도 함께 지원되어 비전공자도 게임 로직을 시각적으로 구성할 수 있다.
      i) Epic Games가 개발한 고성능 실시간 렌더링 엔진으로 AAA급 게임 및 고품질 비주얼 콘텐츠 제작에 특화.
+
##* Unreal Engine은 높은 성능과 정교한 표현력을 제공하는 대신, 비교적 높은 시스템 요구사항과 학습 난이도를 수반한다. 그럼에도 불구하고 영화, 건축 시각화, 디지털 트윈 등 게임 이외의 산업 분야에서도 널리 사용되고 있다.
      ii) 최신 버전 UE5는 Nanite(가상화 지오메트리)·Lumen(실시간 글로벌 일루미네이션) 도입으로 실사 수준 그래픽 구현.
 
      iii) Chaos Physics, Cloth Simulation, Rigid/Soft Body Dynamics 등 내장, C++ 성능 제어와 Blueprint 시각 스크립팅 지원. 
 
      iv) 높은 표현력 대비 시스템 요구 사양과 학습 난이도는 높은 편이나, 영화·건축·디지털 트윈 등 산업 분야에서도 널리 사용된다.
 
 
 
====시장상황에 대한 분석====
 
*경쟁제품 조사 비교
 
1) Super Monkey Ball : 키패드/조이스틱 기반 싱글플레이 중심. 자이로 입력과 협동 요소 부재.
 
 
 
2) Tiltagon : 빠른 템포 생존형 싱글플레이. 멀티플레이·협동 요소 없음.
 
 
 
3) Rolling Sky : 터치 드래그 방식 싱글플레이. 자이로·협동 요소 없음.
 
 
 
→ 본 과제 게임은 자이로 기반 직관적 2인 협동 설계로 차별화.
 
 
 
*마케팅 전략 제시
 
1) 대학 커뮤니티(에브리타임·인스타 릴스) 타겟 티저 영상 배포 
 
 
 
2) 자체 랜딩 페이지 gyrodrop.xyz 운영 
 
 
 
3) 게임 스토어 — Stove — 출시
 
 
 
===개발과제의 기대효과===
 
====기술적 기대효과====
 
• 자이로 데이터 실시간 취합 및 피어 간 실시간 동기화 기술 확보
 
• WebRTC 기반 P2P 게임 상태 동기화 기술 구현
 
 
 
====경제적·사회적 기대 및 파급효과====
 
• 친구·가족이 함께 즐기는 2인 협동 소셜 게임 제공
 
• 협동심 증진과 공감각 발달로 노인 치매 예방 프로그램 등 파생 활용 가능
 
 
 
===기술개발 일정 및 추진체계===
 
====개발 일정====
 
[[파일:스크린샷 2025-06-19 오후 3.58.09.png]]
 
 
 
====구성원 및 추진체계====
 
1. 조성채(팀장) : 게임 클라이언트 개발, 프로젝트 총괄
 
 
 
2. 이현제(팀원) : 게임 클라이언트 개발, 레벨 디자인
 
 
 
3. 이성호(팀원) : 게임 클라이언트 개발, 서버 개발
 
 
 
===설계===
 
 
 
====2.1 사용자 요구사항====
 
게임 플레이
 
• 1 (D, 중요도: 대) 플레이어가 멀티플레이 룸을 생성 또는 입장하고, 스테이지를 선택하여 상대방과 게임을 플레이할 수 있다.
 
• 2 (D, 대) 2명의 플레이어가 자이로 센서를 통해 각각 Pitch/Roll 축을 담당하여 판의 기울기를 조작할 수 있다.
 
• 3 (D, 중) 한 스테이지에서 공이 목표 지점까지 최단 거리로 이동하는 시간이 1 분 이내여야 한다.
 
• 4 (D, 대) 협동 플레이를 유도하는 맵 디자인을 제공해야 한다.
 
* 두 축을 동시에 기울여야만 통과 가능한 경로
 
 * 시간차를 맞춰야만 클리어 가능한 점프 구조 등 다양한 기믹 포함
 
• 5 (D, 중) 크로스 플랫폼 지원. 자이로 센서가 없는 기기는 모바일 기기를 컨트롤러로 사용해 조작 가능해야 한다.
 
• 6 (W, 소) 레벨 디자이너용 스테이지 제작 툴을 제공해야 한다.
 
 
 
기술적 요소
 
• 1 (D, 중) 자이로 센서 입력 반응속도 ≤ 100 ms
 
• 2 (D, 대) 게임 서버―클라이언트 실시간 동기화 ≤ 30 ms
 
• 3 (D, 중) 렌더링 ≥ 60 FPS 유지
 
• 4 (W, 중) CI/CD 제공으로 빠른 개발·배포 가능
 
• 5 (W, 소) 오케스트레이션 기반 수평 확장 가능
 
 
 
====2.2 기능 정의 및 정량목표====
 
가. 기능 정의
 
• GR1 게임 룸 생성: 멀티플레이 룸 생성
 
• GR2 게임 룸 입장: 상대방 정보로 룸 입장
 
• GR3 스테이지 플레이: 룸 내 스테이지 선택·플레이
 
• GY1 자이로 데이터 취득: 기기 자이로 데이터 수집
 
• GY2 자이로 대체 취득: 자이로 없는 기기에서 모바일 컨트롤러 사용
 
• GY3 자이로 반응 속도: 게임 반영 ≤ 100 ms
 
• GY4 자이로 데이터 취합: 두 플레이어 자이로 데이터 서버 반영
 
• GS1 기믹 상호작용: 점프대·발판·열쇠 등 ≥ 3종
 
• GS2 스테이지 레벨 디자인: 협동 기믹 포함 맵 비율 ≥ 80 %
 
• GS3 네트워크 동기화: 서버―클라이언트 RTT ≤ 30 ms
 
• GS4 렌더링: 최신 스마트폰 기준 60 FPS 보장
 
• GD1 레벨 에디터 도구: Unity 내부 맵 제작 지원
 
• GD2 배포·서버 관리: Kubernetes·Docker 기반 CI/CD·수평 확장
 
 
 
나. 기능별 정량목표
 
(평가 시 점수 = ∑ [기능 점수 × 중요도 계수] × 100)
 
• GR1 ~ GR3, GY1, GY2, GY4, GD1: 구현 여부(개발 1 / 미개발 0)
 
• GY3: (반응속도 ≤ 100 ms) → 점수 = max(0, 1 – 반응속도/100)
 
• GS1: 점프대·발판·열쇠 구현 기믹 수 n → 점수 = max(1, n/6)
 
• GS2: 협동 기믹 포함 맵 비율 p → 점수 = p/100 (목표 ≥ 0.8)
 
• GS3: RTT ms → 점수 = max(0, 1 – RTT/30)
 
• GS4: 평균 FPS f → 점수 = min(1, f/60)
 
• GD2: 구현 여부(1/0)
 
 
 
====2.3 세부기술 선택사항====
 
• GR1, GR2, GY4: Node.js + NestJS 웹 서버(룸·시그널링·데이터 취합)
 
• GR3, GS1, GS2, GS4: Unity 엔진 채택(C# 스크립팅, 물리·UI·레벨)
 
• GY1, GY2: deviceorientation Web API, React 프런트엔드(모바일 컨트롤러)
 
• GY3: WebSocket 실시간 양방향 통신으로 지연 최소화
 
• GS3: WebRTC P2P, Unity.WebRTC 패키지 + Node.js (Socket.io) 시그널링
 
• GD1: Unity 에디터 내 레벨 제작(전용 툴 없이)
 
• GD2: AWS EC2 + ELB, CloudFront, Docker·Kubernetes, CI/CD 파이프라인
 
 
 
====2.4 게임 클라이언트 설계====
 
매니저 계층
 
• Managers (싱글톤) → GameManager, RoomManager, SessionManager, UIManager, SoundManager 전역 접근·의존성 주입
 
• GameManager: 스테이지 클리어, 로딩, 잠금 관리
 
• RoomManager: 룸 생성·입장·자이로 점유, URL·코드 관리
 
• SessionManager: P2P 연결 관리(WebRTC 등)
 
• SoundManager: BGM·SFX 재생
 
• UIManager: 씬 UI·팝업 UI 생성·관리
 
 
 
플레이어 이동
 
• Raycast로 플랫폼 감지 → 중력 분해 후 표면 사영 이동
 
• 공 중심을 표면에 투영해 겹침·튜닝 방지, 과가속 시 감속력 부여, 낙사 자동 리셋
 
 
 
기믹 클래스(10 종 이상)
 
• BrokenBoard, CubeZMover, HammerSwing, JumpPad, KeyTrigger, MovingScrew, PickUp(Score/Death), RepeatingCrusher, TeleportPad, TriggerPlate 등
 
 
 
UI 설계
 
• ReactiveProperty / IReadOnlyReactiveProperty 옵저버 패턴
 
• Managers.Dispatch()로 메인 스레드 안전 호출, 모델·뷰 분리
 
 
 
P2P 통신·RPC
 
• WebRTC 데이터 채널 수립(Offer/Answer, ICE) → NAT Traversal
 
• SyncManager + SyncBehaviour + SyncRPCAttribute로 RPC 직렬화/역직렬화
 
• Transform·게임 상태 호스트 계산 → 게스트 동기화
 
 
 
====2.5 게임 룸 서버 설계====
 
개요
 
• NestJS 서버가 룸 생성·입장·자이로 값 수집·시그널링 담당
 
 
 
• WebSocket + REST API, 메모리 저장소(Map) 기반 룸 관리
 
 
 
주요 레이어
 
• Repository: GameRoomInMemoryRepository, ShortCodeBase62Repository, ClientVersionJsonRepository
 
 
 
• Service: GameRoomService, WebRTCSignalingService, ClientVersionService
 
 
 
• Controller/Gateway: GameRoomController, GameRoomGateway, WebRTCSignalingGateway, ClientVersionController, HealthController
 
 
 
주요 API (일부)
 
• POST /rooms  룸 생성
 
 
 
• POST /rooms/{id}/join 룸 입장
 
 
 
• GET /rooms/{id}/gyro 자이로 조회
 
 
 
• POST /rooms/{id}/gyro 자이로 갱신
 
 
 
• POST /rooms/code/{short}/join 단축 코드 입장
 
 
 
====2.6 스테이지 레벨 디자인====
 
Stage 1 (Tutorial)
 
[[파일:1.png]]
 
• 기믹: 없음
 
  
• 조작감 학습용, 중력 가속도로만 목적지 도달
+
===관련 시장에 대한 분석===
 +
====경쟁제품 조사 비교====
 +
# Super Monkey Ball: 해당 게임은 키패드나 조이스틱 기반 조작으로 플랫폼 위의 캐릭터를 조종하는 싱글플레이 중심의 게임이다. 멀티플레이 요소는 제한적이며, 자이로 센서를 활용한 조작 방식은 지원하지 않아 실제 기기 움직임과의 연동 경험이 부족하다. 우리 게임은 자이로 기반의 직관적인 조작감과 플레이어 간 협업 설계를 통해 보다 몰입감 있는 플레이를 제공한다.
 +
# Tiltagon: 빠른 템포의 생존형 싱글플레이 게임으로, 키보드나 마우스를 이용한 입력에 의존하며 멀티플레이나 협동 요소는 존재하지 않는다. 이에 반해 우리 게임은 다양한 기믹과 시간 차 협동이 요구되는 퍼즐 요소, 실시간 네트워크 동기화를 통한 협동 경험에 초점을 맞춘 구조를 제공한다.
 +
# Rolling Sky: 터치 드래그 방식의 싱글플레이 게임으로, 자이로 센서를 지원하지 않으며 협동 요소가 없다. 우리 게임은 단순한 반사신경 게임과 달리 두 명이 동시에 조작하지 않으면 클리어할 수 없는 구조로 협동심을 유도하며, 플레이어 간의 조작 축 분리 및 공동 책임 구조를 강조한다.
  
Stage 2 (Tutorial)
+
====마케팅 전략====
[[파일:Example.jpg]]
+
* 대학 커뮤니티(에브리타임·인스타 릴스) 타겟팅 티저 영상 배포
• 기믹: Key-Door
+
* 자체 렌딩 페이지(gyrodrop.xyz)에 배포
 
+
* 게임 스토어(Stove, Steam) 출시
• 장애물 뒤 열쇠 획득 → 문 개방
 
 
 
Stage 3 (Tutorial)
 
[[파일:Example.jpg]]
 
• 기믹: PickUp
 
  
도토리 획득 → 즉시 스테이지 리셋
+
==설계==
 +
===사용자 요구사항===
 +
{| class="wikitable"
 +
! 번호 !! 요구사항 !! D or W !! 중요도
 +
|-
 +
! colspan="4" | '''게임 플레이'''
 +
|-
 +
| 1 || 플레이어가 멀티플레이 룸을 생성 또는 입장할 수 있고, 게임 스테이지를 선택하여 상대방과 게임을 플레이할 수 있다. || D || 대
 +
|-
 +
| 2 || 2명의 플레이어가 자이로 센서를 통해 각각 Pitch/Roll 축을 담당하여 판의 기울기를 조작할 수 있다. || D || 대
 +
|-
 +
| 3 || 게임 내 한 스테이지에서 공이 목표 지점까지 도달하는 최단 거리로 움직이는 시간이 1분 내로 소요되어야 한다. || D || 중
 +
|-
 +
| 4 || 협동 플레이를 유도하도록 맵이 디자인되어야 한다. <br/> 두 축을 동시에 협력하여 기울여야만 통과 가능한 경로 <br/> • 시간차를 맞춰 움직여야 클리어 가능한 점프 구조 등 <br/> 다양하게 설계된 기믹을 바탕으로 다채로운 맵 디자인을 제공 || D || 대
 +
|-
 +
| 5 || 크로스 플랫폼을 지원하고 기기에 자이로 센서가 없는 경우 이를 지원하는 기기로 컨트롤이 가능해야 한다. || D || 중
 +
|-
 +
| 6 || 레벨 디자이너가 게임 내 스테이지를 생성하기 위한 툴이 제공되어야 한다. || W || 소
 +
|-
 +
! colspan="4" | '''기술적 요소'''
 +
|-
 +
| 1 || 자이로 센서의 입력에 대한 반응속도를 100ms 이하로 유지한다. || D || 중
 +
|-
 +
| 2 || 게임 서버–클라이언트 간 실시간 동기화 시간을 30ms 이하로 유지한다. || D || 대
 +
|-
 +
| 3 || 렌더링 속도를 60FPS 기준으로 유지하여 매끄러운 플레이를 제공한다. || D || 중
 +
|-
 +
| 4 || CI/CD를 제공하여 빠른 개발과 배포가 가능하도록 한다. || W || 중
 +
|-
 +
| 5 || 게임 서버의 수평적 확장이 가능하도록 오케스트레이션이 가능해야 한다. || W || 소
 +
|}
  
Stage 4 (Easy)
+
===사용자 요구사항 만족을 위한 기능 정의 및 기능별 정량목표===
[[파일:Example.jpg]]
+
====기능 정의====
기믹: Maze, Key-Door
+
{| class="wikitable"
 +
! 분류 !! 기능 명칭 !! 설명
 +
|-
 +
| GR1 || 게임 룸 생성 || 플레이어가 멀티플레이 룸을 생성할 수 있다.
 +
|-
 +
| GR2 || 게임 룸 입장 || 플레이어가 상대방의 접속 정보를 이용하여 멀티플레이 룸에 입장할 수 있다.
 +
|-
 +
| GR3 || 스테이지 플레이 || 멀티플레이 룸에서 스테이지를 선택하여 게임을 플레이할 수 있다.
 +
|-
 +
| GY1 || 자이로 데이터 취득 || 게임 클라이언트가 구동되는 기기로부터 자이로 센서 데이터를 취득할 수 있다.
 +
|-
 +
| GY2 || 자이로 데이터 대체 취득 || 게임 클라이언트가 구동되는 기기에서 자이로 센서를 가져올 수 없는 경우(예: PC) 이를 지원하는 모바일 기기를 이용하여 컨트롤러 부분만 대체할 수 있다.
 +
|-
 +
| GY3 || 자이로 반응 속도 || 자이로 컨트롤러의 반응이 게임 상에 100ms 이내로 적용된다.
 +
|-
 +
| GY4 || 자이로 데이터 취합 || 두 플레이어의 자이로 데이터를 취합하여 게임 서버에 반영할 수 있다.
 +
|-
 +
| GS1 || 기믹 상호작용 || 점프대, 발판, 열쇠, 부서지는 바닥 등의 기믹 구현 및 상태 변화 처리를 수행한다.
 +
|-
 +
| GS2 || 스테이지 레벨 디자인 || 협동 플레이를 유도하는 맵을 제작한다. 하나의 축만을 이용하여 게임을 플레이할 수 없어야 하며, 두 개의 축을 이용해서 서로 협동하여 스테이지를 클리어 하도록 설계되어야 한다.
 +
|-
 +
| GS3 || 네트워크 동기화 || 게임 서버–클라이언트 간 실시간 동기화 시간이 30ms 이하로 유지되도록 한다.
 +
|-
 +
| GS4 || 렌더링 || 최신 스마트폰을 기준으로 60FPS 렌더링 성능을 보장한다.
 +
|-
 +
| GD1 || 레벨 에디터 도구 || 스테이지 제작 도구를 제공하여 쉽고 빠른 맵 제작이 가능하도록 한다.
 +
|-
 +
| GD2 || 배포 및 서버 관리 || 오케스트레이션 도구(kubernetes, docker 등)를 이용하여 CI/CD 및 수평 확장을 고려한 설계를 한다.
 +
|}
  
• 제한 시야 미로, 열쇠 획득 → 탈출
+
====기능별 정량목표====
 +
{| class="wikitable"
 +
! 분류 !! 기능 명칭 !! 목표 기준치 !! 평가 방식 !! 중요도 계수
 +
|-
 +
| 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))<br />*RTT는 교내 무선랜 환경에서 측정 || 0.10
 +
|-
 +
| GS4 || 렌더링 || ≥ 60FPS || min(1, FPS / 60)<br />*FPS는 평균값 사용 || 0.10
 +
|-
 +
| GD1 || 레벨 에디터 도구 || 구현됨 || 개발 여부 || 0.02
 +
|-
 +
| GD2 || 배포 및 서버 관리 || 구현됨 || 개발 여부 || 0.06
 +
|}
  
Stage 5 (Easy)
+
완료 작품의 평가에서 위의 표의 평가 방식으로 점수를 매기고, ((기능 점수 * 기능 중요도 계수)의 합 * 100)을 계산하여 100점 만점을 기준으로 평가한다.
[[파일:Example.jpg]]
 
• 기믹: Key-Door, Plate-Door, MovingPlatform
 
  
• Plate-Door는 제한 시간 개방, 이동 발판으로 타이밍 요구
+
===기능 구현을 위한 세부기술 선택사항===
 +
# '''게임 룸 생성(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)을 배치하여 여러 인스턴스를 스케일링 가능하게 구성하였다.
  
Stage 6 (Easy)
+
===게임 클라이언트 설계===
 +
====매니저 클래스 설계====
 
[[파일:Example.jpg]]
 
[[파일:Example.jpg]]
• 기믹: PickUp
 
  
• Roll 축 이동 + Pitch 축으로 도토리 전부 획득해야 클리어
+
게임 내 스크립트에서 우리 게임의 핵심 서비스 로직에 쉽게 접근할 수 있도록 싱글톤 패턴을 사용하여 전역 접근을 용이하도록 하였다. 또한 매니저 위의 매니저 클래스인 Managers 클래스를 두어 하위 매니저 클래스들의 의존성 주입을 담당하도록 하였고, 각 하위 매니저 클래스들은 책임과 역할을 명확히하여 기능 확장 및 디버깅이 용이하도록 하였다. 아래는 각 클래스들의 역할에 대한 설명이다.
  
Stage 7 (Hard)
+
# Managers 클래스
[[파일:Example.jpg]]
+
#* Singleton 패턴으로 구현된 최상위 매니저 클래스이다.
• 기믹: BouncingObstacle, Crusher, JumpPad
+
#* 각 서브 매니저(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)
  
• 장애물 피해서 JumpPad → 맞은편 Crusher 주기적 돌진
+
====플레이어 이동 설계====
 +
기존의 Rigidbody 기반으로 중력으로만 움직이는 설계는 얇거나 기울어진 표면에서 다음과 같은 문제를 유발했다.
 +
* 갑작스럽게 기울어진 바닥에 대하여 공이 바닥 콜라이더를 관통하여 낙하하거나
 +
* 경사진 표면에서 예기치 않게 튕겨 불안정하게 움직이는 현상
 +
이를 해결하기 위해, 기존 물리 기반 이동 방식 대신 표면 정착 및 사영 기반 이동 방식으로 새롭게 움직임을 설계하였다. 구현된 클래스는 플랫폼 회전과 공의 움직임을 자연스럽게 연동하여, 직관적이고 안정적인 조작감을 제공한다.
  
Stage 8 (Hard)
+
# 플랫폼(평면) 감지
[[파일:Example.jpg]]
+
#* Unity의 Raycast 기능을 이용하여 플레이어의 위치에서 중력 방향으로 보이지 않는 광선을 쏘아 충돌된 객체를 바닥으로 인식한다.
• 기믹: TeleportPad, Hammer
+
#* 짧은 순간의 오인식이나 접지 흔들림(jitter)을 방지하기 위해 내부적으로 이전 상태를 기억하고, 접지 손실 여부를 일정 거리 이상 벗어난 경우에만 판단하도록 처리하였다.
 +
# 중력 분해 및 표면 사영 적용
 +
#* 인식된 평면의 법선 벡터를 기준으로 중력 벡터를 분해하여, 법선 방향 성분을 제거하고 평면에 평행한 방향의 힘만 공에 가한다.
 +
#* 플랫폼이 회전하면 법선 방향도 함께 변하므로, 플레이어는 해당 표면을 따라 자연스럽게 미끄러지는 형태로 이동하게 된다.
 +
#* 이를 통해 표면 기울기에 따라 실제 물리적으로 이동하는 느낌을 재현하였다.
 +
# 정확한 위치 조정(접지 보정)
 +
#* 공의 중심 좌표를 바닥의 표면에 정사영(수직 사영)하여, 물리 충돌에 의한 튕김이나 겹침을 방지한다.
 +
#* 공은 표면에 붙어 있는 듯한 상태로 유지되며, 얇은 구조물이나 미세한 기울기에서도 안정적으로 동작한다.
 +
#* 사영 위치는 바닥 기준점에서의 상대 거리와 법선 벡터를 이용하여 계산된다.
 +
# 플레이 경험 향상
 +
#* 공의 현재 속도가 최대 속도를 초과할 경우, 반대 방향의 감속력을 추가로 가하여 과도한 가속을 억제한다.
 +
#* 게임 공간의 유효 범위를 벗어나면 자동으로 리셋되어 초기 위치로 돌아오며, 상태도 함께 초기화된다.
 +
#* 이는 사용자의 실수로 인한 낙사 또는 무한 낙하로부터 빠르게 복구할 수 있도록 하기 위함이다.
  
• 올바른 Pad만 다음 플랫폼, 잘못 선택 시 되돌아감; 360° Hammer 회전
+
====기믹 요소 설계====
 
 
Stage 9 (Hard)
 
 
[[파일:Example.jpg]]
 
[[파일:Example.jpg]]
• 기믹: JumpPad, BrokenBoard, MovingPlatform, Hammer
 
 
• 2단계 구조; 첫 JumpPad 자동 점프 → 두 번째 단계 Grid 바닥(4.5 초 후 붕괴) + 이동 발판 3개; 압박·정밀 컨트롤 요구
 
 
===개념설계안===
 
모바일 자이로센서 입력으로 3D 플랫폼을 기울여 공을 움직이는 퍼즐·플랫폼 게임.
 
1인 모드(전 축)와 2인 모드(Pitch/Roll 분담)를 제공해 협동성을 강조한다.
 
호스트 중심 물리 연산 구조에 WebRTC P2P 네트워킹을 결합해 원격지 사용자 간 실시간 멀티플레이를 구현하고, Windows·macOS·모바일 웹 컨트롤러를 모두 지원한다.
 
  
===이론적 계산 및 시뮬레이션===
+
기믹 요소는 게임 내에서 플레이어의 진행을 도와주거나 방해하는 동적인 오브젝트들로 구성되어 있다. 모든 기믹 클래스는 MonoBehaviour(또는 SyncBehaviour)를 상속받으며, 일부는 IClearableGimmic 인터페이스를 구현하여 스테이지 리셋 시 상태 복원이 가능하도록 설계되어 있다. 다음은 각 기믹 클래스들의 역할과 기능이다.
• 자이로-클라이언트 간 지연 계산: 교차상관 함수를 사용해 두 축 데이터의 최적 랙을 구하고 지연(밀리초) = 최적 랙 × 10으로 산출.
 
• 네트워크 동기화 실험: 동일 NTP 서버로 1 ms 이내 시간 동기를 맞춘 두 피어 간 Unix Timestamp 차이를 10 초간 측정해 평균 지연을 검증.
 
• 물리 시뮬레이션: 플랫폼 회전 시 공이 뜨는 현상을 방지하기 위해 캐릭터 위치를 플랫폼에 수직 투영 후 속도를 제어해 접지 상태를 유지하도록 계산.
 
  
===상세설계 내용===
+
# BrokenBoard 클래스
• 매니저 계층: 싱글톤 Managers 클래스가 GameManager·RoomManager·SessionManager·UIManager·SoundManager 등을 보유, 서비스 로직에 전역 접근을 제공하며 Dispatch(Action)로 메인 스레드 안전 실행을 보장한다.
+
#* 플레이어가 바닥에 닿으면 일정 시간 후 바닥이 사라지는 붕괴형 발판 기믹이다.
• 게임 오브젝트 클래스
+
#* 붉은색으로 색상을 바꾼 후 ColliderPlatform을 비활성화하고 자기 자신도 비활성화된다.
• RollingPlatform·MovingSaw 등 장애물은 주기적 이동 패턴과 충돌 처리 로직 내장.
+
# CubeZMover 클래스
• PickUp(Score·Death), RepeatingCrusher, TeleportPad, TriggerPlate 등 10여 종 기믹 클래스 구현.
+
#* 일정 속도로 X축 또는 Z축을 따라 왕복 운동하는 움직이는 발판이다.
• UI 설계: ReactiveProperty / IReadOnlyReactiveProperty 기반 옵저버 패턴으로 모델-뷰 결합을 최소화하고 Managers.Dispatch()로 UI 이벤트를 메인 스레드에 안전 반영.
+
#* Mathf.PingPong을 활용하여 자연스러운 반복 이동을 구현하며, 호스트 측에서 위치 동기화를 수행한다.
• 개발 프로세스: GitHub flow, dev-main 브랜치 전략, PR 승인 후 병합·Rebase 규칙, 주요 릴리스 시 dev → main 병합 배포.
+
# 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 이벤트를 안전하게 실행하도록 하였다.
 +
# 적용 방식 및 흐름
 +
#* [[파일:Example.jpg]]
 +
#* 모델(Model)에서의 상태 정의
 +
#** 모델 클래스(예: GameManager, SessionManager)에서는 관리하고자 하는 상태 프로퍼티들을 ReactiveProperty<T>로 래핑하여 정의하였다.
 +
#** 외부에는 IReadOnlyReactiveProperty<T> 형태로 노출하여, 구독만 가능하도록 구성하였다.
 +
#* 뷰(View)에서의 상태 구독
 +
#** UI 요소에서는 상태의 변경을 구독(Subscribe)하고, 변경 시 등록한 콜백 함수가 호출되어 화면을 새로 렌더링한다.
 +
#** 이 방식으로 모델 내부에 UI 로직이 들어가지 않도록 분리함으로써 관심사의 분리가 가능해졌다.
 +
#* 컨트롤러(Controller)에서의 상태 조작
 +
#** 사용자의 입력이나 이벤트에 따라 컨트롤러가 모델의 상태를 변경하며, 이 변경은 자동으로 UI 반영으로 이어진다.
 +
# 설계 효과
 +
#* 모델과 뷰 간의 의존성을 제거하여 유지보수가 쉬워졌다.
 +
#* 상태 변경이 있을 때만 UI가 렌더링되어, 렌더링 효율이 향상되었다.
 +
#* UI 반영 누락과 같은 오류 가능성을 줄여 내부 상태와 UI 간의 일관성 유지가 가능해졌다.
 +
#* 값의 변경과 UI의 갱신이 명확하게 연결되어 있어 디버깅 시 흐름 추적이 쉬워졌다.
  
===완료작품의 평가===
+
====P2P 통신 및 RPC 설계====
내용
+
P2P 통신을 위해 WebRTC를 어떻게 구현하였고, 확립된 통신 채널을 이용해 두 Peer 간 동기화를 RPC로 어떻게 구현하였는지 아래에 설명한다.
  
===향후계획===
+
# WebRTC 시그널링
내용
+
#* [[파일:Example.jpg]]
 +
#* WebRTC는 NAT(라우터)를 넘어 Peer 간 직접 연결(P2P)을 설정하기 위해 초기 협상 과정인 시그널링(Signaling) 단계를 거친다. 이 과정에서 양쪽 Peer는 Session Description(Offer/Answer)과 ICE Candidate(네트워크 후보군)을 교환하며, 연결을 설정하기 위한 정보를 주고 받는다.
 +
#* 서로의 연결 정보를 모르는 상태에서 시그널링을 할 순 없으므로, WebSocket 기반 임시 통신 채널을 열어 WebRTC 시그널링 정보를 터널링하는 서버를 구현했다. 이 서버는 추후 설명할 게임 룸 서버와 통합되어 있어, 게임 룸에 입장한 두 플레이어 간의 정보를 알 수 있으며, 시그널링에 필요한 정보 또한 터널링하여 전송할 수 있다.
 +
#* 시그널링 과정은 다음 단계로 구성된다.
 +
#** 호스트가 시그널링 서버(룸 서버)에 등록한다.
 +
#** 게스트는 호스트의 룸 코드를 입력하여 시그널링 서버(룸 서버)에 참가한다.
 +
#** STUN 서버를 통해 호스트 자신의 연결 정보를 수집한다(IP, UDP Port 등).
 +
#** 수집된 호스트의 연결 정보를 시그널링 터널링 서버를 통해 게스트로 전송한다.
 +
#** 게스트도 마찬가지로 STUN 서버를 통해 게스트 자신의 연결 정보를 수집한다.
 +
#** 수집된 게스트의 연결 정보를 시그널링 터널링 서버를 통해 호스트로 전송한다.
 +
#** 게스트는 연결 정보를 기반으로 데이터 채널을 생성하여 연결 제안(Offer)를 호스트에게 전송한다.
 +
#** 호스트는 게스트의 연결 제안(Offer)를 받고 게스트에 답장(Answer)함으로써 통신 채널이 수립된다(이 단계에서는 더 이상 시그널링 터널링 채널이 필요하지 않는다).
 +
# RPC를 통한 게임 상태 동기화
 +
#* [[파일:Example.jpg]]
 +
#* WebRTC로 수립된 데이터 채널을 이용하여 두 Peer 간 정보 교환이 실시간으로 이루어질 수 있게 됐다. 두 Peer는 서로 같은 코드를 공유하고 있다는 가정 하에 RPC(Remote Procedure Call)을 구현하여, 호스트가 필요 시 게스트에게 특정 액션을 취하도록 할 수 있도록 설계했다.
 +
#* 호스트에서 모든 물리 연산을 수행하고 난 위치(Position) 및 회전(Rotation) 결과를 게스트에게 실시간으로 전송하여 호스트와 게스트 간 게임 오브젝트의 동기화를 이루고, 게임의 상태(점수 및 클리어 여부) 변경 또한 호스트에서 이루어질 시 동일하게 게스트에도 적용되도록 설계했다.
 +
#* 구체적인 동기화 과정은 아래와 같다.
 +
#** SyncObjectId가 붙은 게임 오브젝트에 SyncBehaviour를 상속받은 컴포넌트가 SyncRPC 애트리뷰트가 붙은 사용자 정의 RPC 메서드를 호출한다.
 +
#** SyncManager는 SyncBehaviour 컴포넌트가 호출한 RPC 메서드를 내부(호스트)에서도 호출하고 이를 직렬화하여 WebRTC로 수립한 데이터 채널을 통해 상대편(게스트)으로 전송한다.
 +
#** 이때, NAT Traversal이 되는 상황에서는 UDP 전송을 수행하고, 그렇지 않은 특수한 상황에서는 어쩔 수 없이 외부 TURN 서버로 릴레이하여 fallback 처리한다.
 +
#** 상대편(게스트)는 RPC 메시지를 수신하여 역직렬화하여 어떤 게임 오브젝트의 어떤 컴포넌트의 어떤 메서드를 호출해야 하는지 알아내어 이를 호출한다.
 +
# 동기화 클래스 설계
 +
#* [[파일:Example.jpg]]
 +
#* 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 시그널링도 제공한다.
 +
# 아키텍처 설계
 +
#* 주요 모델
 +
#** [[파일:Example.jpg]]
 +
## Repository Layer
 +
##* [[파일:Example.jpg]]
 +
##* GameRoomInMemoryRepository: Map<string, GameRoom>을 사용해 룸 정보를 메모리에 저장합니다. create, getById, update, delete 등 기본 CRUD 메서드를 구현한다.
 +
##* ShortCodeBase62InMemoryRepository: 일정 길이의 Base62 문자열을 생성해 룸 ID와 매핑하며 TTL이 지나면 자동으로 정리합니다.
 +
##* ClientVersionJsonRepository: JSON 파일을 읽어 최신·최소 클라이언트 버전을 관리한다.
 +
## Service Layer
 +
##* [[파일:Example.jpg]]
 +
##* GameRoomService: 게임 룸 생성/입장/퇴장, 자이로 점유 관리, 단축 코드 발급 등을 담당합니다. 내부적으로 Repository 인터페이스에 의존한다.
 +
##* WebRTCSignalingService: 피어 간 시그널링 연결을 관리하고 TURN 계정 정보를 동적으로 생성합니다. 연결된 피어의 메시지 전달을 중계한다.
 +
##* ClientVersionService: 클라이언트 버전을 검사하여 호환 여부와 최신 버전을 알려준다.
 +
## Controller Layer
 +
##* [[파일:Example.jpg]]
 +
##* GameRoomController: /rooms 경로에서 룸 생성, 조회, 입장/퇴장, 자이로 관련 REST API를 제공한다.
 +
##* GameRoomGateway: update-gyro 웹소켓 이벤트를 받아 GameRoomService의 자이로 값 갱신 메서드를 호출한다.
 +
##* WebRTCSignalingGateway: /webrtc-signaling 경로에서 register/offer/answer/ice-candidate 등을 처리하여 상대 피어로 전달한다.
 +
##* ClientVersionController: /client-version/check 엔드포인트로 클라이언트 버전을 검사한다.
 +
##* HealthController: /health 경로에서 단순한 상태 체크 API를 제공합니다.
 +
# API 설계
 +
{| class="wikitable"
 +
! 경로 !! 메소드 !! 설명 !! 파라미터
 +
|-
 +
| /rooms || POST || 게임 룸 생성 || Header: game-client-id
 +
|-
 +
| /rooms/{roomId} || GET || 게임 룸 조회 || Path: roomId<br />Header: game-client-id
 +
|-
 +
| /rooms/{roomId}/join || POST || 게임 룸 입장 || Path: roomId<br />Header: game-client-id
 +
|-
 +
| /rooms/{roomId}/leave || POST || 게임 룸 퇴장 || Path: roomId<br />Header: game-client-id
 +
|-
 +
| /rooms/{roomId}/gyro || GET || 자이로 상태 조회 || Path: roomId
 +
|-
 +
| /rooms/{roomId}/gyro || POST || 자이로 상태 갱신 || Path: roomId<br />Header: game-controller-id<br />Body: GyroDTO
 +
|-
 +
| /rooms/{roomId}/gyro || POST || 자이로 제어권 요청 || Path: roomId, axis
 +
|-
 +
| /join/{axis} || - || - || Header: game-controller-id
 +
|-
 +
| /rooms/{roomId}/gyro/release/{axis} || POST || 자이로 제어권 반환 || Path: roomId, axis<br />Header: game-client-id
 +
|-
 +
| /rooms/{roomId}/code || GET || 단축 코드 조회 || Path: roomId<br />Header: game-client-id
 +
|-
 +
| /rooms/code/{shortCode}/join || POST || 단축 코드로 입장 || Path: shortCode<br />Header: game-client-id
 +
|}

2025년 6월 18일 (수) 23:59 판

프로젝트 개요

기술개발 과제

  • 국문: 협동심 증진 및 공감각 발달을 위한 게임 ‘자이로드롭’ 개발
  • 영문: 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)

  1. 자이로 센서
    • 자이로 센서는 각속도를 측정하여 회전 방향과 속도를 정확히 감지하는 역할을 한다. 최근의 자이로 센서 기술은 MEMS(미세전자기계 시스템) 기반으로 소형화 및 고정밀화가 이루어졌으며, 현실 세계와 가까운 가상 환경 경험을 제공할 수 있기에 스마트폰, VR 기기, 게임 컨트롤러 등 다양한 분야에서 필수적인 기술로 자리 잡았다.
    • 최근 자이로 센서는 가속도 센서와 결합하여 6축 센서를 구성하며, 여기에 자기장 센서를 추가해 9축 센서로 발전하였다. 이를 통해 더욱 정확한 공간 인식과 자세 추적이 가능해졌다.
    • 최신 자이로 센서는 초당 300~2000 DPS(degrees per second)의 정밀한 각속도 측정 범위를 제공하며, 모바일 게임 환경에서 미세한 움직임까지 정확히 감지할 수 있게 되었다.
  2. 게임 엔진
    • 게임 개발 및 실시간 시뮬레이션 구현을 위한 대표적인 기술로는 Unity Engine과 Unreal Engine이 있다.
    1. 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의 장점 중 하나로 꼽힌다.
    2. Unreal Engine
      • Unreal Engine은 Epic Games에서 개발한 고성능 실시간 렌더링 엔진으로, AAA급 게임 및 고품질 비주얼 콘텐츠 제작에 특화되어 있다.
      • 특히 최신 버전인 Unreal Engine 5는 Nanite(가상화 지오메트리), Lumen(실시간 글로벌 일루미네이션)과 같은 첨단 렌더링 기술을 도입하여, 실사 수준의 그래픽 구현이 가능하다.
      • 고급 물리 효과를 위한 Chaos Physics, Cloth Simulation, Rigid/Soft Body Dynamics 등 다양한 내장 기능을 제공하며, C++ 기반의 강력한 성능 제어와 함께 Blueprint라 불리는 시각적 스크립팅 시스템도 함께 지원되어 비전공자도 게임 로직을 시각적으로 구성할 수 있다.
      • Unreal Engine은 높은 성능과 정교한 표현력을 제공하는 대신, 비교적 높은 시스템 요구사항과 학습 난이도를 수반한다. 그럼에도 불구하고 영화, 건축 시각화, 디지털 트윈 등 게임 이외의 산업 분야에서도 널리 사용되고 있다.

관련 시장에 대한 분석

경쟁제품 조사 비교

  1. Super Monkey Ball: 해당 게임은 키패드나 조이스틱 기반 조작으로 플랫폼 위의 캐릭터를 조종하는 싱글플레이 중심의 게임이다. 멀티플레이 요소는 제한적이며, 자이로 센서를 활용한 조작 방식은 지원하지 않아 실제 기기 움직임과의 연동 경험이 부족하다. 우리 게임은 자이로 기반의 직관적인 조작감과 플레이어 간 협업 설계를 통해 보다 몰입감 있는 플레이를 제공한다.
  2. Tiltagon: 빠른 템포의 생존형 싱글플레이 게임으로, 키보드나 마우스를 이용한 입력에 의존하며 멀티플레이나 협동 요소는 존재하지 않는다. 이에 반해 우리 게임은 다양한 기믹과 시간 차 협동이 요구되는 퍼즐 요소, 실시간 네트워크 동기화를 통한 협동 경험에 초점을 맞춘 구조를 제공한다.
  3. 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점 만점을 기준으로 평가한다.

기능 구현을 위한 세부기술 선택사항

  1. 게임 룸 생성(GR1), 게임 룸 입장(GR2), 자이로 데이터 취합(GY4) 기능 개발을 위해 Node.js 기반의 NestJS 웹 서버 프레임워크를 선정하였다.
    • Node.js의 풍부한 패키지 생태계와 빠른 프로토타이핑 및 개발 속도를 고려하여 선택하였다.
    • 플레이어가 상대방의 연결 정보를 직접적으로 알 수 없으므로 중립적이고 안정적인 연결을 보장하기 위해 서버-클라이언트 아키텍처를 도입하고, 이를 통해 게임 룸 및 접속 코드를 생성하고 관리하도록 하였다.
  2. 스테이지 플레이(GR3) 기능 구현을 위해 게임 엔진으로 Unity를 채택하였다.
    • Unity는 직관적인 시각적 개발 툴과 방대한 플러그인 생태계를 제공하여 초기 개발 속도를 크게 향상시킬 수 있으며, 캐주얼 게임 및 실시간 인터랙티브 콘텐츠 제작에 적합하다.
    • Unity는 또한 UI 시스템, 물리 기반 시뮬레이션, 경로 탐색, 상태 머신 등 주요 게임 개발 기능을 위한 풍부한 라이브러리와 예제를 제공하여 개발의 재사용성과 유지보수성 측면에서 큰 이점을 제공한다.
  3. 자이로 데이터 취득(GY1), 자이로 대체 컨트롤(GY2) 구현을 위해 모바일 기기 디바이스의 자이로 정보를 취득하기로 했으며, 별도의 애플리케이션 설치가 필요하지 않도록 웹 기반 애플리케이션을 제공하기로 했다.
    • 자이로 센서 데이터를 획득하기 위해 deviceorientation 웹 API를 이용한다.
    • React 라이브러리를 사용하여 개발 효율성을 높였고, React의 방대하고 다양한 라이브러리 생태계를 활용하여 인터랙티브한 UI/UX 설계를 실현할 수 있다.
  4. 자이로 반응 속도(GY3) 요구사항 충족을 위해 실시간 양방향 통신이 가능한 WebSocket을 도입하였다.
    • HTTP 통신 대비 헤더 등의 오버헤드를 줄이고 실시간 이벤트 전송 방식을 채택하여 통신 지연을 최소화하였다.
  5. 기믹 상호작용(GS1), 협동형 레벨 디자인(GS2)은 Unity의 MonoBehaviour를 상속받는 방식으로 구현하였으며, Unity 에셋 스토어에서 유/무료 모델을 활용하여 디자이너가 없는 팀 상황에서도 높은 품질의 게임 디자인을 가능하게 하였다.
  6. 네트워크 동기화(GS3)를 위해 처음에는 Mirror, FishNet과 같은 서버-클라이언트 구조의 동기화 프레임워크를 고려하였으나, 매 게임마다 Unity Headless 서버 인스턴스를 매번 띄우는 오버헤드와 P2P 위한 Transport 계층의 미구현 및 빈약한 문서화로 인해 최종적으로 WebRTC 기반의 P2P 기술을 채택하였다.
    • WebRTC는 서버 연결 없이 Peer 간 직접적인 통신이 가능하고, NAT 및 방화벽을 우회할 수 있으며, 실시간으로 데이터를 전송할 수 있다는 점이 우리의 요구사항에 딱 맞아 떨어진다.
    • 클라이언트는 Unity.WebRTC 패키지로 구현하고, 시그널링 서버는 Node.js 및 Socket.io를 사용하였다.
    • RPC 기술은 C#의 리플렉션 기술을 이용하여 동일하게 배포된 애플리케이션 내에서 원격지의 메서드를 호출하는 방식으로 구현하였다.
  7. 렌더링(GS4) 성능 최적화를 위해 Unity의 생명 주기(Update, FixedUpdate)를 명확히 구분하여 사용하였으며, Raycast, 복잡한 물리 연산, 충돌 판정 등 고비용 연산을 FixedUpdate에서만 실행하여 성능을 관리하였다.
  8. 레벨 에디터 도구(GD1)는 시간과 인력의 제한으로 별도의 도구 개발 없이 Unity 프레임워크 내에서 레벨 디자인을 진행하였다.
  9. 배포 및 서버 관리(GD2)는 AWS를 활용하여 서비스 안정성을 확보하고, CloudFront를 통해 모바일 웹 컨트롤러의 빠른 접근성을 보장하였다. EC2 인스턴스 앞에 Elastic Load Balancing(ELB)을 배치하여 여러 인스턴스를 스케일링 가능하게 구성하였다.

게임 클라이언트 설계

매니저 클래스 설계

Example.jpg

게임 내 스크립트에서 우리 게임의 핵심 서비스 로직에 쉽게 접근할 수 있도록 싱글톤 패턴을 사용하여 전역 접근을 용이하도록 하였다. 또한 매니저 위의 매니저 클래스인 Managers 클래스를 두어 하위 매니저 클래스들의 의존성 주입을 담당하도록 하였고, 각 하위 매니저 클래스들은 책임과 역할을 명확히하여 기능 확장 및 디버깅이 용이하도록 하였다. 아래는 각 클래스들의 역할에 대한 설명이다.

  1. Managers 클래스
    • Singleton 패턴으로 구현된 최상위 매니저 클래스이다.
    • 각 서브 매니저(GameManager, RoomManager, SessionManager, UIManager, SoundManager 등)를 소유하며, 전역 접근을 제공한다.
    • Dispatch(Action) 메서드를 제공하여 Unity 메인 스레드에서 실행되어야 할 작업을 안전하게 큐잉 및 실행
  2. GameManager 클래스
    • 게임 진행 상태 전반을 관리한다.
    • 주요 기능
      • 스테이지 클리어 로직 수행(FinishAction)
      • 스테이지 로딩(LoadStageScene, LoadMainScene)
      • 스테이지 잠금/해금 관리(GetLastUnlockedStage, UnlockLastStage)
      • 초기화 및 리셋(Init, Clear)
  3. RoomManager 클래스
    • REST API를 통한 룸 생성, 참가, 자이로 제어 기능을 담당한다.
    • 클라이언트가 속한 룸 정보(Current), 현재 자이로 상태(CurrentGyro), 접속 코드(AccessCode) 등을 관리한다.
    • 주요 기능
      • 룸 생성 및 참가 (OpenAsync, JoinAsync, LoadAsync)
      • 자이로 축 점유/해제 (TaskAxisAsync, ReleaseAxisAsync)
      • 웹 컨트롤러 URL 제공 (GetWebControllerUrl)
      • 전체 초기화 (ResetAsync)
  4. SessionManager 클래스
    • 상대방과 원격 플레이를 위한 세션 연결 관리를 담당한다.
    • 연결 흐름의 상태(SessionStatus)를 추적하며, 호스트/게스트 역할에 따라 연결 절차를 처리한다.
    • 구체적인 연결 방식은 외부에 노출하지 않기 위해 해당 클래스를 정의하였으며,, 해당 클래스 안에서 WebRTC를 쓸 지 다른 P2P 통신 기법을 사용할지 결정한다.
    • 주요 기능
      • 호스트로서 게스트를 기다림 (StartWaitForGuest)
      • 게스트로서 호스트에 접속 (StartJoinHostRoom)
      • 세션 리셋 (ResetAsync)
      • 연결 종료 처리 (Dispose)
  5. SoundManager 클래스
    • 게임 내 효과음 및 배경음악 재생을 담당한다.
    • 주요 기능
      • BGM/SFX 재생 (Play)
      • 초기화 및 정리 (Init, Clear)
  6. UIManager 클래스
    • UI 패널 관리를 담당한다(씬 UI, 팝업 UI)
    • 주요 기능
      • UI 생성 및 표시 (ShowSceneUI<T>, ShowPopupUI<T>)
      • 팝업 닫기 (ClosePopupUI, CloseAllPopupUI)

플레이어 이동 설계

기존의 Rigidbody 기반으로 중력으로만 움직이는 설계는 얇거나 기울어진 표면에서 다음과 같은 문제를 유발했다.

  • 갑작스럽게 기울어진 바닥에 대하여 공이 바닥 콜라이더를 관통하여 낙하하거나
  • 경사진 표면에서 예기치 않게 튕겨 불안정하게 움직이는 현상

이를 해결하기 위해, 기존 물리 기반 이동 방식 대신 표면 정착 및 사영 기반 이동 방식으로 새롭게 움직임을 설계하였다. 구현된 클래스는 플랫폼 회전과 공의 움직임을 자연스럽게 연동하여, 직관적이고 안정적인 조작감을 제공한다.

  1. 플랫폼(평면) 감지
    • Unity의 Raycast 기능을 이용하여 플레이어의 위치에서 중력 방향으로 보이지 않는 광선을 쏘아 충돌된 객체를 바닥으로 인식한다.
    • 짧은 순간의 오인식이나 접지 흔들림(jitter)을 방지하기 위해 내부적으로 이전 상태를 기억하고, 접지 손실 여부를 일정 거리 이상 벗어난 경우에만 판단하도록 처리하였다.
  2. 중력 분해 및 표면 사영 적용
    • 인식된 평면의 법선 벡터를 기준으로 중력 벡터를 분해하여, 법선 방향 성분을 제거하고 평면에 평행한 방향의 힘만 공에 가한다.
    • 플랫폼이 회전하면 법선 방향도 함께 변하므로, 플레이어는 해당 표면을 따라 자연스럽게 미끄러지는 형태로 이동하게 된다.
    • 이를 통해 표면 기울기에 따라 실제 물리적으로 이동하는 느낌을 재현하였다.
  3. 정확한 위치 조정(접지 보정)
    • 공의 중심 좌표를 바닥의 표면에 정사영(수직 사영)하여, 물리 충돌에 의한 튕김이나 겹침을 방지한다.
    • 공은 표면에 붙어 있는 듯한 상태로 유지되며, 얇은 구조물이나 미세한 기울기에서도 안정적으로 동작한다.
    • 사영 위치는 바닥 기준점에서의 상대 거리와 법선 벡터를 이용하여 계산된다.
  4. 플레이 경험 향상
    • 공의 현재 속도가 최대 속도를 초과할 경우, 반대 방향의 감속력을 추가로 가하여 과도한 가속을 억제한다.
    • 게임 공간의 유효 범위를 벗어나면 자동으로 리셋되어 초기 위치로 돌아오며, 상태도 함께 초기화된다.
    • 이는 사용자의 실수로 인한 낙사 또는 무한 낙하로부터 빠르게 복구할 수 있도록 하기 위함이다.

기믹 요소 설계

Example.jpg

기믹 요소는 게임 내에서 플레이어의 진행을 도와주거나 방해하는 동적인 오브젝트들로 구성되어 있다. 모든 기믹 클래스는 MonoBehaviour(또는 SyncBehaviour)를 상속받으며, 일부는 IClearableGimmic 인터페이스를 구현하여 스테이지 리셋 시 상태 복원이 가능하도록 설계되어 있다. 다음은 각 기믹 클래스들의 역할과 기능이다.

  1. BrokenBoard 클래스
    • 플레이어가 바닥에 닿으면 일정 시간 후 바닥이 사라지는 붕괴형 발판 기믹이다.
    • 붉은색으로 색상을 바꾼 후 ColliderPlatform을 비활성화하고 자기 자신도 비활성화된다.
  2. CubeZMover 클래스
    • 일정 속도로 X축 또는 Z축을 따라 왕복 운동하는 움직이는 발판이다.
    • Mathf.PingPong을 활용하여 자연스러운 반복 이동을 구현하며, 호스트 측에서 위치 동기화를 수행한다.
  3. HammerSwing 클래스
    • Z축을 중심으로 좌우로 회전하며, 회전 방향이나 각도는 설정값을 통해 조정할 수 있다.
    • FixedUpdate()에서 회전 동작을 수행하며, 호스트에서만 회전 값을 네트워크로 동기화한다.
  4. JumpPad 클래스
    • 플레이어가 트리거에 진입하면 사전에 설정된 방향으로 힘을 가해 점프시키는 발판이다.
    • Rigidbody.AddForce()를 사용하여 물리적 힘을 적용한다.
  5. KeyTrigger 클래스
    • 플레이어가 트리거에 진입하면 해당 컴포넌트에 연결된 문을 열고, 자신은 비활성화된다.
  6. MovingScrew 클래스
    • 톱니 모양의 장애물로, 주기적으로 X축으로 좌우 움직인다.
  7. PickUp 클래스
    • 플레이어가 획득 시 점수 추가, 데스 처리 등의 효과를 발생시키는 수집형 오브젝트이다.
    • PickupType 열거형을 통해 타입을 구분하며, Score 및 Death 타입이 구현되어 있다.
  8. RepeatingCrusher 클래스
    • 일정 주기로 전방으로 돌진한 후 다시 원위치로 복귀하는 반복형 해머 기믹이다.
    • 돌진 도중 플레이어를 감지하면 플레이어의 BreakDown()을 호출하여 파괴 액션을 취한다.
  9. TeleportPad 클래스
    • 연결된 게임 오브젝트의 위치로 플레이어를 순간이동시키는 패드형 기믹이다.
    • 대상 플레이어의 인터페이스(IBallControl)를 통해 위치를 직접 조작한다.
  10. TriggerPlate 클래스
    • 플레이어가 충돌하면 발판이 내려가고 연결된 문이 열리며, 시간이 지난 후 자동으로 복원된다.

UI 설계

게임 내 상태 변화를 UI에 반영하기 위해 옵저버 패턴을 적극 활용하였으며, 이를 위해 ReactiveProperty<T>와 IReadOnlyReactiveProperty<T>라는 구조를 설계에 도입하였다. 모델 내부의 상태 변경을 View(UI)에 자동으로 반영함으로써, 모델-뷰 간 결합을 줄이고, 유지보수성과 확장성을 향상시켰다.

  1. 설계 개요
    • ReactiveProperty<T>는 값이 변경되었을 때 구독 중인 콜백 함수들에게 자동으로 알림을 전달하는 구조로, 옵저버 패턴을 기반으로 구현되었다.
    • 외부에서는 IReadOnlyReactiveProperty<T>를 통해 읽기 및 구독만 허용하며, 직접 값 변경은 불가능하도록 캡슐화하였다.
    • Unity 환경의 특성상, 이벤트 콜백은 항상 메인 스레드에서 실행되어야 하므로, 내부적으로 Managers.Dispatch()를 사용해 UI 이벤트를 안전하게 실행하도록 하였다.
  2. 적용 방식 및 흐름
    • Example.jpg
    • 모델(Model)에서의 상태 정의
      • 모델 클래스(예: GameManager, SessionManager)에서는 관리하고자 하는 상태 프로퍼티들을 ReactiveProperty<T>로 래핑하여 정의하였다.
      • 외부에는 IReadOnlyReactiveProperty<T> 형태로 노출하여, 구독만 가능하도록 구성하였다.
    • 뷰(View)에서의 상태 구독
      • UI 요소에서는 상태의 변경을 구독(Subscribe)하고, 변경 시 등록한 콜백 함수가 호출되어 화면을 새로 렌더링한다.
      • 이 방식으로 모델 내부에 UI 로직이 들어가지 않도록 분리함으로써 관심사의 분리가 가능해졌다.
    • 컨트롤러(Controller)에서의 상태 조작
      • 사용자의 입력이나 이벤트에 따라 컨트롤러가 모델의 상태를 변경하며, 이 변경은 자동으로 UI 반영으로 이어진다.
  3. 설계 효과
    • 모델과 뷰 간의 의존성을 제거하여 유지보수가 쉬워졌다.
    • 상태 변경이 있을 때만 UI가 렌더링되어, 렌더링 효율이 향상되었다.
    • UI 반영 누락과 같은 오류 가능성을 줄여 내부 상태와 UI 간의 일관성 유지가 가능해졌다.
    • 값의 변경과 UI의 갱신이 명확하게 연결되어 있어 디버깅 시 흐름 추적이 쉬워졌다.

P2P 통신 및 RPC 설계

P2P 통신을 위해 WebRTC를 어떻게 구현하였고, 확립된 통신 채널을 이용해 두 Peer 간 동기화를 RPC로 어떻게 구현하였는지 아래에 설명한다.

  1. WebRTC 시그널링
    • Example.jpg
    • WebRTC는 NAT(라우터)를 넘어 Peer 간 직접 연결(P2P)을 설정하기 위해 초기 협상 과정인 시그널링(Signaling) 단계를 거친다. 이 과정에서 양쪽 Peer는 Session Description(Offer/Answer)과 ICE Candidate(네트워크 후보군)을 교환하며, 연결을 설정하기 위한 정보를 주고 받는다.
    • 서로의 연결 정보를 모르는 상태에서 시그널링을 할 순 없으므로, WebSocket 기반 임시 통신 채널을 열어 WebRTC 시그널링 정보를 터널링하는 서버를 구현했다. 이 서버는 추후 설명할 게임 룸 서버와 통합되어 있어, 게임 룸에 입장한 두 플레이어 간의 정보를 알 수 있으며, 시그널링에 필요한 정보 또한 터널링하여 전송할 수 있다.
    • 시그널링 과정은 다음 단계로 구성된다.
      • 호스트가 시그널링 서버(룸 서버)에 등록한다.
      • 게스트는 호스트의 룸 코드를 입력하여 시그널링 서버(룸 서버)에 참가한다.
      • STUN 서버를 통해 호스트 자신의 연결 정보를 수집한다(IP, UDP Port 등).
      • 수집된 호스트의 연결 정보를 시그널링 터널링 서버를 통해 게스트로 전송한다.
      • 게스트도 마찬가지로 STUN 서버를 통해 게스트 자신의 연결 정보를 수집한다.
      • 수집된 게스트의 연결 정보를 시그널링 터널링 서버를 통해 호스트로 전송한다.
      • 게스트는 연결 정보를 기반으로 데이터 채널을 생성하여 연결 제안(Offer)를 호스트에게 전송한다.
      • 호스트는 게스트의 연결 제안(Offer)를 받고 게스트에 답장(Answer)함으로써 통신 채널이 수립된다(이 단계에서는 더 이상 시그널링 터널링 채널이 필요하지 않는다).
  2. RPC를 통한 게임 상태 동기화
    • Example.jpg
    • WebRTC로 수립된 데이터 채널을 이용하여 두 Peer 간 정보 교환이 실시간으로 이루어질 수 있게 됐다. 두 Peer는 서로 같은 코드를 공유하고 있다는 가정 하에 RPC(Remote Procedure Call)을 구현하여, 호스트가 필요 시 게스트에게 특정 액션을 취하도록 할 수 있도록 설계했다.
    • 호스트에서 모든 물리 연산을 수행하고 난 위치(Position) 및 회전(Rotation) 결과를 게스트에게 실시간으로 전송하여 호스트와 게스트 간 게임 오브젝트의 동기화를 이루고, 게임의 상태(점수 및 클리어 여부) 변경 또한 호스트에서 이루어질 시 동일하게 게스트에도 적용되도록 설계했다.
    • 구체적인 동기화 과정은 아래와 같다.
      • SyncObjectId가 붙은 게임 오브젝트에 SyncBehaviour를 상속받은 컴포넌트가 SyncRPC 애트리뷰트가 붙은 사용자 정의 RPC 메서드를 호출한다.
      • SyncManager는 SyncBehaviour 컴포넌트가 호출한 RPC 메서드를 내부(호스트)에서도 호출하고 이를 직렬화하여 WebRTC로 수립한 데이터 채널을 통해 상대편(게스트)으로 전송한다.
      • 이때, NAT Traversal이 되는 상황에서는 UDP 전송을 수행하고, 그렇지 않은 특수한 상황에서는 어쩔 수 없이 외부 TURN 서버로 릴레이하여 fallback 처리한다.
      • 상대편(게스트)는 RPC 메시지를 수신하여 역직렬화하여 어떤 게임 오브젝트의 어떤 컴포넌트의 어떤 메서드를 호출해야 하는지 알아내어 이를 호출한다.
  3. 동기화 클래스 설계
    • Example.jpg
    • 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()를 통해 주입된다.

게임 룸 서버 설계

  1. 개요
    • 서로 모르는 두 플레이어가 같은 방(room)에 접속하기 위해 중앙에서 관리되는 서버가 필요하다.
    • Node.js 기반 NestJS 서버를 통해 Room Manager를 구현하여 각 방의 상태와 두 플레이어의 연결 정보를 한 곳에서 관리한다.
    • 각 컨트롤러(웹 또는 게임 클라이언트)는 이 서버를 통해 룸을 생성·입장하고, 지속적으로 자이로 값을 전송한다.
    • 서버는 실시간 WebSocket(또는 REST) API를 통해 자이로 데이터를 모아 Single Source of Truth를 유지하며, 필요 시 WebRTC 시그널링도 제공한다.
  2. 아키텍처 설계
    • 주요 모델
      • Example.jpg
    1. Repository Layer
      • Example.jpg
      • GameRoomInMemoryRepository: Map<string, GameRoom>을 사용해 룸 정보를 메모리에 저장합니다. create, getById, update, delete 등 기본 CRUD 메서드를 구현한다.
      • ShortCodeBase62InMemoryRepository: 일정 길이의 Base62 문자열을 생성해 룸 ID와 매핑하며 TTL이 지나면 자동으로 정리합니다.
      • ClientVersionJsonRepository: JSON 파일을 읽어 최신·최소 클라이언트 버전을 관리한다.
    2. Service Layer
      • Example.jpg
      • GameRoomService: 게임 룸 생성/입장/퇴장, 자이로 점유 관리, 단축 코드 발급 등을 담당합니다. 내부적으로 Repository 인터페이스에 의존한다.
      • WebRTCSignalingService: 피어 간 시그널링 연결을 관리하고 TURN 계정 정보를 동적으로 생성합니다. 연결된 피어의 메시지 전달을 중계한다.
      • ClientVersionService: 클라이언트 버전을 검사하여 호환 여부와 최신 버전을 알려준다.
    3. Controller Layer
      • Example.jpg
      • GameRoomController: /rooms 경로에서 룸 생성, 조회, 입장/퇴장, 자이로 관련 REST API를 제공한다.
      • GameRoomGateway: update-gyro 웹소켓 이벤트를 받아 GameRoomService의 자이로 값 갱신 메서드를 호출한다.
      • WebRTCSignalingGateway: /webrtc-signaling 경로에서 register/offer/answer/ice-candidate 등을 처리하여 상대 피어로 전달한다.
      • ClientVersionController: /client-version/check 엔드포인트로 클라이언트 버전을 검사한다.
      • HealthController: /health 경로에서 단순한 상태 체크 API를 제공합니다.
  3. 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 POST 자이로 제어권 요청 Path: roomId, axis
/join/{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