diff --git a/Unreal/PS_AI_Agent/Plugins/PS_AI_ConvAgent/Source/PS_AI_ConvAgent/Private/PS_AI_ConvAgent_ElevenLabsComponent.cpp b/Unreal/PS_AI_Agent/Plugins/PS_AI_ConvAgent/Source/PS_AI_ConvAgent/Private/PS_AI_ConvAgent_ElevenLabsComponent.cpp index 78609ee..b23d062 100644 --- a/Unreal/PS_AI_Agent/Plugins/PS_AI_ConvAgent/Source/PS_AI_ConvAgent/Private/PS_AI_ConvAgent_ElevenLabsComponent.cpp +++ b/Unreal/PS_AI_Agent/Plugins/PS_AI_ConvAgent/Source/PS_AI_ConvAgent/Private/PS_AI_ConvAgent_ElevenLabsComponent.cpp @@ -260,15 +260,12 @@ void UPS_AI_ConvAgent_ElevenLabsComponent::StartConversation() { if (GetOwnerRole() == ROLE_Authority) { - // Server (or standalone): open WebSocket directly. - // In networked mode, also set replicated conversation state. - if (GetWorld() && GetWorld()->GetNetMode() != NM_Standalone) - { - APlayerController* PC = GetWorld()->GetFirstPlayerController(); - bNetIsConversing = true; - NetConversatingPlayer = PC; - NetConversatingPawn = PC ? PC->GetPawn() : nullptr; - } + // Set conversation state (used by ApplyConversationPosture, posture, LOD, etc.). + // In standalone these aren't replicated but are still needed as local state flags. + APlayerController* PC = GetWorld() ? GetWorld()->GetFirstPlayerController() : nullptr; + bNetIsConversing = true; + NetConversatingPlayer = PC; + NetConversatingPawn = PC ? PC->GetPawn() : nullptr; // In persistent mode the WebSocket was already opened by the first StartConversation. // Reuse the existing connection — only set up conversation state. 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 d1003fb..086beb3 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 @@ -311,10 +311,13 @@ void UPS_AI_ConvAgent_InteractionComponent::SetSelectedAgent(UPS_AI_ConvAgent_El NewAgent->GetOwner() ? *NewAgent->GetOwner()->GetName() : TEXT("(null)")); } - // Network: auto-start conversation if the agent isn't connected yet. + // Network: auto-start conversation if no active conversation. + // In persistent session mode, the WebSocket stays connected but + // bNetIsConversing is false between interactions — we still need + // to call StartConversation() to re-activate posture and mic. // Only when bAutoStartConversation is true — otherwise the user must // call StartConversationWithSelectedAgent() explicitly (e.g. on key press). - if (bAutoStartConversation && !NewAgent->IsConnected() && !NewAgent->bNetIsConversing) + if (bAutoStartConversation && !NewAgent->bNetIsConversing) { // On the server, call StartConversation() directly. // On clients, route through our relay RPC (clients can't call @@ -494,6 +497,7 @@ void UPS_AI_ConvAgent_InteractionComponent::AttachPostureTarget( if (UPS_AI_ConvAgent_PostureComponent* Posture = FindPostureOnAgent(AgentPtr)) { Posture->TargetActor = GetOwner(); + Posture->bActive = true; // Reset the body target to the actor's current facing so body tracking // starts fresh on re-entry. Without this, TargetBodyWorldYaw retains