[ 짧은 메모 ]
RepLayOut.cpp - 1525 Comment
Most replication conditions don't actually effect whether or not we compare properties, because we share comparisons across connections, and typically only want to do one comparison per frame for all connections, when possible.
This means that we will end up performing the comparison, ignoring replication conditions, even if we might not have to send the property to any connections on a given frame frame.
COND_InitialOnly is special, though. In theory, COND_InitialOnly properties should only ever be compared a single time, the first time an object is ever replicated, so it's a waste to compare them every frame.
However, in practice, there are a number of cases where an object can be replicated multiple times, and still have its bNetInitial flag set, because of how we handle multiple connections.
E.G., it may be the first time an Object is replicating to a Specific Connection, and we would consider that an Initial Replication, even though the object may have replicated previously.
If the property's value has changed, and the object was replicated again BEFORE a new Net Initial replication occurs, AND the object is a Push Model Property, then we will end up clearing the fact that the property was ever changed, and the new value will never be sent to any connections.
To get around that, if we detect that this is an Initial Replication, and we have Initial Only properties, we will consider them dirty.
대부분의 복제 조건은 실제로 프로퍼티 비교 여부에 영향을 미치지 않습니다. 왜냐하면 우리는 연결 간에 비교를 공유하고, 일반적으로 가능한 경우 모든 연결에 대해 프레임당 한 번만 비교를 수행하려고 하기 때문입니다. 즉, 특정 프레임 프레임에서 프로퍼티를 어떤 연결에도 전송할 필요가 없더라도 복제 조건을 무시하고 비교를 수행하게 됩니다. 하지만 COND_InitialOnly는 특별합니다. 이론적으로 COND_InitialOnly 프로퍼티는 객체가 처음 리플리케이트될 때 한 번만 비교해야 하므로 매 프레임마다 비교하는 것은 낭비입니다. 그러나 실제로는 여러 연결을 처리하는 방식 때문에 오브젝트가 여러 번 리플리케이트되고도 bNetInitial 플래그가 설정되어 있는 경우가 많이 있습니다. 예를 들어, 오브젝트가 특정 연결에 처음 복제되는 경우 이전에 복제된 적이 있더라도 이를 초기 리플리케이션으로 간주할 수 있습니다. 프로퍼티 값이 변경되었고 새로운 순 초기 복제가 발생하기 전에 오브젝트가 다시 리플리케이트되었으며 해당 오브젝트가 푸시 모델 프로퍼티인 경우, 프로퍼티가 변경되었다는 사실이 지워지고 새 값이 어떤 연결에도 전송되지 않게 됩니다. 이 문제를 해결하기 위해 이니셜 리플리케이션이고 이니셜 전용 프로퍼티가 있는 것을 감지하면 더티 프로퍼티로 간주합니다.
- RepLayout.cpp
RepFlags의 값을 기반으로 ConditionMap을 만듦.

- DataChannel.cpp

ReplicateSubobjects : Replicate UObject
- RepLayout.h
Property Replication에서 COND_OwnerOnly같은 조건(Conditional Property Replication)을 거르는 코드 찾아보기
일단 이 부분은 ActorChannel에서 ReplicateActor()내에서 ActorReplicator->ReplicateProperties() 내에서 호출하는 부분이 존재한다. (Subobject, Component, Property Replication을 담당하는 부분이 모여있다)
SendProperties()의 주석

ConditionMap에 설정했던 Condition들이 저장되어 있고, FRepLayout::FilterChangeList()에서 필터링한다고 한다.
그런데 찾아가보면 코드 의미를 알기가 매우 매우 힘들다.

정말 느낌만 기록하자면, InactiveParents에는 상위 함수인 ReplicateProperties() 에서 FSendingRepState* RepState가 넘어오는데, FilterChangeList() 이전에 호출되는 FRepLayOut::RebuildConditionalProperties() 내에서 FReplicationFlag& RepFlag에 있는 ConditionMap 정보를 기반으로 RepState에 값을 옮긴 뒤, 이 RepState에 저장된 Condition 정보가 결국 InactiveParents가 되는 것이다.
그래서 이 값을 기반으로 Changelist를 순회하며 OutInactiveProperties, OutActiveProperties에 따로 따로 나뉘어서 추가한 뒤, 참조로 받아왔으므로 필터링하게 되는 것이다.
이후에 Merge를 통해 Changed 라는 변수로 다 병합되면서 이걸 요리조리 넘기면서 전송하게될 부분을 FNetBitWriter& Writer에다가 기록하게 된다.
거의 가장 로우레벨인 코드부분이라서 용어도 하이레벨과 다르고 코드 하나하나 의미를 알기가 힘들다.
대략 무슨 일이 일어나는지 작성된 엔진코드 주석을 기반으로 이해하는게 나을듯.
'UE5 > Network' 카테고리의 다른 글
[UE5] Animation Update in Server, Server side Rewind (0) | 2024.10.06 |
---|---|
[UE5] SetPawn() : OnPossess in Client (0) | 2024.09.28 |
[UE5] Replication Graph Deep Dive (0) | 2024.08.29 |
Multiplayer in UE : How to Understand Network Replication (0) | 2024.08.29 |
[UE5] About HUD After Seamless Travel (1) | 2024.08.22 |