3.31.2014

네트워크 팁과 꼼수

By * John Pollard

기본 프로퍼티 리플리케이션

네이티브 코드로 리플리케이트된 프로퍼티를 처리할 때 알아두면 좋을 꼼수 몇 가지에 대해 이야기해 보고자 합니다.

프로퍼티 리플리케이션 전체에 대한 설명은 이 글의 범위를 약간 벗어나는 것이므로, 여기서는 기본에 대해 간단히 짚어보도록 하겠습니다.

프로퍼티 리플리케이션을 위해서는 몇 가지 작업을 해 줘야 합니다:

프로퍼티가 정의된 액터 클래스의 헤더에서, UPROPERTY 선언에 대한 파라미터 중 하나로 'replicated' 키워드가 있는지 확인해야 합니다:

class ENGINE_API AActor : public UObject

{

UPROPERTY( replicated )

AActor * Owner;

};

액터 클래스 구현에서, GetLifetimeReplicatedProps 함수를 구현해 줘야 합니다:

void AActor::GetLifetimeReplicatedProps( TArray< FLifetimeProperty > & OutLifetimeProps ) const

{

DOREPLIFETIME( AActor, Owner );

}

액터의 생성자에 bReplicates 플래그가 True 로 설정되어 있는지 확인합니다:

AActor::AActor( const class FPostConstructInitializeProperties & PCIP ) : Super( PCIP )

{

 

bReplicates = true;

}

대충 그렇습니다. 멤버 변수 'Owner' 는 이제 연결된 모든 클라이언트의 현재 인스턴싱된 이 액터 유형(이 경우 베이스 액터 클래스)의 모든 사본에 대해 동기화될 것입니다.

조건식 프로퍼티 리플리케이션

프로퍼티가 리플리케이션 등록되고나면, 그 등록을 해제할 수 없습니다 (그래서 수명이란 것이 등장합니다). 그 이유는 가급적 많은 정보를 구워넣기 때문에, 같은 프로퍼티 세트에 대한 다수의 접속에 걸쳐 작업 공유의 이점을 활용할 수 있는 것입니다. 이를 통해 계산 시간이 많이 절약됩니다.

그러면 이 프로퍼티 리플리케이트에 대한 더욱 미세한 제어가 어떻게 가능할까요? 바로 조건식 프로퍼티 입니다.

기본적으로 각 리플리케이트된 프로퍼티에는 내장된 조건이 있는데, 그것은 변경되지 않은 경우 리플리케이트하지 않는 것입니다.

프로퍼티 리플리케이션에 대한 제어를 강화하기 위해, 부차적인 조건을 추가시킬 수 있는 특수 매크로가 있습니다.

이 매크로는 DOREPLIFETIME_CONDITION 이라 불립니다. 그 사용법에 대한 예제는 아래에서 확인할 수 있습니다:

void AActor::GetLifetimeReplicatedProps( TArray< FLifetimeProperty > & OutLifetimeProps ) const

{

DOREPLIFETIME_CONDITION( AActor, ReplicatedMovement, COND_SimulatedOnly );

}

조건 매크로에 전달된 'COND_SimulatedOnly' 플래그는 이 프로퍼티의 리플리케이션 고려를 하기도 전에 추가적인 검사를 하도록 합니다. 이 경우, 이 액터의 시뮬레이션 사본이 있는 클라이언트에만 리플리케이트될 것입니다.

이 방법의 큰 장점 중 하나는 대역폭이 절약된다는 점입니다. 이 액터의 autonomous (자율) 프록시 버전을 갖는 클라이언트는 (이 프로퍼티를 예측 목적으로 직접 설정한다든가 해서) 이 프로퍼티에 대해 알 필요가 없다고 결정했기 때문입니다. 다른 장점은 이 프로퍼티를 받지 않는 클라이언트의 경우, 서버는 이 클라이언트의 로컬 사본에 발을 딛지 않을 것입니다.

