Unreal Engine/네트워크

[UE] #1. Replication

코딩하는상후니 2022. 10. 24. 18:24

 

 

 

 

 


 

 

 
 

* 언리얼의 동기화 개념

 
 
멀티 플레이 게임에서의 가장 핵심적인 작업 중의 하나라고 볼 수 있다.
 
만약,
내가 플레이어를 때렸을 때 상대편은 내가 때리는 모습, 상대방이 맞는 모습을 볼 수 있어야하고
나는 상대편이 맞는 모습과 내가 때리는 모습을 볼 수 있어야한다.
 
네트워크 통신으로 연결된 클라이언트들이 자신들의 화면을 어떻게 공유하고
자신에 화면에서만 볼 수 있는 데이터들은 어떻게 구별해서 구현하는지 정확하게 알 필요가 있다.
 
 
서버-클라이언트 모델을 기반으로 하는 언리얼에서
어떤 과정으로 서버에서 처리하고 연결된 클라이언트들에게 어떻게 동기화시키는지 알아보자.
 
 
 
 
 
 
 
 
 

* Dedicated Server vs. Listen Server

 
언리얼에서 사용하는 서버-클라이언트 모델이다.

 

 

 

 

* Dedicated Server

 
=> 클라이언트가 아닌 독립형 서버이다.
 
말 그대로 헌신적인 서버라는 의미로 오로지 서버의 역할로서
클라이언트와는 분리되며 서버가 작동하는 동안 클라이언트는 서버에 연결될 수 있다.
 
Visual 부분이 없고 뒤쪽에서 지원해주는 역할로 언리얼의 UI, PlayerController 가 필요하지 않다.
또, 캐릭터, 혹은 클라이언트에게 보여주는 다른 것들을 필요하지 않는다.
 
 
 
 
 

* Listen Server

 
=> Listen Server 는 서버 임과 동시에 클라이언트 이다.
 
만약 Server 인 Host 가 연결이 끊어진다면, 서버는 다운된다.
 
클라이언트이기 때문에 Dedicated Server 와는 반대로
PlayerController, UI 등 플레이 요소들이 필요하다.
 
또한 보통의 경우,
ISP 를 통해 고정적인 IP를 제공받기 때문에 해당 IP 주소가 유동적 (변화) 일 수 있다.
그로 인해 다른 클라이언트들에게 혼동을 줄 수 있다.
( 서버의 IP 주소가 바뀌기 때문에 )
 
이러한 문제들은 OnlineSubsystem 을 활용해 바뀌는 IP 주소 문제를 해결할 수 있다.
( OnlineSubsystem 은 추후에 다룰 예정. )
 
 
 
 
 
 
 
 
 
 

* Replication

 
=> 'Replication' 이란 서버가 클라이언트들에게 정보/데이터를 전달해주는 행동 이다.
 
또 언리얼에서는 특정 그룹이나 객체에게 전달할 수 있도록 한다.
 
=> AActor 를 상속받은 모든 클래스에게는 Replicate 할 수 있는 기능이 존재한다.
물론 예외도 존재하는데,
GameMode 같은 경우에는 서버에만 존재하기 때문에 Replicate 를 할 수 없고 필요도 없다.
 
즉,
어떤 Object 등이 Replicated 하다 라는 의미
모든 클라이언트들에게 '동기화' 될 Object ( Data ) 라고 생각하면 된다.
 
동기화 : 여기서의 의미는 모든 클라이언트들에게 동일하게 보여지는 것

 

 

 
Actor Class 에는 Replication 항목이 존재한다.
 
 
=> 중요한 것은
오직 서버에 의해서 Object 가 생성되었을 때에만 서버에 연결된 클라이언트들에게 Replicated 될 수 있다.
만약, 클라이언트에서 Object 를 생성했을 때에는 오직 클라이언트에서만 작동한다. ( 로컬 )
 
 
 
 
또 하나 알아두어야할 것은
Replication 과정은 서버에서 클라이언트로 가는 과정만을 담는다.
 
 
즉,
Replication 은 서버에 영향을 미치지 않는다.
아래에서 살펴볼 OnRep Notify 함수도 마찬가지로 서버에서 동작하지 않기 때문에
 
만약,
Host 가 Server 인 Listen Server 라면 OnRep Notify 함수 호출 시,
Host Server 는 해당 함수를 실행하지 않는다.
 
 
 
 
 
 
 
 

* Replication 지정

 
 
여기서 생각해볼 문제는 '모든 것을 Replicated 한다면 어떻게 될까' 이다.
 
당연히 부하가 클 수 밖에 없다.
위에서 말한 것처럼 Replicated 된다라는 의미는 동기화 된다라는 말인데
Replicated Object 가 많을수록 서버에 연결된 클라이언트들에게 정보를 주는 횟수, 양이 많아진다.
 
때문에 우리의 궁극적인 목적은 효율적으로 게임이 부하 없이 돌아가기 위해선
'최소한''필요한 Replicated Data' 만을 '선별' 하여 게임을 구현하는 것이다.
 
 
 
 
 
 
 
 
 

* Replicaing PROPERTY ( Blueprint version )

 
 
 
 
