[이득우 네트워크 멀티플레이] 05. 액터 리플리케이션 기초
액터 리플리케이션의 동작 원리를 이해하고 프로퍼티 리플리케이션을 구현해 보자
액터 리플리케이션 기초
액터 리플리케이션
액터 리플리케이션 : 특정 플레이어에 속한 액터의 정보를 네트워크 내 다른 플레이어에게 복제하는 작업
클라이언트-서버 모델에서는 대부분 서버에 Authority가 있기 때문에 서버에서 클라이언트로 전달한다.
리플리케이션의 방법에는 크게 두 가지가 있다.
1. 프로퍼티 리플리케이션 : 속성 복제에 관련된 작업을 수행
2. RPC(Remote Procedure Call) : 함수 호출에 관련된 작업을 수행
기본 액터의 로딩
리플리케이션 작업에서 가장 중요한 것은 데이터 전송량을 최소화해서 서버 부하를 최소화하는 것이다.
이런 관점에서 클라이언트가 초기화될 때 모든 액터 정보를 서버로부터 받는 것을 비효율적이다.
따라서 기본 레벨에 배치된 액터는 맵을 통해 스스로 로딩하도록 설계되어 있다. 즉 네트워크 없이 클라이언트가 스스로 로딩하도록 돼있다.
기본 레벨에 배치된 액터를 고정으로 제공하는 액터라고 하고 게임이 진행되면서 만들어지는 액터를 동적으로 생성하는 액터라고 볼 수 있다.
고정으로 제공하는 액터의 예) 레벨을 구성하는 배경 액터
동적으로 생성하는 액터의 예) 플레이어 컨트롤러와 폰
고정 액터에 대해 NetLoadOnClient 속성을 체크해야 한다.
> 레벨에 배치되는 액터들은 기본값이 참이다.
Question
NetLoadOnClient 했을 때 클라이언트에서 액터의 어써리티 체크
프로퍼티 리플리케이션의 구현
액터의 리플리케이션 설정
몇몇 액터는 게임 중 변경 사항이 발생하는 액터는 그 값을 전달해야 함.
네트워크 데이터를 최소화하기 위해 변경 사항을 전부 보내기보다, 변경을 유발한 속성 값을 전달해야 한다.
> 비주얼 적인 변화가 있을 때, 변경된 비주얼에 관련된 정보를 전부 보내는 것이 아니라 속성값을 전달하는 식으로 최소화한다.
이를 위해 액터의 Replicates 옵션을 체크해야 함.
리플리케이션 프로퍼티의 지정
프로퍼티 리플리케이션을 사용하는 방법은 다음과 같다.
1. 액터의 리플리케이션 속성을 참으로 지정함
> bReplicates 속성을 true로 설정
2. 네트워크로 복제할 액터의 속성을 키워드로 지정.
> UPROPERTY에 Replicated 키워드 설정
3. GetLifetimeReplicatedProps함수를 오버라이드해서 네트워크로 복제할 속성을 추가.
> #include "Net/UnrealNetwork.h" 헤더 파일 지정
> DOREPLIFETIME 매크로를 사용해 복제할 속성을 명시
이때 Lifetime은 액터 채널의 Lifetime을 의미한다. 즉 활성화된 액터 채널로 전송할 복제될 속성을 의미하는 것
> 액터 리플리케이션 관련 네트워크 데이터는 앞서 배운 컨트롤 채널과 동일한 넷드라이버의 패킷을 사용하지만 논리적으로 컨트롤 채널과 별도로 구분된 액터 채널을 사용한다.
> 가상 함수 OnActorChannelOpen을 오버라이드 해보면, 커넥션에 대해서 번치정보를 해석해서 어떤 리플리케이션을 작업해야 하는지 명령을 받아서 그것을 수행하는 것을 알 수 있다.
프로퍼티 리플리케이션 콜백 함수 호출
프로퍼티 리플리케이션을 한다면 클라이언트에 속성이 복제될 때 콜백 함수가 호출되도록 할 수 있다.
리플리케이션 콜백 함수 구현은 다음과 같다.
1.UPROPERTY의 Replicated 키워드를 ReplicatedUsing 키워드로 변경
2.ReplicatedUsing에 호출할 콜백 함수를 지정.
3. 호출될 콜백 함수는 UFUNCTION으로 선언해야 한다.
콜백 함수를 구현할 때 네이밍은 일반적으로 OnRep_ 의 접두사를 가지는 이름 규칙을 가진다.
콜백 함수는 서버가 아닌 '클라이언트'에서만 호출됨.
서버에서는 호출되지 않기 때문에 호출해야 한다면 명시적 호출을 해야 한다.
콜백 함수를 사용하면 필요한 타이밍에만 해당 로직을 처리할 수 있어 효율적인 구현이 가능하다.
C++ OnRep VS 블루프린트 ReNotify
프로퍼티 리플리케이션은 언리얼 블루프린트에서 ReNotify라는 이름으로 제공한다.
두 방법은 유사하게 동작하지만, 동작 방식에 있어 차이가 있다.
C++는 클라이언트에서만 호출되지만 블루프린트는 서버, 클라이언트에서 호출된다.
C++는 명시적 호출이 가능해서 서버에서 호출이 필요하면 단순히 OnRep_ 함수를 호출하면 되지만, 블루프린트는 명시적 호출이 불가능하다 즉 별도로 호출이 불가능하다
C++은 값이 변경될 때만 호출되지만 블루프린트는 서버는 항시 호출되고 클라이언트는 값이 변경된 때만 호출된다.