발생한 문제
프로젝트 및 월드 세팅을 언리얼 엔진에서 제공하는 GameState 클래스의 경우 컨트롤러에 빙의한 캐릭터 내
Movement Component가 자동으로 동기화가 됨.
게임 내 공통적으로 필요한 기능들을 구현하기 위해 GameStateBase 기반의 커스텀 GS를 생성, 게임모드 생성자에서
GameStateClass = MyGS::StatcClass() 적용, 프로젝트 및 월드세팅 확인 후 결과
다른 컴포넌트들은 정상적으로 동기화가 되었으나, 언리얼에서 제공하는 Movement Component는 동기화가 안됨.
해결 과정
AMyGameMode.cpp
AMyGameState::AMyGameState()
{
bReplicates = true;
bAlwaysRelevant = true;
bNetLoadOnClient = true;
}
리플리케이티드 및 네트워크 동기화를 위한 변수 true 적용해보기
언리얼에서 제공하는 기본 게임 스테이트 클래스에서는 적용이 되어있었으나,
커스텀 게임 스테이트 클래스에서는 명시적으로 처리해야 하는 것.
- bReplicates : 클라이언트에 해당 GameState 복제에 대한 여부
- bAlwaysRelevant : 모든 클라이언트가 항상 리플리케이션 되도록 설정
- bNetLoadOnClient : 클라이언트가 레벨 로드시 GameState를 생성하도록 설정
BP_MyCharacter
무브먼트 컴포넌트 내 리플리케이트 설정
- C++ : GetMovementComponent()->SetIsReplicated(true);
두가지의 적용 결과 언리얼에서 제공하는 기본적인 기능들이 리플리케이션이 적용되지 않았습니다.
- Weapon관련 RPC, Health관련 RPC의 경우는 정상적으로 동작됨을 확인
AGameStateBase -> AGameState 클래스 상속 변경
- class MyProject_API AMyGameState : public AGameStateBase -> : public AGameState
- AGameStateBase : 게임 스테이트 클래스의 기본적인 기능을 가지고 있음, 멀티플레이 관련 확장적으로 가능
- AGameState : 멀티플레이 관련 기능 기본적으로 제공
- 관련 문서 : https://dev.epicgames.com/documentation/ko-kr/unreal-engine/game-mode-and-game-state-in-unreal-engine
기반 상속구조 변경 후 정상적으로 동기화가 됨.
멀티플레이 내 GameState VS GameStateBase
- override 하지 않은 함수들의 경우, 기본적으로 GameStateBase에서 동일한 로직을 구현할 것이라 생각.
- 생성자 관련 부분 먼저 확인해보기
- 생성자 관련 부분에서 State에서는 추가적인 멀티플레이 로직이 없는것을 확인 할 수 있었음.
- 즉, 생성자 외 오버라이드된 함수 내에서 추가기능을 통해 Possess 관련 동기화과 있을것이라 생각.
공식문서 설명을 보면, 해당 함수 및 변수들이 멀티플레이 관련 역할을 한다고 알 수 있다.
// AGameStateBase.cpp
void AGameStateBase::PostInitializeComponents()
{
Super::PostInitializeComponents();
UWorld* World = GetWorld();
World->SetGameState(this);
FTimerManager& TimerManager = GetWorldTimerManager();
if (World->IsGameWorld() && GetLocalRole() == ROLE_Authority)
{
UpdateServerTimeSeconds();
if (ServerWorldTimeSecondsUpdateFrequency > 0.f)
{
TimerManager.SetTimer(TimerHandle_UpdateServerTimeSeconds, this, &AGameStateBase::UpdateServerTimeSeconds, ServerWorldTimeSecondsUpdateFrequency, true);
}
}
for (TActorIterator<APlayerState> It(World); It; ++It)
{
AddPlayerState(*It);
}
}
// AGameState.cpp
void AGameState::PostInitializeComponents()
{
Super::PostInitializeComponents();
FTimerManager& TimerManager = GetWorldTimerManager();
TimerManager.SetTimer(TimerHandle_DefaultTimer, this, &AGameState::DefaultTimer, GetWorldSettings()->GetEffectiveTimeDilation() / GetWorldSettings()->DemoPlayTimeDilation, true);
}
- 주요 문제는 StateBase 상속 시 Component가 동기화 되지않음
- 즉, Component 관련 설정이 문제다. -> PlayerArray에 추가하는 로직이 오버라이드 되어있다.
- 언리얼은 서버 동기화시 실시간성을 동시 지원하기위해 예측 및 Reconciliation 방법을 사용.
- 동기화시 서버 월드와 클라이언트의 월드는 서로 다르기때문에 월드 서버를 기준으로 동작해야된다.
- TimeManager를 통해 서버의 월드를 Simulate해서 클라이언트의 월드를 복제, 시간값 관련 동기화
'Unreal Engine > Debugging' 카테고리의 다른 글
[UE5] - 리슨서버 RPC/Replicated를 사용한 Bulls And Cows구현 (0) | 2025.03.25 |
---|---|
[UE5] UObject 클래스 내 GetWorld Null 반환 (0) | 2025.02.26 |
[UE5] - 유효성 검사 (0) | 2025.01.27 |