본문 바로가기
언리얼(Unreal)/네트워크

25.03.13 언리얼 네트워크와 객체 통신

by alwaysyoung2 2025. 3. 13.
728x90
반응형

Replication이란?

Replication은 언리얼 엔진에서 네트워크 멀티플레이어 게임을 구현할 때 필수적인 기능입니다. 서버와 클라이언트 간의 데이터 동기화를 담당하며, 게임의 상태를 모든 플레이어에게 일관되게 유지하는 데 사용됩니다. Replication은 크게 RepNotify, ActorReplication, RPCs 세 가지 주요 개념으로 나뉩니다.

 

1. RepNotify

  • 용도: 특정 변수의 값이 변경될 때, 서버에서 클라이언트로 이벤트를 호출합니다.
  • 호출 방법: 자동으로 호출됩니다.
  • 실행 위치: 클라이언트에서 실행됩니다.
  • 특징: 네트워크가 연결되어 있을 때만 신뢰할 수 있습니다.
  • 예시 코드
UPROPERTY(ReplicatedUsing=OnRep_HealthChanged)
int32 PlayerHealth = 100;

UFUNCTION()
void OnRep_HealthChanged();
  • PlayerHealth 변수가 변경되면, OnRep_HealthChanged 함수가 클라이언트에서 자동으로 호출됩니다.

2. ActorReplication

  • 용도: 액터의 변수 값을 서버에서 클라이언트로 동기화합니다. 오너쉽(소유권) 관리도 포함됩니다.
  • 호출 방법: 자동으로 호출됩니다.
  • 실행 위치: 서버에서 값이 변경되면 클라이언트에 반영됩니다.
  • 특징: 네트워크가 연결되어 있을 때만 신뢰할 수 있습니다.
  • 예시 코드:
UPROPERTY(Replicated)
int32 PlayerHealth = 100;
  • PlayerHealth 변수는 서버에서 변경되면 클라이언트에 자동으로 동기화됩니다.

3. RPCs (Remote Procedure Calls)

  • 용도: 서버와 클라이언트 간의 양방향 함수 호출을 가능하게 합니다.
  • 호출 방법: 수동으로 호출됩니다.
  • 실행 위치: 서버 또는 클라이언트에서 실행됩니다.
  • 특징: Reliable(신뢰 가능) 또는 Unreliable(신뢰 불가능)로 설정할 수 있습니다.
  • 예시 코드:
UFUNCTION(Server, Reliable)
void ServerFireWeapon();

UFUNCTION(NetMulticast, Unreliable)
void MulticastPlayExplosionEffect();
  • ServerFireWeapon: 클라이언트에서 서버로 호출되는 함수입니다.
  • MulticastPlayExplosionEffect: 서버에서 모든 클라이언트로 브로드캐스트되는 함수입니다

Listen Server와 Dedicated Server

1. Dedicated Server

  • 정의: 전용 서버로, 오직 서버 기능만을 수행하는 별도의 빌드입니다.
  • 특징:
    • 별도의 빌드가 필요합니다.
    • 클라이언트 기능을 포함하지 않습니다.
    • 보안이 뛰어납니다.
    • 독립된 서버 환경에서 사용됩니다.
    • 개발 난이도가 상대적으로 깔끔합니다.
  • 용도: 대규모 멀티플레이어 게임이나 보안이 중요한 환경에서 사용됩니다.

2. Listen Server

  • 정의: 클라이언트 중 하나가 서버의 역할을 겸직하는 방식입니다.
  • 특징:
    • 별도의 빌드가 필요하지 않습니다.
    • 클라이언트 기능을 포함합니다.
    • 보안이 취약할 수 있습니다.
    • LAN 환경이나 소규모 그룹에서 사용됩니다.
    • 개발 난이도가 높으며, 권한 체크가 필수입니다.
  • 용도: 근거리 네트워크(LAN) 환경이나 소규모 멀티플레이어 게임에서 사용됩니다.

쉽게 이해하기 위한 예시

  1. RepNotify:
    • 서버: "너 체력이 100에서 80으로 줄었어!"
    • 클라이언트: "아, 체력이 줄었구나. 화면에 표시해줘야지!"
  2. ActorReplication:
    • 서버: "플레이어 A가 (10, 20, 30) 위치로 이동했어!"
    • 클라이언트: "플레이어 A를 그 위치로 이동시켜야지!"
  3. RPCs:
    • 클라이언트: "서버님, 제가 총을 쐈어요!"
    • 서버: "알겠어. 모든 클라이언트에게 폭발 이펙트를 재생하라고 알릴게!"

결론

  • Replication: 서버와 클라이언트가 정보를 공유하는 방법.
    • RepNotify: 값이 바뀌면 클라이언트에게 알림.
    • ActorReplication: 액터의 정보를 동기화.
    • RPCs: 서버와 클라이언트가 서로 함수를 호출.
  • 서버 종류:
    • Dedicated Server: 전용 서버로, 대규모 게임에 적합.
    • Listen Server: 한 명의 플레이어가 서버를 겸임, 소규모 게임에 적합.

 

객체 간 통신이란?

게임에서 여러 객체(예: 플레이어, 적, 아이템 등)가 서로 정보를 주고받아야 할 때가 있습니다.
예를 들어, 플레이어가 적을 공격하면 적의 체력이 줄어들고, 이를 화면에 표시해야 합니다.
이렇게 객체 간에 정보를 주고받는 것을 객체 간 통신이라고 합니다.

 

강한 결합 vs 이벤트 디스패처

