We’re evaluating using Mover with the Network Prediction backend for our project and seeing even stationary actor replication saturate the network pretty quickly where the UCharacterMovementComponent doesn’t exhibit this behavior.
We’ve done a fair amount of work to cut down on the number of bits sent when replicating our sync states (FMoverDefaultSyncState included) to the point where there isn’t a lot of fat left to cut from individual actors.
I’ve traced through UNetDriver.cpp into UActorChannel::ReplicateActor for both CMC and Mover. A stationary CMC-backed character ends up bWroteSomethingImportant false and a stationary Mover actor comes out true due to FReplicationProxy::Identical (code snippets at bottom)
I’m curious about the reasoning for FReplicationProxy::Identical comparing the CachedPendingFrame vs comparing the underlying data. It must save CPU cycles on the authority machine, but that’s a huge cost in terms of bits over the network.
Does it seem reasonable to create an FReplicationProxy::IdenticalFunc/Predicate analogous to FReplicationProxy::NetSerializeFunc, assign it in NetworkPredictionWorldManager::Bind functions, then call it from FReplicationProxy::Identical the same way that FReplicationProxy::NetSerialize calls its NetSerializeFunc?
bool FReplicationProxy::Identical(const FReplicationProxy* Other, uint32 PortFlags) const
{
return (CachedPendingFrame == Other->CachedPendingFrame);
}
----
class UMoverNetworkPredictionLiaisonComponent : public UNetworkPredictionComponent, public IMoverBackendLiaisonInterface
----
class UNetworkPredictionComponent : public UActorComponent
...
UPROPERTY(Replicated, transient)
FReplicationProxy ReplicationProxy_Autonomous;
UPROPERTY(Replicated, transient)
FReplicationProxy ReplicationProxy_Simulated;
UPROPERTY(Replicated, transient)
FReplicationProxy ReplicationProxy_Replay;