Networking for Multiplayer and Unreal Physics desync.

I’ve recently beem working on a networked game and ran into some troubles with replication on physics objects. The image below was with an object with replicate movement off:
Coins_S.PNG.jpg

Even with replicate movement on I get some desync (its hard to tell in the image but its subtle) and other issues (like characters glitching when they touch the object or disappearing).
Coins_S.PNG.jpg

Am I doing replication for physics objects incorrectly? Ideally for these types of objects i would like physics to only be generated from the server.


// Fill out your copyright notice in the Description page of Project Settings.
**//@CoinPickup.h**
#pragma once

#include "CoreMinimal.h"
#include "Pickup.h"
#include "CoinPickup.generated.h"

/**
 * 
 */
UCLASS()
class CPPTEST_API ACoinPickup : public APickup
{
    GENERATED_BODY()
public:
    //set default values for constructor
    ACoinPickup();




};

// Fill out your copyright notice in the Description page of Project Settings.
**//@CoinPickup.cpp**
#include "CoinPickup.h"

ACoinPickup::ACoinPickup()
{
    //keep physics synced from client to server
    bReplicateMovement = true;
    //this coponent is physics enabled and should move
    GetStaticMeshComponent()->SetMobility(EComponentMobility::Movable);
    GetStaticMeshComponent()->SetSimulatePhysics(true);
}


// Fill out your copyright notice in the Description page of Project Settings.
**//@Pickup.h**
#pragma once

#include "CoreMinimal.h"
#include "Engine/StaticMeshActor.h"
#include "Pickup.generated.h"

/**
 * 
 */
UCLASS()
class CPPTEST_API APickup : public AStaticMeshActor
{
    GENERATED_BODY()

public:
    //Set default values
    APickup();

    //Code for networking
    void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;

    //Returns wether or not the pickup is activated
    UFUNCTION(BlueprintPure, Category = "Pickup")
    bool IsActive();

    //Allows other classes to safely change the pickup's activation state
    UFUNCTION(BlueprintCallable, Category = "Pickup")
    void SetActive(bool newPickupState);


protected:


    //True when pickup can be activated
    UPROPERTY(ReplicatedUsing = OnRep_IsActive)
    bool bIsActive;

    //This is called whenever bIsActive is updated
    UFUNCTION()
    virtual void OnRep_IsActive();
};    
// Fill out your copyright notice in the Description page of Project Settings.
**//@Pickup.cpp**
#include "Pickup.h"
#include "Net/UnrealNetwork.h"



APickup::APickup()
{
    //Tells UE4 to replicate actor
    bReplicates = true;

    //Pickups will never tick
    PrimaryActorTick.bCanEverTick = false;

    if (Role = ROLE_Authority)
    {
        bIsActive = true;
    }
}

void APickup::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
    Super::GetLifetimeReplicatedProps(OutLifetimeProps);

    DOREPLIFETIME(APickup, bIsActive);
}

void APickup::OnRep_IsActive()
{

}

void APickup::SetActive(bool newPickupState)
{
    if (Role == ROLE_Authority)
    {
        bIsActive = newPickupState;
    }
}

bool APickup::IsActive()
{
    return bIsActive;
}

Physics does not play well with the network. Typically it is reserved for visual-only effects like destruction etc, or for vehicles (but they are usually client-authoritative and only used because people don’t bother to write their own proper vehicle movement components - but hey, they give me a job…).

Physics replication is therefore a sore subject. To fix desync, you have a couple of initial options:

  1. Do not use replicated movement, and instead send the replicated movement data to all clients via a Multicast RPC at a frequent interval. Have clients update their object with the most recent state when they receive it, and implement some smoothing for the rendered object if you can. This will give the most fluid results and would be my recommend approach if you absolutely need to use physics.

  2. Use replicated movement, but only simulate physics on the server and override the default replicated movement behaviour to NOT copy the simulate physics flag to clients. This will result in frequent snapping, but requires less work.

  3. Don’t use physics, and redesign the objects behaviour if it’s not essential to the game. Coins dropping for example can be easily simulated locally without any need to real collision processing or even movement. Some stuff can be done with simple curves.

I am currently putting together a generic network movement framework that will provide some more out-of-the-box solutions including some of the above, but it’s not quite ready yet.

2 Likes

Ah, alright. Thanks for the reply and i’ll give those a whirl!

Interesting. Please elaborate. :slight_smile:

I’ll make a post soon(ish) - but I will provide more details when I can.

Hi TheJamsh,

I am currently trying to implement this solution, but I am having trouble with it. I’m a novice when it comes to network programming (especially network programming in UE4), so I was hoping you could give me some pointers on how to do this.