[Iris] Protocol mismatch with replicated component that has an RPC and replicated state

Hello,

Since upgrading to 5.6, we’re seeing an issue where client side we end up with a protocol mismatch. The reason being that the actor in question generates an additional fragment for an actor component that has bReplicates set to false client side even though it’s clearly set to true both in native and further verified it’s set on the actor BP that it belongs to. The actor both replicates state and has a single RPC. The code generating the additional fragment is in Actor::RegisterReplicationFragments:

if (ActorComp->HasAnyFlags(RF_DefaultSubObject) || ActorComp->IsDefaultSubobject())

{

if (!ActorComp->GetIsReplicated() || ActorComp->GetReplicationCondition() == COND_Never)

{

// Register RPC functions for not replicated default subobjects

ActorComp->RegisterReplicationFragments(Context, EFragmentRegistrationFlags::RegisterRPCsOnly);

}

}

We’ve been looking into this for a couple days with no luck. I don’t understand how only specific instances of the BP actor could have bReplicates set to false, the property replicates but at the time we find deserialize the actor out of the map it should use what is in the CDO right? Any thoughts on this would be very much appreciated.

Thanks,

Nick

Hi,

To get a better idea of the problem, I have a couple questions.

First, you mentioned that the component has bReplicates set to false on the client, despite this being set to true for the class. Where is this being set to true, in the component’s constructor or somewhere else?

Also, is the component and its owning actor placed in the map, or is it being spawned dynamically on the server?

Finally, are you able to place a data breakpoint on the component’s bReplicates, in order to see where it is being set back to false?

Thanks,

Alex

I’ve got a full repro purely in BP:

  1. Need a replicated component with an RPC (I used multicast but I don’t think it matters)
  2. Need a replicated actor to attach this component to marked as “Dormant All”
  3. Place the actor in the map and spawn the player in outside of it’s net relevancy range
  4. Bring the actor into relevancy range
  5. Back out of relevancy range
  6. Bring the actor back into relevancy range
  7. Observe the protocol mismatch on the client

…note that the 2 most important requirements here are the RPC and “dormant all” dormancy. I can’t chase this thread any further on my own as it’s already taken much more time than anticipated, but it would seem that the issue only repros in the case that the server sends initial state to the client purely due to net relevancy when the actor in question has yet had reason to replicate anything. This theory was strengthened further by adding a “FlushNetDormancy” to the actor on BeginPlay and observing that the issue was no longer reproducible.

Hey Alex,

It was set on the owning actor’s BP (Component Replicates), but I’ve since set it in native in the component’s constructor as well and that has had no impact. These are net startup actors and there are a lot of them, with the repro being inconsistent I can’t place a data breakpoint since there’s no way to know one(s) will have the issue on any particular run.

Can you explain what’s going on in that code above? Why are we registering additional actor fragments for non-replicated components that have RPCs?

Thanks,

Nick

Hi,

It is a supported operation to call a RPC on a default subobject for a replicated actor, even if that component/subobject itself isn’t set to replicate. In Iris, we register the component’s replication fragment with the “RegisterRPCsOnly” flag in order to support this use case.

We did run into a similar issue previously, which was due to the blueprint’s construction script adding a replicated component. You mentioned that the component is now set to replicate in its native constructor, but is the component or owning actor’s BP doing any sort of initialization in its construction script?

Thanks,

Alex

No construction script initialization in this case.

However, I have found the repro.

  1. Move into net relevancy range of the net startup actor
  2. Move out of net relevancy range
  3. Move back into net relevancy range and observe that we hit the ensure mentioned

…when stopping replication for the actor in question on the client, it would appear that something is mutating/clearing the bReplicates member of that component on that net startup actor.

Please let me know if you’re able to repro on your side.

Thanks,

Nick

Hi,

Thank you for the additional information, but I’ve unfortunately still been unable to reproduce the protocol mismatch so far. I apologize that this issue has taken longer than anticipated, and I will continue working on getting a repro together.

In the meanwhile, something else worth trying is setting these placed in the map actors as “Dormant Initial,” as “Dormant All” is more intended for dynamically spawned actors or initially dormant actors that have been previously woken up.

Thanks,

Alex