75 번재 TIL

이원창·2026년 10월 7일

2026년 10월 7일 팀원과 소통시간을 가진 후 강의를 들으며 내용정리 중이다.

오늘 배운 내용 한 줄 요약: 서버와 클라이언트가 같은 로그 창에 찍히게 만든 뒤, 접속·시작·빙의 함수가 어느 머신에서 어떤 순서로 도는지 본다.

로그를 한 창에서 보기

Play 설정은 Launch Separate Server = false, Run Under One Process = true. 서버와 클라이언트 로그가 한 출력에 모인다.

에디터를 켠 직후 바로 플레이하면 CDO 생성자 로그가 여러 번 찍힌다. 네트워크 로그만 보려면 에디터를 켠 다음 Clear Log하고 플레이한다.

// 넷모드 + 함수 이름
#define DX_LOG_NET(LogCategory, Verbosity, Format, ...) \
    UE_LOG(LogCategory, Verbosity, TEXT("[%s] %s %s"), NETMODE_TCHAR, FUNCTION_TCHAR, *FString::Printf(Format, ##__VA_ARGS__))

// 넷모드 + LocalRole/RemoteRole
#define DX_LOG_ROLE(...)

NETMODE_TCHAR는 Client00, Server, StandAlone 중 하나다. PIE 번호가 붙어서 어느 창의 로그인지 구분한다.

프레임워크 액터는 어디서 생기나

생성자에 DX_LOG_NET을 넣고 비교한다.

접속 함수

PostLogin에서 서버 쪽 연결 목록, PostNetInit에서 클라이언트 쪽 서버 연결. 양쪽을 나눠 보는 이유다.

데이터가 오가는 단위

게임이 시작되는 길

GameMode::StartPlay의 Super를 빼면 모든 액터의 BeginPlay가 안 불린다. 캐릭터도 움직이지 않는다. 확인 뒤에는 주석을 푼다.

클라이언트에는 GameMode가 없다. 그래서 GameMode가 직접 시작하지 않고 GameState에 시작을 맡긴다. GameState는 복제된다.

GameMode::StartPlay
  → GameState::HandleBeginPlay
       서버: bReplicatedHasBegunPlay = true
             WorldSettings::NotifyBeginPlay()  → 서버 액터 BeginPlay
       클라이언트: OnRep_ReplicatedHasBegunPlay
             (Authority가 아니면) NotifyBeginPlay() → 클라이언트 액터 BeginPlay

NotifyBeginPlay는 월드의 액터를 돌며 DispatchBeginPlay를 호출한다.

시작 전후 함수 순서:

  1. PostInitializeComponents — 붙인 컴포넌트가 준비된 뒤
  2. PostNetInit — 서버에서 속성 세팅이 끝나고 클라이언트에 복제된 뒤. 항상 BeginPlay보다 먼저
  3. StartPlay — 게임 시작을 지시
  4. BeginPlay — 그 신호로 월드의 액터에서 호출

빙의(Possessed) 와 Owner

PossessedBy가 SetOwner(NewController)를 한다. 이 소유로 어느 클라이언트의 NetConnection에 속하는지가 정해진다. UnPossessed는 Owner, Controller, PlayerState를 비우고 ForceNetUpdate한다.

PlayerController::OnPossess는 서버에서만 돈다. 클라이언트는 Possess()를 호출하지 않는다. Owner는 ReplicatedUsing이라, 클라이언트에서는 OnRep_Owner로 소유자가 들어온다.

빙의 전후에 DX_LOG_ROLE로 Local Role / Remote Role을 찍으면, 캐릭터의 Remote Role이 바뀌는 것을 볼 수 있다.

오늘 정리

  • 한 프로세스 PIE + DX_LOG_NET으로 서버/클라이언트를 같은 로그에서 구분한다.
  • 접속을 막으려면 PreLogin의 ErrorMessage. 연결 목록은 PostLogin, 서버 연결은 PostNetInit.
  • 시작은 GameMode가 아니라 복제되는 GameState의 bReplicatedHasBegunPlay가 클라이언트 BeginPlay를 연다.
  • 빙의(Possessed)와 Owner는 서버에서 정하고, 클라이언트는 OnRep_Owner로 받는다.

0개의 댓글