1-5. NetRole
Authority와 Proxy
서버에 스폰 된 액터가 가진 NetRole 속성 값은 언제나 Authority.
서버에 스폰 된 액터에서 수행될 로직은 권한을 가지고 있음을 뜻함.
게임에 중대한 영향을 끼치는 로직은 NetRole이 Authority일 때 수행해야 함.
NetRole이 Authority인 액터가 클라이언트로 복제되었을 때, 클라이언트에 복제된 액터의 NetRole 속성 값은 Proxy.
(허상 정도로 생각하면 편함)

로컬 롤과 리모트 롤
게임에 중대한 영향을 끼치는 로직을 작성하기 위해,
해당 액터가 현재 어느 PC에 스폰 되어서 로직이 돌고 있는지 구분해야 함.
로컬 롤(Local Role)
현재 동작하는 컴퓨터에서의 롤
리모트 롤(Remote Role)
커넥션으로 연결된, 반대편 컴퓨터에서의 롤

NetRole의 종류
None
- 보통의 경우, 레플리케이션 되지 않는 액터를 뜻함. (무조건적이진 않음)
- ex) LocalRole은 Authority이고 RemoteRole이 None이라면
서버에서 스폰 되고, 클라쪽으로 레플리케이션 되지 않는 액터라고 볼 수 있음.
Authority
- 게임에 중대한 영향을 끼칠 수 있는 권한을 가진 액터를 뜻함.
- 서버에서 스폰된 액터가 LocalRole으로 Authority를 가질 수 있음.
- ex) GameMode
Autonomous Proxy
- Authority 액터의 복제본.
서버로부터 데이터를 수신 받아서 동기화 가능, 서버로 송신도 가능. - ex) PlayerController
Simulated Proxy
- Authority 액터의 복제본.
서버로부터 수신 받아서 동기화 당하기만 함. - ex) 내 화면에 보이는 친구의 PlayerCharacter

매크로를 통한 NetRole 출력
New C++ 클래스 > Pawn 부모 클래스 > “CXPawn”
Path: Player (경로 뒤에 Player 추가)
BP_GameModeBase > Details > Default Pawn Class에 CXPawn 지정
// ChatX.h
...
class ChatXFunctionLibrary
{
public:
...
static FString GetRoleString(const AActor* InActor)
{
FString RoleString = TEXT("None");
if (IsValid(InActor) == true)
{
FString LocalRoleString = UEnum::GetValueAsString(TEXT("Engine.ENetRole"), InActor->GetLocalRole());
FString RemoteRoleString = UEnum::GetValueAsString(TEXT("Engine.ENetRole"), InActor->GetRemoteRole());
RoleString = FString::Printf(TEXT("%s / %s"), *LocalRoleString, *RemoteRoleString);
}
return RoleString;
}
};
// CXPawn.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Pawn.h"
#include "CXPawn.generated.h"
UCLASS()
class CHATX_API ACXPawn : public APawn
{
GENERATED_BODY()
protected:
virtual void BeginPlay() override;
virtual void PossessedBy(AController* NewController) override;
};
// CXPawn.cpp
#include "CXPawn.h"
#include "ChatX.h"
void ACXPawn::BeginPlay()
{
Super::BeginPlay();
FString NetRoleString = ChatXFunctionLibrary::GetRoleString(this);
FString CombinedString = FString::Printf(TEXT("CXPawn::BeginPlay() %s [%s]"), *ChatXFunctionLibrary::GetNetModeString(this), *NetRoleString);
ChatXFunctionLibrary::MyPrintString(this, CombinedString, 10.f);
}
void ACXPawn::PossessedBy(AController* NewController)
{
Super::PossessedBy(NewController);
FString NetRoleString = ChatXFunctionLibrary::GetRoleString(this);
FString CombinedString = FString::Printf(TEXT("CXPawn::PossessedBy() %s [%s]"), *ChatXFunctionLibrary::GetNetModeString(this), *NetRoleString);
ChatXFunctionLibrary::MyPrintString(this, CombinedString, 10.f);
}
BP_GameModeBase > Details > Default Pawn Class에 CXPawn을 지정

로그를 확인했다면 BP_GameModeBase > Default Pawn Class는 None으로 돌려놓기

NetRole을 활용하여 정의된 중요 함수
게임에 중대한 영향을 끼치는 데미지나 스폰 같은 로직은 서버 컴퓨터에서 실행되어야 함.
이를 위해 언리얼은 AActor::HasAuthority() 함수를 제공
입력 관련 로직이나 UI는 Autonomous Proxy에서 수행되어야 함.
이를 위해 AController::IsLocalController() 와 APawn::IsLocallyControlled() 함수가 제공.
[참고] AActor::HasAuthority() 함수
// AActor.cpp
FORCEINLINE_DEBUGGABLE bool AActor::HasAuthority() const
{
return (GetLocalRole() == ROLE_Authority);
}
HasAuthority → 서버 로직을 체크하기 위함.
주의사항
리슨서버 → 플레이어 임과 동시에 서버 역할도 겸함.
Standalone 상태에서도 Ture가 나옴.
HasAuthority → Ture라고 해서 무조건 멀티플레이 중인 서버는 아님.
AController::IsLocalController() 함수
// APawn.cpp
bool APawn::IsLocallyControlled() const
{
return ( Controller && Controller->IsLocalController() );
}
// AController.cpp
bool AController::IsLocalController() const
{
const ENetMode NetMode = GetNetMode();
if (NetMode == NM_Standalone)
{
// Not networked.
return true;
}
if (NetMode == NM_Client && GetLocalRole() == ROLE_AutonomousProxy)
{
// Networked client in control.
return true;
}
if (GetRemoteRole() != ROLE_AutonomousProxy && GetLocalRole() == ROLE_Authority)
{
// Local authority in control.
return true;
}
return false;
}
각 액터에 따른 특징
- 게임 모드는 HasAuthority() 함수를 호출할 필요가 없음.
- 폰은 Authority, Autonomous Proxy, Simulated Proxy가 혼재되어 있음.
- UI 관련 로직은 클라이언트에서만 수행.
로컬 롤과 리모트 롤 2가지인 이유
로컬 롤만 있었다면 분간하기가 어려운 케이스
예시: 서버에 접속한 플레이어의 캐릭터 A와 서버에서 스폰 된 캐릭터 B가 있다고 가정. (A와 B의 로컬 롤은 Authority)
- 로컬 롤만으로는 서버에 접속한 플레이어의 캐릭터인지, 서버에서 스폰된건지 구분 불가능.
- 만약 리모트 롤까지 알게된다면, 서버에 접속한 플레이어의 캐릭터는 Autonomus Proxy.
- 서버에서 스폰된 캐릭터는 None이므로 구분할 수가 있어짐.
구분이 가능해야 서버에서 호출되고 오너 클라이언트에서 실행될 RPC를 구현이 가능.
멀티플레이에서 각 액터들을 좀 더 정확하게 분류하게 위해 2가지로 나눔.

'개인 강의 > Unreal Engine 멀티플레이어 게임 개발' 카테고리의 다른 글
| Unreal Engine 멀티플레이어 게임 개발 2-2 (0) | 2026.07.29 |
|---|---|
| Unreal Engine 멀티플레이어 게임 개발 2-1 (0) | 2026.07.29 |
| Unreal Engine 멀티플레이어 게임 개발 1-4 (0) | 2026.07.29 |
| Unreal Engine 멀티플레이어 게임 개발 1-3 (0) | 2026.07.28 |
| Unreal Engine 멀티플레이어 게임 개발 1-2 (0) | 2026.07.28 |