Unreal Engine 멀티플레이
싱글플레이 코드를 단순히 두 창에서 실행하는 데서 멈추지 않고, 서버 권한·Ownership·Replication·RPC·세션·Travel을 하나의 흐름으로 설계합니다. 최종적으로 호스트와 참가자가 로비에서 함께 맵으로 이동해 점령 포인트를 경쟁하는 2인 게임을 완성합니다.
과정에서 해결하는 문제
싱글플레이에서는 한 프로세스의 값 하나가 곧 정답이지만 멀티플레이에서는 서버와 각 클라이언트가 같은 Actor의 서로 다른 복사본을 가집니다. 클라이언트 화면에서 총알이 맞았다고 해서 서버의 피해 판정이 끝난 것이 아니며, 서버 값이 바뀌었다고 해서 UI가 자동으로 갱신되는 것도 아닙니다. 이 과정은 누가 결정하고, 어디에 저장하며, 어떤 연결로 누구에게 전달할지를 코드와 로그로 추적합니다.
선수 지식
- Unreal Engine C++ 기초집 완료 또는 동등한 Unreal C++ 프로젝트 경험
- C++ 클래스, 상속, 포인터·참조,
const, Delegate의 기초 - Actor, Pawn, Character, PlayerController와 ActorComponent의 기본 수명 주기
- Unreal Editor에서 C++ 클래스를 만들고 Development Editor 빌드를 실행하는 경험
이 과정은 첫 Unreal 과정이 아닙니다. 위 개념이 낯설다면 기존 입문 과정의 Character, Component, 체력, 디버깅 강의를 먼저 완료하세요.
개발 환경과 버전 기준
- Unreal Engine 5 계열 C++ 프로젝트
- Visual Studio 2022 또는 Unreal C++를 지원하는 Rider
- 첫 실습은 기본 Generic Replication System과 Online Subsystem Null을 사용
- 두 개 이상의 PIE 창, 별도 프로세스 실행과 로컬 포트 사용이 가능한 개발 PC
메뉴 이름과 Online Services API는 UE5 세부 버전에서 달라질 수 있습니다. 프로젝트가 사용하는 버전의 공식 문서를 우선하고, 이 과정의 IOnlineSession 예제와 새 Online Services Sessions API를 한 프로젝트에서 무심코 섞지 않습니다.
클래스 책임 지도
| 클래스 | 이 과정에서 맡는 책임 | 클라이언트에서의 상태 |
|---|---|---|
ACaptureArenaGameMode | 접속 승인, 스폰, 점령 점수와 승리 판정, Travel 시작 | 서버에만 존재하며 클라이언트에서 직접 접근 불가 |
ACaptureArenaGameState | 경기 단계, 팀 점수, 남은 시간처럼 모두가 알아야 할 상태 | 서버 원본과 모든 클라이언트 복사본 |
ACaptureArenaPlayerState | 플레이어 이름, 개인 점수, 킬처럼 Pawn 교체 뒤에도 남을 상태 | 서버 원본과 관련 클라이언트에 복제 |
ACaptureArenaPlayerController | 로컬 입력·UI 연결, 소유 클라이언트 RPC 경계 | 서버와 해당 소유 클라이언트에 존재 |
ACaptureArenaCharacter | 이동, 조준, 발사 요청과 캐릭터 상태 표현 | 서버 원본, 소유 Autonomous Proxy, 다른 Simulated Proxy |
| Actor / ActorComponent | 체력, 무기, 아이템, 점령 지점처럼 재사용 가능한 월드 기능 | 서버 권한 Actor와 필요 연결의 복사본 |
UCaptureSessionSubsystem | 세션 생성·검색·참가 Delegate와 Travel 연결 | 각 게임 프로세스의 GameInstance 수명 |
최종 결과물
CaptureArena는 두 명이 한 세션에 접속해 로비에서 준비한 뒤 경기 맵으로 이동하는 작은 점령 게임입니다. 서버가 점령 인원과 시간을 판정하고 GameState의 팀 점수를 복제합니다. 플레이어는 소유 Pawn을 통해 발사를 요청하지만 Trace, 데미지, 아이템 획득과 승리는 서버가 최종 결정합니다. 클라이언트는 RepNotify로 HUD를 갱신하고 Multicast는 일시적인 사운드·파티클에만 사용합니다.
32강 커리큘럼
| 강의 | 주제 | 누적 결과물 |
|---|---|---|
| 1 | 멀티플레이 게임은 싱글플레이와 무엇이 다른가 | 서버·클라이언트 상태 흐름도 |
| 2 | 서버 권한 구조와 클라이언트의 역할 | 권한 경계가 있는 첫 규칙 |
| 3 | P2P, 리슨 서버, 데디케이티드 서버 비교 | 호스팅 모델 비교표 |
| 4 | 리슨 서버와 데디케이티드 서버는 언제 선택할까 | 프로젝트 선택 기록 |
| 5 | PIE 멀티플레이 테스트 환경 만들기 | 2인 테스트 프로필 |
| 6 | NetMode로 현재 실행 환경 확인하기 | 인스턴스 식별 로그 |
| 7 | Authority, Role, 로컬 플레이어 판별하기 | 실행 위치 진단 Actor |
| 8 | Actor Replication 시작하기 | 서버 스폰 복제 Actor |
| 9 | Replicated 변수와 RepNotify | 상태와 화면 반응 동기화 |
| 10 | GameMode, GameState, PlayerState에 데이터를 어디에 둘까 | 게임플레이 상태 클래스 |
| 11 | PlayerController와 Pawn의 네트워크 역할 | 소유 입력 경계 |
| 12 | Ownership이란 무엇이며 왜 중요한가 | 유효한 RPC 소유 체인 |
| 13 | RPC 전체 구조 이해하기 | RPC 실행 대상 표와 진단 코드 |
| 14 | Server RPC로 서버에 요청 보내기 | 서버 검증 상호작용 요청 |
| 15 | Server RPC 검증과 치팅 방지 기초 | 요청 빈도·거리·상태 검증 |
| 16 | Client RPC로 특정 클라이언트에 알리기 | 소유 플레이어 전용 알림 |
| 17 | NetMulticast RPC로 모두에게 효과 보여 주기 | 일시적 공용 효과 |
| 18 | Reliable과 Unreliable RPC 선택 기준 | 전송 신뢰도 정책 |
| 19 | RPC와 변수 복제는 언제 구분할까 | 상태·이벤트 설계표 |
| 20 | Replication Condition으로 전송 대상 제한하기 | OwnerOnly·SkipOwner 상태 |
| 21 | CharacterMovementComponent와 캐릭터 이동 복제 | 이동·회전 검증 맵 |
| 22 | 입력, 카메라, UI는 어디서 처리할까 | 로컬 전용 표현 계층 |
| 23 | 무기 발사와 데미지를 서버 권한으로 처리하기 | 서버 Trace 무기 |
| 24 | 체력, 점수, 킬 로그 동기화하기 | RepNotify HUD와 점수판 |
| 25 | 아이템 스폰, 획득, 파괴 복제하기 | 서버 권한 회복 아이템 |
| 26 | 접속, 퇴장, 플레이어 목록 처리하기 | 복제 플레이어 목록 |
| 27 | 맵 이동과 ServerTravel 기초 | 로비→경기 맵 이동 |
| 28 | 세션 생성과 참가 흐름 이해하기 | Null 세션 생성·검색·참가 |
| 29 | LAN 테스트와 온라인 세션의 차이 | 환경별 테스트 매트릭스 |
| 30 | 데디케이티드 서버 패키징 구조와 준비 사항 | Server Target과 실행 기록 |
| 31 | 실습: 2인용 점령 포인트 게임 구현 | 세션부터 승리까지 통합 게임 |
| 32 | 최종 점검: 멀티플레이 버그 디버깅과 심화 과정 연결 | 재현 보고서와 확장 계획 |
공식 문서 기준
COURSE ORIENTATION
과정 선택 안내
- 학습 대상
- Unreal C++ 기초를 서버 권한·복제·RPC·세션이 있는 2인 게임으로 확장하려는 학습자
- 선수지식
- Unreal Engine C++ 입문, C++ 클래스와 Actor/Pawn/Character 기초
- 최종 결과물
- 세션과 서버 권한 판정을 갖춘 2인용 점령 포인트 게임
- 추천 다음 과정