Multiplayer용 Session 시스템 만들어 보기 #1

Ryan Ham·2025년 2월 3일
1

Unreal Engine

목록 보기
34/39
post-thumbnail

이번에 새로운 멀티플레이 포트폴리오 작업 계획을 세울때 어차피 세션에 대한 개념이 들어가고 이 세션 시스템을 한번 만들어 놓으면 나중에 다른 멀티플레이 프로젝트를 할때도 많이 사용할 것 같아 이를 그냥 플러그인으로 만들어 보려고 했다.

따라서 현재 언리얼의 세션이 어떻게 돌아가는지, FAB에는 어떤 세션 플러그인들이 존재하는지, 내가 더 개선해서 플러그인으로 만들만한 부분들이 있는지 등을 먼저 조사해보았다.


언리얼 세션관련 주요 항목들 (C++)

IOnlineSession

IOnlineSession은 언리얼이 세션 관련 중요 함수들을 모아놓은 인터페이스이다. 대표적으로 Session Create, Session Find, Session Join, Session Destroy, Session Start와 같은 함수들을 제공한다. 또한, 각각의 함수들이 불려졌을때 트리거되는 Delegate(i.e. FOnCreateSessionCompleteDelegate)들 또한 제공하고 있다.

FOnlineSessionSettings

보통 언리얼에서 'F-' prefix가 붙으면 구조체를 말하는데 FOnlineSessionSettings 그냥 일반 클래스여서 약간 의아했다. 이 클래스에서는 Session 관련 함수를 부를때 추가적인 설정을 더할 수 있다. 예를 들어서 IOnlineSession에 존재하는 CreateSession은 단순하게 이렇게 생겼다.

SessionInterface->CreateSession(0, SessionName, SessionSettings);

위 코드에서 SessionSettings에 추가 정보를 입력함으로서 디테일하게 세션 관련 함수를 사용할 수 있다.

대표적으로 많이 사용하는 추가 Session Settings

GameMode, GameState, GameInstance

이 클래스들은 항상 중요한 친구들이지만 세션 작업시에도 이들이 어떻게 일을 하는지 잘 알고 있어야 한다. GameMode는 Multiplay 게임에서 사용자가 들어오고 나갈때 작동하는 PostLogin, Logout 함수들이 있다. GameState에는 Login을 완료한 연결된 플레이어의 PlayerState 배열을 들고 있어 현재 몇명이 server에 연결되어 있는지 확인할 수 있다. GameInstance는 Singleton 객체이면서 Multiplay 게임 도중 맵이 전환될때에도 죽지 않고 살아있다(다른 객체들은 server-travel이 일어나면 없어졌다가 다시 spawn된다)


AdvancedSessionPlugins

인터넷 서칭을 해보니 Joshua란 사람이 이미 FOnlineSessionSettings의 세팅을 한꺼번에 포함해서 세션관련 함수들을 다룰 수 있는 BP 함수 라이브러리를 만들어 놓았다. 이에 관련해서 유튜브에 많은 튜토리얼 또한 존재했어서 이분이 만든 프로덕트를 먼저 사용해보기로 했다.

AdvancedSessionPlugins 깃헙 링크

설치 방법

  1. Github description에 들어가보면 ue4 전용이라고 하지만, 사이트에서 binary 섹션에 들어가보면 5.5 build까지 되어 있다. 이를 다운로드 하자.
  2. 새로운 언리얼 프로젝트를 파고 안에다가 Plugins 폴더 생성. 다운로드 받은 항목에서 AdvancedSessionsAdvancedSteamSessions 2개 파일 이동
  3. .vs, DerivedDataCache, Intermediate, Saved, .vsconfig, .sln 지우고 uproject -> regenerate files한다.
  4. 새롭게 생성된 .sln 파일에서 build
  5. Unreal 파일(.uproject)에서 Plugins 탭에 들어가서 Advanced Sessions과 Advanced Steam Sessions 플러그인들이 잘 활성화되어 있는지 다시 한번 체크 + OnlineSubsystem 까지
  6. OnlineSubsystem Steam을 사용하려면 DefaultEngine.ini에 추가적인 설정을 해야한다.(만약 이미 사용하고 있는 SteamDevAppId가 있다면 그 번호를 설정에 넣을것! 참고 링크)
  7. Steam을 백그라운드에서 실행하고 StandAlone 모드로 게임을 돌려봐서 Steam이 제대로 연결되었는지 확인 (이때는 다시 rebuild 할 필요는 없음)

일반 SessionCreate VS AdvancedSessionPlugin의 SessionCreate

왼쪽이 언리얼에서 기본적으로 제공하는 CreateSession BP 노드이고, 오른쪽이 AdvancedSEssionPlugin에서 만든 CreateSession BP 노드이다. FOnlineSessionSettings에서 제공하는 추가 세팅들을 그냥 인풋핀에 박아버린 것을 확인할 수 있다.

