The steps are as follows: The PlayerController first Possesses a Character, then after getting into a vehicle, the PlayerController UnPossesses the Character and then Possesses the vehicle. Finally, the PlayerController sets the owner of the Character to the vehicle, all within one frame.
The problem arises when multiple clients are connected, and the second connected client attempts to Possess the Character during the network synchronization process. At this point, the RemoteRole of the Character is not being properly synchronized for the second connection, resulting in the Role of the Character on the second client remaining as Autonomous Proxy when it should be Simulated Proxy.
The root cause of the problem is the introduction of the PushModel, where the RemoteRole is not handled correctly. When the Character is initially synchronized by the first connected client, the RemoteRole is consistently set as Simulated Proxy. As a result, there is no recorded change for the RemoteRole, especially because the dirty flag is cleared after the comparison with the first client's data:
As a consequence, when the second client attempts to synchronize the Character, it fails to detect the dirty flag for RemoteRole, and thus, does not perform the RemoteRole attribute comparison. This leads to the absence of marking the dirty flag for the second client.
Moreover, the issue becomes more complex when more clients are involved, as it can trigger other mysterious bugs, but the root cause remains the situation described above.
When PushModel is not enabled, there is a bForceCompare to ensure that the second client performs its own attribute comparison instead of using the comparison results from the first client. However, when PushModel is introduced, bForceCompare seems to have no effect, as it takes effect earlier in the UpdateChangelistMgr function, while PushModel's effect is at a lower level in the logic.
There's no existing public thread on this issue, so head over to Questions & Answers just mention UE-190825 in the post.