게임 개발 메모장
[ UE5 ] 액터 리플리케이션 본문
- 특정 플레이어에 속한 액터의 정보를 네트워크 내
다른 플레이어에게 복제하는 작업이다.
- 클라이언트 - 서버 모델에서는 대부분 서버에서 클라이언트로 전달한다.
( 언리얼 엔진이 사용하는 클라이언트 서버 모델에서는 서버만이
Authority를 가지기 때문이다. )
- 리플리케이션의 방법에는 크게 두 가지가 있는데
1) 프로퍼티 리플리케이션
2) RPC(Remote Procedure Call) 이있다.
기본 액터의 로딩
리플리케이션 작업이 진행 되기 위해서는 네트워크로 데이터를 전송해줘야 된다.
사용자마다 다양한 디바이스와 네트워크 환경에 변수가 있기 때문에
우리는 항상 이것을 정확하게 예측하는 것은 어렵다.
그렇기 때문에 최악의 경우를 언제나 가정해야 되는데,
리플리케이션 작업에서 가장 중요한 것은 데이터 전송량을 최소화 하는 것이라고 볼 수 있다.
- 클라이언트가 초기화 될 때 모든 액터 정보를 서버로부터 받는 것은 비효율적이다.
- 따라서 기본 배경에 관련된 액터는 맵을 통해 스스로 로딩하도록 설계 되어있다.
- 고정으로 제공하는 액터와 동적으로 생성하는 액터
1) 고정으로 제공하는 액터의 예 : 레벨을 구성하는 배경 액터
: 이들은 앞으로 크게 변할 일이 없기 때문에 클라이언트에서
직접 초기 값을 로딩하는 것이 효율적이다.
2) 동적으로 생성하는 액터의 예 ; 플레이어 컨트롤러와 폰
: 고정 액터에 대해 NetLoadOnClient 속성을 체크해야 한다. ( true 가 기본 값 이다.)
이 값이 true 로 성정된 액터들은 서버와 통신 없이 클라이언트가 초기화 될 때
자체적으로 로딩함으로써 서버에서 콘텐츠를 배포한 것과 동일한 효과를 효과적으로
얻어낼 수가 있게 되겠다.
액터 리플리케이션 설정
* 고정으로 보여지는 액터 중, 게임 중 변경 사항이 발생하는
액터는 그 값을 전달해야 함.
* 네트워크 데이터를 최소화 하기 위해서 변경 사항을 보내기 보다,
변경을 유발한 속성 값을 전달함.
* 이를 위해 액터의 Replicates 옵션을 체크 해야 함.
: 액터의 상태라고 하는데 이러한 속성값을 전달하기 위해서는
우선 전달할 액터의 Replicates라는 속성 값을 true 로 지정해 줘야 한다.
만일 이 속성의 기본 값이 참으로 지정된다면 우리가 구현하는데는
편리 하겠지만 모든 액터의 속성값이 네트워크로 전달 되기 때문에
네트워크 부하가 심해져서 정작 중요한 데이터를 전달하지 못할 수가 있다.
따라서 이러한 속성값의 변화에 따라서 우리가 원하는 동작을 스스로
수행할 수 있도록 데이터 기반으로 설계하는 것이 무엇보다 중요하다.
리플리케이션 프로퍼티(속성) 의 지정
1. 액터의 리플리케이션 속성을 참으로 지정함
- bReplicates 속성을 true로 설정
2. 네트워크로 복제할 액터의 속성을 키워드로 지정
- UPROPERTY에 Replicated 키워드 설정
3. GetLifetimeReplicatedProps 함수에 네트워크로 복제할 속성을 추가.
- #include "Net/UnrealNetwork.h" 헤더 파일 지정
- DOREPLIFETIME 매크로를 사용해 복제할 속성을 명시
Lifetime은 액터 채널의 Lifetime을 의미함
즉, 활성화된 액터 채널로 전송할 복제될 속성을 의미함.
예시
1) 생성자로 가서 bReplicates라고 하는 속성을 true 값으로 변경 해줘야 한다.
2) 그리고 나서 우리가 복제할 속성에 대해서 멤버 변수로 선언해주면 된다.
UPROPERTY 매크로를 붙여주면 언리얼 오브젝트의 속성이 되지만
이때는 Replicated 라고 키워드를 붙여줘야지
이것이 자동으로 언리얼 엔진의 네트워크 기능을
사용해서 다른 클라이언트로 복제가 된다.
3) 그리고 라이프 타임 함수를 선언해줘야한다.
함수에 DOREPLIFETIME 매크로를 추가해 주려면 macro를 위해서
먼저 #include "Net/UnrealNetwork.h" 해줘야한다.
여기에다가 클래스 이름 넣어주고 속성 Property를 넣어주면
기본적인 Property Replication 기능을 구현할 수가 있다.
Replicated 속성을 사용하기 위해서는 GetLifetimeReplicatedProps() 함수에
Replicated할 속성값을 DOREPLIFETIME 에등록해줘야만 정상적으로 빌드를 할 수 있다.
서버쪽에서 우리가 전송할 데이터를 변경해야한다.
서버 액터에서 서버 로테이션 값을 어떻게 변경할지를 지정해줘야된다.
서버에서 주도적으로 변경해야 되기 때문에 HasAuthority 라고 하는 함수를 호출해
클라이언트와 서버 코드를 분리를 해줘야 한다.
현재 리슨 서버 모델이기 때문에 하나의 코드,
하나의 로직에서 두 가지를 분리해줘야 되는 번거로움이 있다.
만약 우리가 Dedicated 서버로 가게 되면 Dedicated 서버는 클라이언트 로직을
전혀 고려할 필요가 없기 때문에 이런 함수를 굳이 사용하지 않고 서버 로직만
구현해주면 된다.
그래서 사실 Dedicated 서버 구현이 Listen 서버 구현보다 훨씬 더 편리하다.
리플리케이션 콜백 함수 호출
매 Tick마다 서버로부터 받은 속성을 업데이트 해주면 매 Frame 마다
실행되는 Tick의 코드가 방대해지고 상대방의 네트워크 전송 주기가
만일 Tick 보다 느리다면은 데이터를 받기 전에 Tick이 몇 번 호출되어 있어서
비효율적으로 동작할 수가 있다.
딱 필요한 만큼만 효율적으로 작업할 수 있도록 해당 속성에 콜백함수를 등록해
이를 호출하도록 구조를 변경 해야한다.
이를 위해 먼저 기존 속성에 선언한 Replicated 키워드를 우선 제거해주고
대신에 Replicated Using 이라는 키워드로 변경을 해줘야 된다.
그리고 여기에는 Property 속성이 변경될 때마다 호출될 콜백 함수를 지정해주면 된다.
이 호출될 콜백 함수는 언리얼 엔진에서 파악할 수 있도록
UFUNCTION으로 선언해주면 된다.
보통 언리얼 엔진에서는 프로퍼티 리플리케이션을 사용하는 콜백 함수에는
OnRep_이라고 하는 접두사를 붙인다.
이러한 콜백 함수는 서버가 아닌 클라이언트에서만 자동으로 호출된다는 특징
1. 클라이언트에 속성이 복제될 때 콜백 함수가 호출되도록 구현한다.
- UPROPERTY의 Replicated 키워드를 ReplicatedUsing 키워드로 변경
- ReplicatedUsing 에 호출할 콜백 함수를 지정
- 호출될 콜백 함수는 UFUNCTION으로 선언해야 한다.
2. 콜백 함수의 구현
- 일반적으로 OnRep_의 접두사를 가지는 이름 규칙을 가짐
- 콜백 함수는 서버가 아닌 클라이언트에서만 호출됨
-> 필요한 타이밍에만 해당로직을 처리할 수 있어 효율적인 구현이 가능함.
매 틱마다 발생했던 이 돌리는 함수가 이 Callback 함수로 옮겨지면서
Callback 함수가 Tick보다 더 적게 돌아가는 경우에는
보다 효율적으로 logic을 처리할 수가 있게 된다.
딱 필요한 만큼만 우리가 호출할 수가 있기 때문이다.
이 액터 채널 오픈 포탈이 열린 이후에 리플리케이션 작업이 채널을 통해서 진행된다.
https://docs.unrealengine.com/4.27/ko/InteractiveExperiences/Networking/Actors/Properties/
'언리얼 엔진 > Network' 카테고리의 다른 글
[ UE5 ] RPC (1) | 2024.01.05 |
---|---|
[ UE5 ] 캐릭터 공격 구현 예시 (0) | 2023.12.30 |
[ UE5 ] 커넥션과 오너십 (0) | 2023.12.25 |
[ UE5 ] 게임 모드와 로그인 (0) | 2023.12.25 |
[ UE5 ] 언리얼 네트워크 멀티 플레이어 프레임워크 (0) | 2023.12.24 |