또, 여기서 하나의 중요한 킥이 있는데 바로 Extra Settings 인풋 핀이다. 여기서는 자기가 Session을 만들때 넣고 싶은 값을 Key-Value 형태로 만들어서 보관할 수 있다. 예를 들어서 세션의 이름, 세션의 제작자, 세션을 만든 위치 등 다양한 정보를 상황에 맞게 넣을 수 있다.


플러그인 테스트 해보기

여러 관련 유튜브 튜토리얼을 보면서 Pixel Helmet이라는 채널의 자료를 사용해서 플러그인 테스트를 진행해보았다.

테스트 프로젝트 진행(초기 버전)

기능은 아주 간단하다. 사용자는 세션을 만들거나 아니면 만들어진 세션 목록들을 보면서 자기가 세션에 참여할 수 있다. 세션을 만드는 창에서는 세션 이름, 최대 접속 플레이어 수, 나라, 맵 등을 설정해서 세션을 만들 수 있다.

만들어진 세션 목록들을 볼수있는 Session Browser에서는 Session을 만들때 넣었던 추가 항목들로 필터링해서 결과 값을 볼 수 있다. 여기서 디테일이 있는데, 처음 Session Browser에 진입하는 순간과 Refresh 버튼을 누르는 순간에만 생성된 모든 세션 결과를 가져와 저장한다. 이게 시간이 은근 많이 걸리는 작업임으로 필터링할때 매번 세션 결과를 가져오지 않게 했다.

Session 생성 창

Session Browser 들어가는 화면

Session Browser에서 필터링

Session Browser에서 Session Join


고전했던 부분

첫 번째로 고전했던 부분은 Client와 Server의 초기 화면을 맞추는 것이였다. 레벨 블루프린트에서 시네마틱 카메라와 Set View Target With Blend를 사용해서 백그라운드에 고정된 영상을 실시간으로 틀어주는 것이 가능하다. 하지만, Server에서만 영상이 틀어지고 Client에서는 틀어지지 않는 문제가 발생했다.

이유를 찾아보니 레벨 블루프린트의 로직은 서버에서만 실행이 된다고 한다. 따라서 이를 해결하기 위해 Set View Target With Blend 관련 로직을 Client RPC로 만들어 Player Controller안에 위치 시켰다. 그리고, 레벨 블루프린트에서는 서버가 GameState에 접근해 연결된 모든 Player의 PlayerController의 Client RPC를 직접 실행시켜 주었다.(사실 여기서도 PlayerController가 로그인되기 전에 GameState를 먼저 접근해버려서 문제가 생겼는데 일단은 임시방편으로 delay를 사용해서 해결했다. PostLogin에 델리게이트를 연결하면 깔끔하게 해결할 수 있을 것 같긴 하다.)

1번째 고전했던 문제 고치기 전 화면

1번째 고전했던 문제 고친 후 화면

두 번째로 고전했던 부분은 GameMode/GameModeBase와 GameState/GameStateBase의 관계였다. 둘다, ~Base가 붙지 않는 클래스가 더 확장된 기능을 제공한다. 여기서 GameMode를 상속한 클래스는 GameState를 상속한 클래스를 사용해야 되고 반대로, GameModeBase를 상속한 클래스는 GameStateBase를 상속한 클래스를 사용해야 한다. 이를 몰라서 많이 해맸다.

세 번째로 고전했던 부분은 맵이였다. 플레이어가 Session Browser에서 선택한 세션과 연관된 맵으로 client travel하려면 맵에 대한 정보를 알아야 한다. 처음에는 언리얼 맵의 타입인 UWorld의 Soft Reference를 저장하는 것이 가능해서 Reference로 직접 맵을 열려고 했으나 이름만으로 열 수 있는 방법이 있다는 것을 알았다.

이름으로 맵을 잘 열다가 프로젝트를 패키징할때 맵 관련 오류가 나서보니 게임 프로젝트에 사용되는 맵을 따로 Project Setting에 아래와 같이 등록했었어야 했다.


추가 작업 계획

  • 지금은 Listen Server로 맵을 만들고 ServerTravel하는데 이를 Dedicated로 바꿔보기
  • Firewall의 문제인지 만든 프로젝트를 패키징해서 다른 머신과 로컬에서 접속해보면 세션을 찾지 못하는데 이 문제 해결해보기
  • 서버 인스턴스가 ServerTravel하면 client 인스턴스들의 화면이 갑자기 새로고침이 되는데 이것의 원인 파악해보기

Reference

https://vreue4.com/advanced-sessions-plugin
https://github.com/mordentral/AdvancedSessionsPlugin
https://www.youtube.com/@PixelHelmet

profile
🏦KAIST EE | 🏦SNU AI(빅데이터 핀테크 전문가 과정) | 📙CryptoHipsters 저자

0개의 댓글

관련 채용 정보