1. 강한 결합 (형 변환을 통한 직접 호출)

  • 뭐냐?: 객체 A가 객체 B의 정보를 직접 알고 있어야 통신이 가능한 방식입니다.
  • 문제점:
    • 객체 B의 구조를 알아야 합니다.
    • 객체 B가 없으면 오류가 발생할 수 있습니다.
    • 코드가 복잡해지고 유지보수가 어려워집니다.
  • 예시:
    • GameMode에서 BP_Controller라는 객체를 찾아서 직접 이벤트를 호출합니다.
    • 만약 BP_Controller가 없으면 오류가 발생합니다.

2. 이벤트 디스패처 (Event Dispatcher)

  • 뭐냐?: 객체 A가 이벤트를 발생시키면, 객체 B와 C가 이를 구독하고 있다가 자동으로 반응하는 방식입니다.
  • 장점:
    • 객체 A는 객체 B와 C의 존재를 몰라도 됩니다.
    • 객체 B와 C는 원할 때 이벤트를 구독하거나 해지할 수 있습니다.
    • 코드가 간결해지고 유지보수가 쉬워집니다.
  • 예시:
    • 플레이어가 적을 공격하면, 이벤트 디스패처가 "체력이 줄었다!"라는 이벤트를 발생시킵니다.
    • 적 객체와 UI 객체는 이 이벤트를 구독하고 있다가, 체력을 업데이트합니다.

이벤트 디스패처 작동 원리

  1. 이벤트 등록: 객체 A가 이벤트 디스패처를 만듭니다.
  2. 이벤트 구독: 객체 B와 C가 객체 A의 이벤트 디스패처를 구독합니다.
  3. 이벤트 발생: 객체 A가 이벤트를 발생시키면, 구독한 객체 B와 C가 자동으로 반응합니다.

RPC와의 관계

이벤트 디스패처는 네트워크 게임에서도 사용할 수 있습니다.
이벤트의 Replicates 속성을 설정하면, 이벤트가 서버나 클라이언트에서 실행되도록 할 수 있습니다.
예를 들어:

  • Multicast: 서버에서 모든 클라이언트에게 이벤트를 전파합니다.
  • Run on Server: 클라이언트에서 서버로 이벤트를 전달합니다.
  • Run on Owning Client: 서버에서 특정 클라이언트에게 이벤트를 전달합니다.

쉽게 이해하기 위한 예시

강한 결합 예시

  • GameMode: "야, BP_Controller! 너 체력이 줄었으니까 화면 업데이트 해!"
  • BP_Controller: "알겠어!"
  • 문제: BP_Controller가 없으면 오류가 발생합니다.

이벤트 디스패처 예시

  • Player: "체력이 줄었어!" (이벤트 발생)
  • BP_Controller와 Enemy: "체력이 줄었다는 이벤트가 발생했네? 우리가 처리해야지!"
  • 장점: Player는 BP_Controller와 Enemy의 존재를 몰라도 됩니다.

결론

  • 강한 결합: 객체가 서로를 직접 알고 있어야 통신이 가능합니다. 유연성이 떨어집니다.
  • 이벤트 디스패처: 객체가 서로를 몰라도 통신이 가능합니다. 유연성이 높고 유지보수가 쉽습니다.
  • RPC와의 관계: 이벤트 디스패처를 네트워크 게임에서 사용할 때, Replicates 속성을 설정하면 서버와 클라이언트 간 통신이 가능합니다.

서버와 클라이언트 간의 통신

1. 서버에서만 작동하는 로직 호출하기

  • 문제: 클라이언트는 서버에서만 실행되는 게임 모드에 직접 접근할 수 없습니다.
  • 해결 방법: 플레이어 컨트롤러를 통해 서버에 요청을 보냅니다.
    • 예: 클라이언트가 플레이어 컨트롤러를 통해 서버에게 "게임 시작해주세요!"라고 요청합니다.
    • 서버는 이 요청을 받아 게임 모드에서 게임을 시작합니다.

2. 서버가 클라이언트에게 메시지 전달하기

  • 문제: 서버는 클라이언트에게 직접 메시지를 보낼 수 없습니다.
  • 해결 방법: 플레이어 컨트롤러 또는 게임 스탯을 통해 메시지를 전달합니다.
    • 예: 서버가 게임 스탯에 "점수가 업데이트되었습니다!"라는 정보를 저장하면, 클라이언트는 이를 동기화받아 화면에 표시합니다.

예시 시나리오

  1. 클라이언트가 서버에 요청하기:
    • 클라이언트: "플레이어 컨트롤러님, 서버에게 게임 시작해달라고 요청해주세요!"
    • 플레이어 컨트롤러: "서버님, 클라이언트가 게임 시작을 원합니다!"
    • 서버: "알겠습니다. 게임 모드님, 게임을 시작해주세요!"
  2. 서버가 클라이언트에게 메시지 전달하기:
    • 서버: "게임 스탯님, 점수가 업데이트되었으니 모든 클라이언트에게 알려주세요!"
    • 게임 스탯: "모든 클라이언트님들, 점수가 업데이트되었습니다!"
    • 클라이언트: "점수가 바뀌었네요. 화면에 표시해야겠어요!"

정리

  • 게임 모드: 게임의 규칙을 정의. 서버에서만 실행.
  • 게임 스탯: 게임의 현재 상태를 저장. 서버와 클라이언트 모두에서 접근 가능.
  • 플레이어 컨트롤러: 플레이어의 입력과 화면을 관리. 서버와 클라이언트 간의 중개자 역할.
  • 통신 방법:
    • 클라이언트 → 서버: 플레이어 컨트롤러를 통해 요청.
    • 서버 → 클라이언트: 게임 스탯 또는 플레이어 컨트롤러를 통해 메시지 전달.

728x90
반응형