From 3c4389a43d14b1f090a30efacac46324b94689e9 Mon Sep 17 00:00:00 2001 From: "j.foucher" Date: Mon, 2 Mar 2026 16:57:33 +0100 Subject: [PATCH] Fix InteractionComponent ticking on server for remote client pawns In a listen server, the server-side copy of a remote client's pawn also has an InteractionComponent that ticks. This caused a race condition: the server-side tick would start conversations using GetFirstPlayerController() (= server's PC), setting NetConversatingPawn to the server's pawn instead of the client's. The client's relay RPC arrived too late and was rejected because bNetIsConversing was already true. Fix: disable tick and skip mic creation in BeginPlay for non-locally-controlled pawns. The client handles all interaction locally via relay RPCs. Co-Authored-By: Claude Opus 4.6 --- .../PS_AI_ConvAgent_InteractionComponent.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/Unreal/PS_AI_Agent/Plugins/PS_AI_ConvAgent/Source/PS_AI_ConvAgent/Private/PS_AI_ConvAgent_InteractionComponent.cpp b/Unreal/PS_AI_Agent/Plugins/PS_AI_ConvAgent/Source/PS_AI_ConvAgent/Private/PS_AI_ConvAgent_InteractionComponent.cpp index 485cd3e..00615a3 100644 --- a/Unreal/PS_AI_Agent/Plugins/PS_AI_ConvAgent/Source/PS_AI_ConvAgent/Private/PS_AI_ConvAgent_InteractionComponent.cpp +++ b/Unreal/PS_AI_Agent/Plugins/PS_AI_ConvAgent/Source/PS_AI_ConvAgent/Private/PS_AI_ConvAgent_InteractionComponent.cpp @@ -31,10 +31,24 @@ void UPS_AI_ConvAgent_InteractionComponent::BeginPlay() { Super::BeginPlay(); - // Create mic capture component on the pawn. AActor* Owner = GetOwner(); if (!Owner) return; + // Only run interaction logic on the locally controlled pawn. + // In a listen server, the server-side copy of a remote client's pawn also has + // this component, but it must NOT tick, evaluate agents, or create mic components. + // The client handles all interaction locally and routes through relay RPCs. + // Without this guard, the server-side tick would start conversations using + // GetFirstPlayerController() = server's PC, setting NetConversatingPawn to the + // wrong player (server instead of client). + APawn* OwnerPawn = Cast(Owner); + if (OwnerPawn && !OwnerPawn->IsLocallyControlled()) + { + SetComponentTickEnabled(false); + return; + } + + // Create mic capture component on the pawn. MicComponent = Owner->FindComponentByClass(); if (!MicComponent) {