UPROPERTY 혹은 UCLASS에서 지정할 수 있는 속성으로, 클라이언트에서 자동으로 로드해야 하는지 여부를 결정NetLoadOnClient 속성을 true로 지정해서 모든 클라이언트가 스스로 스폰
ADXBox를 만들어서 실습해본 결과, 복제되는 것이 아닌 서버, 클라이언트 각자 로드가 되는 것을 확인
UPROPERTY(ReplicatedUsing = OnRep_FunctionName) 키워드를 통해 정의OnRep_ 접두사가 꼭 붙어야 하고, UFUNCTION() 키워드가 붙어야 함| C++ OnRep_함수 | Blueprint RepNotify 함수 |
|---|---|
| 클라이언트에서만 호출 | 서버와 클라이언트 모두에서 호출 |
| 명시적 호출 가능 | 명시적 호출 불가능 |
| 속성 값이 변경될 때만 호출 | 서버는 항시 호출되고, 클라이언트는 속성 값 변경될 때만 호출 |
NetUpdateFrequency보다 낮은 경우, 서버의 성능에 맞춰서 복제됨NetUpdateFrequency 속성 값을 줄이고, 클라이언트 자체에서 속도 기반으로 보간 // DXBox.cpp
ADXBox::ADXBox()
{
SetNetUpdateFrequency(1.f);
NetUpdatePeriod = 1 / GetNetUpdateFrequency();
}
void ADXBox::Tick(float DeltaSeconds)
{
if (HasAuthority())
{
...
}
else
{
AccDeltaSecondSinceReplicated += DeltaSeconds;
const float LerpRatio = FMath::Clamp(AccDeltaSecondSinceReplicated / NetUpdatePeriod, 0.f, 1.f);
const float NextServerRotationYaw = ServerRotationYaw + RotationSpeed * NetUpdatePeriod;
const float EstimatedClientRotationYaw = FMath::Lerp(ServerRotationYaw, NextServerRotationYaw, LerpRatio);
SetActorRotation(FRotator(0.f, EstimatedClientRotationYaw, 0.f));
}
}
void ADXBox::OnRep_ServerRotationYaw()
{
SetActorRotation(FRotator(0.f, ServerRotationYaw, 0.f));
AccDeltaSecondSinceReplicated = 0.f;
}
Viewer에 빙의된 ViewTarget이 레벨을 돌아다니면서 어떤 액터와 연관성이 있는지 확인NetPriority 값이 높은 액터의 데이터를 우선 전달하게 됨NetPriority 값은 순서를 정하는 데만 사용되는 것이지, 만약 대역폭이 널널하다면 모두 다 같은 빈도로 전달하게 됨NetCullDistance 같은 연관성 관련 속성들이 반영됨NetPriority 값 등을 곱해서 계산함ViewTarget이거나 영향을 받은 경우 -> 가장 높은 가중치ViewTarget이 바라보는 방향 및 거리에 따라 가중치를 부여NetPriority 값이 낮은 액터는 다음 서버 틱에서 레플리케이션됨
AActor::SetNetDormancy() : 함수를 호출하여 휴면 상태를 변경하여 액터를 깨울 수 있음AActor::FlushNetDormancy() : 함수를 호출하여 휴면 상태 액터의 변경사항을 복제할 수 있음DORM_Initial로 설정된 액터에서 해당 함수가 호출되면 DORM_DormantAll 상태로 변경됨