중요한 것은
Replicated 될 변수는 반드시 Reflection 변수여야만 한다.
 
왜냐하면,
동적으로 해당 변수의 정보를 알 수 있어야지만
해당 값이 변화하였을 때 접근하기 용이하기 때문일 것이다.

 

 

=> 위 그림은 Blueprint 에서 변수를 Replicated 할 수 있는 방법 이다.
 
만약,
Replicated 변수라면 아래 그림처럼 2개의 원 모형이 표시 된다.

 

 

 

 

 

 

 

 

 

=> Blueprint 에서 변수를 Replication 항목에서 설정할 수 있다.
만약,
RepNotify 를 지정하면 자동적으로 OnRep_ 함수가 Blueprint 클래스 안에 선언 된다.
 
 
 
 
 
 
 
 
 

* Repliation ( C++ version )

 

 

* UPOPERTY ( Replicated )

 
=> 리플렉션 변수에 Replicated 지정자를 추가할 수 있다.
 
=> '해당 변수의 값이 변화할 때마다' 서버가 연결된 모든 클라이언트들에게 알려준다.

 

 

 

 

 

 

* UPOPERTY ( ReplicatedUsing = "OnRep_SomeFunction" )

 
=> ReplicatedUsing 은 마찬가지로 Replicated 지정자이다.
 
앞서 본 Replicated 와의 차이점은 'RepNotify' 함수를 설정할 수 있다는 것이다.
RepNotify 함수는 Replicated Data 가 성공적으로 클라이언트에게 도달했을 때 수행된다.

 

 

또한 서버에는 영향을 미치지 않는다.
오직 서버 -> 클라이언트의 과정만을 담기에 서버에 연결된 클라이언트들에게만 해당된다.

 

 

 

 

 

 

 

 

 

=> 추가적으로 활용할 수 있는 것은
 
RepNotify 함수는 Replicated 타입의 변수를 파라미터로 가질 수 있다.
 
Replicated 변수는 해당 값이 바뀔 때마다 Replicate 되고 그 때 Notify 함수가 발동한다고 했었는데
해당 Replicated 변수의 파라미터를 가짐으로써 '바뀌기 이전의 값을 저장' 할 수 있다.
 
다만,
당연하게도 해당 매개변수는 Replicated 타입의 변수이어야만 한다.
 
 
 
따라서 위 그림을 토대로,
 
OverlappingWeapon 은 Replicated 되었고 OnRep_OverlappingWeapon 은 RepNotify 함수이며,
OnRepNotify 함수가 실행되어 해당 영역으로 들어왔을 때
OverlappingWeapon 은 바뀐 변수이고 LastWeapon 은 바뀌기 전의 변수이다.
 
 
추가적으로 RepNotify 함수는 이전의 Replicated 변수의 값을 알 수 있지만,
RPC 함수에서는 알 수 없다. 단지 서버에 해당 함수를 호출하라고 알려주는 것 뿐이다.
RPC 함수는 우리가 일반적으로 사용하는 함수처럼 우리가 원하는 파라미터를 가질 수 있다.
( RPC 단원에서 자세히 알아보자. )
 

 

 
 
 
 
 
Replicated / ReplicatedUsing 지정자의 중요한 차이점은,
 
Replicated Data 는 단지 데이터의 변화만을 클라이언트들에게 전달하는 것 이다.
 
RepNotify 는 서버가 해당 데이터가 변화했다는 사실을 클라이언트에게 알려줌과 동시에,
어떤 동작을 실행시키게 하는 것이 'RepNotify 함수' 가 되겠다.
 
즉,
Replication 동작 시 작동하는 Callback 함수와 같다고 생각하면 된다.
 
RepNotify 함수는 UFUNCTION( ) 메크로를 붙여야하고
그것을 ReplicatedUsing = "FUCNTIONNAME" 으로 지정한다.
 
 
 
 
 
 
 
 
 
 
 
 
 

* GetLifetimeReplicatedProps ( .Cpp )

 

 

 
=> GetLifetimeReplicatedProps 함수 오버라이딩을 통해
사용할 Replication 변수를 등록해주어야 한다.
 
Super 호출은 잊지말아야 한다.
그렇지 않으면, 상속된 부모의 ReplicatedProps 들은 작동하지 않을 것이다.
 
 
 
 

 

 

 

 
 

* DOREPLIFETIME_CONDITION

 

 

 
CONDITION 지정자를 더해서 GetLifetimeReplicatedProps 함수에 추가할 수 있다.
해당 조건을 통해 Replicate 변수를 특정 그룹이나 대상의 범위로 사용할 수 있다.

 

즉,
서버에 연결되어있는 클라이언트들에게만 Replication 하는 과정에서 ( 조건이 없는 )
해당 '조건 키워드' 로 그들만의 특정한 그룹으로 구분지어 호출할 수 있게 한다.

 

 

 

 

 

 


 

 

참고 자료

 

UE4-Network-Compendium-by-cedric-exi-neukirchen.pdf
2.11MB

 

 

 

 

 

 

 

 

 

 

 

'Unreal Engine > 네트워크' 카테고리의 다른 글

[UE] #2. Network Role  (0) 2022.10.28