티스토리 뷰

반응형

Rpc다음으로 다음은 Replicated에 대해 설명을 하자면 

각 액터에는 Replicated 지정자 를 포함하는 모든 프로퍼티 목록이 유지됩니다. 서버는 리플리케이트된 프로퍼티의 값이 변할 때마다 각 클라이언트에 업데이트를 전송하며, 클라이언트는 액터의 로컬 버전에 적용합니다. 이 업데이트는 서버에서만 받으며, 클라이언트는 프로퍼티 업데이트를 서버나 다른 클라이언트로 절대 전송하지 않습니다. (Unreal 문서펌.)

 

프로퍼티 리플리케이션

액터 프로퍼티 리플리케이션 방법에 대한 상세 정보입니다.

docs.unrealengine.com

해당문서로 들어가 경고문을 보자면 다음과 같이 써있습니다.

클라이언트에서 리플리케이트된 변수의 값을 바꾸는 것은 추천하지 않습니다. 다음 번 서버가 변화를 감지하고 업데이트를 전송할 때까지 서버의 값과 달라지게 됩니다. 그 프로퍼티의 서버 사본이 값을 자주 변경하지 않는다면, 클라이언트가 보정을 받을 때까지 오랜 시간이 걸릴 수 있습니다.

라고 써있는것을 확인할수 있는데 진짜로 시험해본결과 값이 자기맘대로 바뀐다.

(만약 자신이 연속공격을 구현하는데 해당구현의 AttackInex(예를 든 예측의 변수)라는 Replicated로 생성한 변수를 만약 NetMulticast, Client로 초기화를 하는경우 값이 클라와 서버측의 값이 클라에서는 실제값이 0이지만, 서버와 다른소유의 클라에서는 2이라고 받는다. <실제로 해봐서 쓰는글.> 그러면 완전히 다른 상황이 발생하게 된다.)

 

그래서 항상 Replicated로 선언된 값들은 무조건 Server호출 함수로 값을 변경해줘야 잘 안착이 된다.

그림으로 설명하면 이런식으로 전달인것이다.

무조건 Server가 이해를 해야 변경된 값으로 전달이 되는것이다.

실제로 Replicated를 사용하기 위해서는 변수를 다음과 같이 선언해줍니다. (귀하는 EFaction이라는 역할을 지정하는 변수를 생성하여 사용할려고 함.) UPROPERTY(Replicated)로 선언해주면 된다. 그리고 해당 폰의 통신을 받기 위해서는 생성자에서 SetReplicates(true);로 호출을 해줘야한다. (이 함수는 내가 소유한 Pawn을 리플리케이티드를 시킬건지를 정하는 함수이다.<생성자에서 말고 Bp로 자손으로 만들어서 에디터에서 true로 변경해도 상관은 없다.>) 

.h

UENUM(BlueprintType)
enum class EFaction : uint8
{
	Enemy            UMETA(DisplayName = "Enemy"),
	Friendly         UMETA(DisplayName = "Friendly"),
	Neutral          UMETA(DisplayName = "Neutral")
};

//Replicated//
UPROPERTY(Replicated)
EFaction Faction = EFaction::Neutral;

.cpp

ACharacterBase::ACharacterBase()
{
 	// Set this character to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = false;
    
    	SetReplicates(true);
}

 

실제로 코드로 표현하려면 먼저 Include헤더와 가상함수이다.

먼저 가상함수는 GetLifetimeReplicatedProps라는 가상함수가 있는데 이 함수같은경우에는 Replicated선언된 변수가 어떤 형식으로 받아서 전달하는지의 필요한 함수이다. 

 

.h

virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;

.cpp

void ACharacterBase::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
	Super::GetLifetimeReplicatedProps(OutLifetimeProps);

	DOREPLIFETIME(ACharacterBase, Faction);
}

(함수를 생성한 후에는 DOREPLIFETIME라는 매크로를 통해서 어떤 형식의 전달을 사용할지를 알려줘야한다. <다른 형식이라하면 대표적으로는 DOREPLIFETIME_CONDITION 등 여러가지가 있지만 다음에 사용방법을 사용할 예정.>)

 

그리고 이 매크로들을 사용하기 위해서는 아래와 같이 인클루드를 시켜줘야 사용할수 있다. (아마 해당 인클루드를 추가 안할경우 에러가 뜨는걸로 알고 있다.)

 

.cpp

#include "Net/UnrealNetwork.h"

그리고 이제 진짜로 값이 전달이 안되는지 확인 하기위해 일반함수, Server함수를 생성하여 호출하게 만들것이다.

.h

//일반 함수//
UFUNCTION(BlueprintCallable)
void SetFaction(EFaction InFaction);

//Server 함수//
UFUNCTION(Server, Reliable, WithValidation, BlueprintCallable)
void Server_SetFaction(EFaction InFaction);

.cpp

void ACharacterBase::SetFaction(EFaction InFaction)
{
	Faction = InFaction;
	GEngine->AddOnScreenDebugMessage(-1, 3.f, FColor::Yellow, "Call Basic SetFaction");
}

void ACharacterBase::Server_SetFaction_Implementation(EFaction InFaction)
{
	Faction = InFaction;
	GEngine->AddOnScreenDebugMessage(-1, 3.f, FColor::Yellow, "Call Server SetFaction");
}

bool ACharacterBase::Server_SetFaction_Validate(EFaction InFaction)
{
	return true;
}

이런식으로 함수가 호출되는지 디버그메시지를 띄워 확인하게 합니다.

그리고 각 역할은 Server = Neutral, Client1 = Enemy, Client2 = Neutral 이런식으로 역할을 줬습니다.

 

너무 빠르니 0.75배로 보는거 추천드립니다.

영상에서 보이듯이 각 액터들 머리위에 자신의 역할이 뜨는걸보아 적용이 되는걸 볼수 있습니다.

반응형
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2025/08   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
글 보관함