Steps to Reproduce
Create an Actor with a Static Mesh Component (like a cube) as root, let’s call it Bob. Enable physics simulation in the component and replication in the actor ( bReplicates
, bReplicateMovement
and bAlwaysRelevant
). Create a new default level, place Bob a bit above the ground and save it as TestLevel. Run the game and execute the command open TestLevel?listen
. Wait for Bob to touch the ground and then sleep. Run another instance of the game and execute the command open 127.0.0.1
.
Result: You’ll see Bob floating above the ground, never falling. Approaching it snaps it to the correct position.
Expected result: You should see Bob sleeping on the ground.
Probable Cause
While debugging, I noticed that while you see Bob floating, its internal PhysX body is actually in the right place. The client receives the correct physics state in AActor::PostNetReceivePhysicState()
and applies it successfully. However, Bob’s sleeping state is also applied, never giving the Primitive Component the chance to synchronize to the PhysX body. You can see that approaching Bob with the DefaultPawn awakens it, letting it finally sync.
Possible Solution
Calling RootPrimComp->SyncComponentToRBPhysics()
right after applying the received physics state in AActor::PostNetReceivePhysicState()
(ActorReplication.cpp) fixes it.