현재 지원되는 조건 목록을 한 눈에 살펴볼 수 있는 목록입니다:

  • COND_InitialOnly - 이 프로퍼티는 초기 번치에만 전송 시도합니다.
  • COND_OwnerOnly - 이 프로퍼티는 액터의 오너에게만 전송합니다.
  • COND_SkipOwner - 이 프로퍼티는 오너를 제외한 모든 접속에 전송합니다.
  • COND_SimulatedOnly - 이 프로퍼티는 simulated 액터에만 전송합니다.
  • COND_AutonomousOnly - 이 프로퍼티는 autonomous 액터에만 전송합니다.
  • COND_SimulatedOrPhysics - 이 프로퍼티는 simulated 또는 bRepPhysics 액터에 전송합니다.
  • COND_InitialOrOwner - 이 프로퍼티는 초기 패킷에서 또는 액터의 오너에 전송합니다.
  • COND_Custom - 이 프로퍼티에는 특별한 조건이 없지만, SetCustomIsActiveOverride 를 통해 껐다 켰다 토글 기능이 필요합니다.

지금까지 이미 알려진 상태를 기반으로 한 조건에 대해 이야기해 봤습니다. 프로퍼티 리플리케이션에 대한 충분한 제어가 가능하면서도 엔진에 필수적인 최적화 작업을 하는 것이 쉬워집니다.

그러나 이 정도의 제어로 충분하지 않다면? 이 주제에 대해 이야기할 것이 한 가지 더 있습니다. 원하는 어떠한 조건이든 사용해서 프로퍼티 리플리케이트 여부와 시점에 대해 완벽한 제어가 가능한 DOREPLIFETIME_ACTIVE_OVERRIDE 라는 매크로가 있습니다. 한 가지 주의점은, 접속 단위가 아니라 액터 단위로 작동한다는 점입니다. 즉 다른 말로, 커스텀 조건에서 접속별로 달라질 수 있는 상태를 사용하는 것은 안전하지 않다는 것입니다. 예제는 아래와 같습니다:

void AActor::PreReplication( IRepChangedPropertyTracker & ChangedPropertyTracker )

{

DOREPLIFETIME_ACTIVE_OVERRIDE( AActor, ReplicatedMovement, bReplicateMovement );

}

ReplicatedMovement 프로퍼티는 이제 bReplicateMovement 가 True 일때만 리플리케이트 됩니다.

그러면 이 매크로를 항상 사용하지 않을 이유가 있을까요? 두 가지 있습니다:

  • 커스텀 조건 값이 많이 바뀌면 느려질 수 있습니다.
  • 접속 단위로 바뀔 수 있는 조건은 사용할 수 없습니다 (여기에는 RemoteRole 체크를 하지 마세요).

프로퍼티 리플리케이션 조건으로 콘트롤과 퍼포먼스 사이의 균형을 찾을 수 있습니다. 엔진이 다수의 접속에 보낼 프로퍼티를 검사하고 보내는 데 걸리는 시간을 최적화시킬 수 있는 기회를 주면서도, 프로그래머에게 프로퍼티 리플리케이트 방법과 시점을 미세하게 조정할 수 있도록 해 주는 것입니다.

지금까지 약간의 네트워킹 꼼수였습니다. 질문이 있으신가요? 포럼에서 이야기 계속 나누시지요. 한글 사용자분들을 위해 네이버 카페도 준비되어 있습니다.

Recent Posts

언리얼 스튜디오 4.20 베타 출시!

언리얼 스튜디오보다 나은 것이 있을까요?  물론이죠, 언리얼 스튜디오 4.20 입니다!  메타데이터 임포트, 원활한 익스포트 프로세스,...

PixARK Dev Kit으로 만드는 나만의 복셀 월드

에픽게임즈 런처에서 Snail Games가 제공한 모드 제작 툴로 재밌는 PixARK 월드를 만들어보세요.

Drive Studio, 언리얼 엔진으로 Fox Sports의 2018 FIFA 월드컵 방송 제작

Drive Studio는 언리얼 엔진의 강력함을 활용해 FOX Sports 채널의 2018 FIFA 월드컵 중계에서 사용할 배경, 중간...