Notice
Recent Posts
Recent Comments
Link
«   2025/03   »
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
Tags
more
Archives
Today
Total
관리 메뉴

UnrealEngineer

[ UnrealEngine5 ] 액터의 리플리케이션 본문

언리얼엔진5

[ UnrealEngine5 ] 액터의 리플리케이션

UnrealEngineer 2024. 8. 23. 15:55

- 액터의 리플리케이션(Replication) 정의

리플리케이션 : 서버가 클라이언트에게 변경된 내용을 변수, 함수로 복제해주는 것

 

사용자의 환경이 각각 다 다르기 때문에 네트워크 통신(데이터 전송)을 최소화 하는 것이 중요하다.

네트워크 통신을 최소화하고 유효성 검사만을 통해 클라이언트 스스로 로딩하는 것이 효율적이다.

 

- 고정 액터 : 레벨을 구성하는 배경 액터

- 동적 액터 : 플레이어컨트롤러, 폰

 

동적 액터와 고정 액터를 구분하기 위해 언리얼엔진은 모든 액터에는 NetLoadOnClient라는 속성이 있다. (기본값 true)

이를 통해 네트워크와의 통신없이 클라이언트의 자체적인 로딩을 통해 효과적으로 구현할 수 있다.

 

서버의 컨텐츠 변경 사항을 모두 보내기 보다는

변경을 일으키는 속성 값의 변경치를 전달한다.

Replicates = true

하지만, Replicates = true로 설정하면 모든 액터의 속성값이 네트워크로 전달되기 때문에 비효율적이다.

 

그러므로 속성값의 변화에 따라서 원하는 동작을 스스로 수행할 수 있도록 데이터 기반으로 설계하는 것이 중요하다.

 


 

- 액터의 리플리케이션 방법

1. 액터의 리플리케이션 속성을 true로 지정

※ bReplicates = true;

 

2. 네트워크로 복제할 액터의 속성을 키워드로 지정

※ UPROPERTY에 Replicated 키워드 설정

 

3. GetLifetimeReplicatedProps 함수에 복제할 속성을 추가

< LifeTime은 액터 채널의 LifeTime을 의미한다. 즉, 활성화된 액터 채널로 전송할 복제될 속성을 의미함 >

※ #include "Net/UnrealNetwork.h"

※ DOLEPLIFETIME 매크로를 사용해 복제할 속성을 명시한다.

 

public:	
	// 서버에서 복제될 프로퍼티
	UPROPERTY(Replicated)
	float ServerRotationYaw;

public:	
	virtual void Tick(float DeltaTime) override;

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

 

#include "Net/UnrealNetwork.h"

void ABCPortal::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	// 서버에서 실행
	if(HasAuthority())
	{
		AddActorLocalRotation(FRotator(0.0f, RotationRate * DeltaTime, 0.0f));

		// 서버의 회전값을 저장해준다.
		ServerRotationYaw = RootComponent->GetComponentRotation().Yaw;
	}
	else
	{
		// 클라이언트인 경우
		FRotator NewRotator = RootComponent->GetComponentRotation();

		NewRotator.Yaw = ServerRotationYaw;

		RootComponent->SetWorldRotation(NewRotator);
	}
}

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

	DOREPLIFETIME(ABCPortal, ServerRotationYaw);
}

 

매 틱마다 서버에서 프로퍼티의 변경이 일어날때마다 네트워크로 데이터 전송이 일어난다.

환경이 좋지 못한 클라이언트의 경우에는 서버와의 딜레이가 발생할 수 있고 많은 데이터의 전송은 원활한 환경구성의 저해 요소이다.


 

이러한 경우를 방지하기 위해서 콜백함수 구현을 통한 동기화 방법이 존재한다.

리플리케이션 콜백 함수 호출

1. 클라이언트에 속성이 복제될때 콜백 함수가 호출되도록 구현한다.

○ UPROPERTY의 Replicated 키워드를 ReplicatedUsing = OnRep_함수 형태의 키워드로 변경

○ ReplicatedUsing에 호출될 콜백 함수는 UFUNCTION 형태로 선언

 

2. 콜백 함수의 구현

○ OnRep_ 접두사를 붙여서 선언한다.

○ 콜백 함수는 서버가 아닌 '클라이언트'에서만 호출된다.

 

public:	
	ABCPortal();

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	TObjectPtr<class UStaticMeshComponent> StaticMeshComponent;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	TObjectPtr<class UBoxComponent> BoxComponent;

	// 서버에서 복제될 프로퍼티
	UPROPERTY(ReplicatedUsing = OnRep_ServerRotationYaw)
	float ServerRotationYaw;

	UPROPERTY()
	float RotationRate = 30.0f;

	// 콜백함수 선언
	UFUNCTION()
	void OnRep_ServerRotationYaw();

protected:
	virtual void BeginPlay() override;

public:	
	virtual void Tick(float DeltaTime) override;

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

 

void ABCPortal::OnRep_ServerRotationYaw()
{
	BC_LOG(LogBCNetwork, Log, TEXT("Yaw : %f"), ServerRotationYaw);

	// 클라이언트인 경우
	FRotator NewRotator = RootComponent->GetComponentRotation();

	NewRotator.Yaw = ServerRotationYaw;

	RootComponent->SetWorldRotation(NewRotator);
}

void ABCPortal::BeginPlay()
{
	Super::BeginPlay();
	
}

void ABCPortal::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	// 서버에서 실행
	if(HasAuthority())
	{
		AddActorLocalRotation(FRotator(0.0f, RotationRate * DeltaTime, 0.0f));

		// 서버의 회전값을 저장해준다.
		ServerRotationYaw = RootComponent->GetComponentRotation().Yaw;
	}
}

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

	DOREPLIFETIME(ABCPortal, ServerRotationYaw);
}

 

리플리케이션 함수는!

값이 변경될때만 호출해서 클라이언트에 복제해준다.

(서버에서 계속 호출되더라도 값의 변경이 없으면 복제는 일어나지 않는다.)


- 블루프린트와 C++ 네트워크