Quick answer: Camera shakes run on the local PlayerCameraManager and are never replicated. Calling StartCameraShake on the server only shakes the server's own view (or nothing, on a dedicated server). Use the built-in client RPC APlayerController::ClientStartCameraShake() for one player, or a multicast or replicated event that calls Play World Camera Shake locally on every client.

The explosion shakes the screen on the listen-server host and on nobody else. Nothing is wrong with the shake asset; it is running on the wrong machine.

Why it does not replicate

Each machine has its own PlayerCameraManager for its local player. Camera shakes are purely cosmetic and live entirely on that local manager, so the engine never sends them over the network. Server code that calls PlayerController->PlayerCameraManager->StartCameraShake(...) for a remote player's controller runs on the server's copy of that controller, which has no camera on screen.

One player: use the client RPC

PlayerController already has a client RPC for this:

// Server side, e.g. when a player takes damage
if (APlayerController* PC = Cast<APlayerController>(GetController()))
{
    PC->ClientStartCameraShake(HitShakeClass, 1.0f);
}

ClientStartCameraShake runs on the owning client and starts the shake on its local camera manager. In Blueprints, call Client Start Camera Shake on the player controller from server-side logic.

Everyone nearby: multicast or replicated event

For world events such as explosions, play the shake locally on each machine, usually from the same place the explosion's visual effects play:

UFUNCTION(NetMulticast, Unreliable)
void MulticastExplode(FVector Location);

void AGrenade::MulticastExplode_Implementation(FVector Location)
{
    UGameplayStatics::PlayWorldCameraShake(
        this, ExplosionShake, Location, InnerRadius, OuterRadius);
}

PlayWorldCameraShake shakes every local camera within the radius, with falloff, on the machine where it runs. Unreliable is fine for cosmetic effects. If the event is already represented by replicated state (a replicated bExploded with an OnRep), trigger the shake in the OnRep instead of adding an RPC.

Client RPCs need an owner

A Client RPC called on an actor the client does not own (a grenade, a door) is dropped. Route per-player RPCs through the PlayerController, the possessed pawn, or the PlayerState.

Dedicated servers

On a dedicated server there is no local player, so camera shake code on the server never does anything visible. Guard it with IsNetMode(NM_DedicatedServer) checks or keep it in client-only paths to avoid wasted work.

UE5 class changes

In Unreal Engine 5, shakes derive from UCameraShakeBase (the Blueprint parent is CameraShakeBase, typically with a Wave or Perlin Noise pattern). Old UMatineeCameraShake assets were converted to legacy shake classes; if a shake does nothing at all even in single player, recreate it from CameraShakeBase and check its duration and pattern amplitudes.

Related fixes