Files
ProjectEleri/Plugins/StevesUEHelpers/Source/StevesUEHelpers/Private/StevesReplicatedPhysicsActor.cpp

75 lines
2.7 KiB
C++

// Copyright Steve Streeting
// Licensed under the MIT License (see License.txt)
#include "StevesReplicatedPhysicsActor.h"
#include "Runtime/Launch/Resources/Version.h"
#include "Components/StaticMeshComponent.h"
#include "Engine/World.h"
AStevesReplicatedPhysicsActor::AStevesReplicatedPhysicsActor(const FObjectInitializer& ObjInit)
{
PrimaryActorTick.bCanEverTick = false;
bReplicates = true;
bStaticMeshReplicateMovement = true;
const auto MeshComp = GetStaticMeshComponent();
MeshComp->SetMobility(EComponentMobility::Movable);
MeshComp->SetCollisionObjectType(ECC_WorldDynamic);
// I think this is actually not needed, since on clients the role is ROLE_SimulatedProxy not ROLE_AutonomousProxy
// When using ROLE_SimulatedProxy physics is replicated all the time
MeshComp->bReplicatePhysicsToAutonomousProxy = true;
// The default MinNetUpdateFrequency of 2 is too slow at responding to woken physics objects
#if ENGINE_MINOR_VERSION >= 5
SetMinNetUpdateFrequency(10);
#else
MinNetUpdateFrequency = 10;
#endif
// We do NOT replicate MeshComp itself! That's expensive and unnecessary
}
void AStevesReplicatedPhysicsActor::BeginPlay()
{
SetReplicateMovement(true);
const auto MeshComp = GetStaticMeshComponent();
// Server test, includes dedicated and listen servers
if (IsServer())
{
// Server collision. Block all but allow pawns through
// Subclasses can change this if they like
MeshComp->SetCollisionResponseToAllChannels(ECR_Block);
MeshComp->SetCollisionResponseToChannel(ECC_Pawn, ECR_Overlap);
MeshComp->SetSimulatePhysics(true);
}
else
{
// We're on a client so will be receiving replicated physics
// Ignore all collisions; if we don't do this, things jank because of conflicting collisions
MeshComp->SetCollisionResponseToAllChannels(ECR_Ignore);
// We DON'T disable physics. Physics still needs to be enabled for replicated physics to be respected.
// Otherwise objects will not move on the client.
// There's one case where this is problematic: replicated physics actors that are already asleep
// once a new client joins a game in-progress will locally simulate themselves through the floor, because no further
// updates will be received about their physics from the server.
// My solution is to start all objects asleep on the client; if they're not, the server will send updates and
// the objects will wake up. If they're asleep on the server, we're good.
MeshComp->PutAllRigidBodiesToSleep();
}
Super::BeginPlay();
}
bool AStevesReplicatedPhysicsActor::IsServer() const
{
// Server test, includes dedicated and listen servers
// I prefer this to Authority test because you can't replicate objects client->server or client->client anyway
return GetWorld()->GetNetMode() < NM_Client;
}