ElevenLabs: guard null gaze target on late join (replicated ref not resolved)
A client that joins while a conversation is already active can run OnRep with NetConnectedPawns/NetActiveSpeakerPawn entries whose replicated pawn references haven't resolved yet (actor channel not open). NetConnectedPawns.Num() > 0 did not guarantee a non-null element, so OnRep_ConversationState dereferenced a null pawn in its log (crash in Dev/PIE) and ApplyConversationGaze set TargetActor to null (gaze glitch). Both now skip until the reference resolves — OnRep fires again once it's patched in. More likely with 3+ clients. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -2060,13 +2060,19 @@ void UPS_AI_ConvAgent_ElevenLabsComponent::OnRep_ConversationState()
|
|||||||
{
|
{
|
||||||
Gaze->bActive = true;
|
Gaze->bActive = true;
|
||||||
// Use active speaker if set, otherwise first connected pawn.
|
// Use active speaker if set, otherwise first connected pawn.
|
||||||
|
// GazeTarget can be null on a late joiner if the replicated pawn
|
||||||
|
// reference hasn't resolved yet (actor channel not open). Skip until
|
||||||
|
// it resolves — OnRep fires again once the reference is patched in.
|
||||||
APawn* GazeTarget = NetActiveSpeakerPawn ? NetActiveSpeakerPawn : NetConnectedPawns.Last();
|
APawn* GazeTarget = NetActiveSpeakerPawn ? NetActiveSpeakerPawn : NetConnectedPawns.Last();
|
||||||
|
if (GazeTarget)
|
||||||
|
{
|
||||||
Gaze->TargetActor = GazeTarget;
|
Gaze->TargetActor = GazeTarget;
|
||||||
Gaze->ResetBodyTarget();
|
Gaze->ResetBodyTarget();
|
||||||
Gaze->bEnableBodyTracking = true;
|
Gaze->bEnableBodyTracking = true;
|
||||||
UE_LOG(LogPS_AI_ConvAgent_ElevenLabs, Log,
|
UE_LOG(LogPS_AI_ConvAgent_ElevenLabs, Log,
|
||||||
TEXT("[NET-REP] Gaze ACTIVATED, TargetActor set to %s"), *GazeTarget->GetName());
|
TEXT("[NET-REP] Gaze ACTIVATED, TargetActor set to %s"), *GazeTarget->GetName());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Gaze->bActive = false;
|
Gaze->bActive = false;
|
||||||
@@ -2704,10 +2710,12 @@ void UPS_AI_ConvAgent_ElevenLabsComponent::ApplyConversationGaze()
|
|||||||
{
|
{
|
||||||
Gaze->bActive = true;
|
Gaze->bActive = true;
|
||||||
// Look at active speaker if set, otherwise last connected pawn.
|
// Look at active speaker if set, otherwise last connected pawn.
|
||||||
|
// GazeTarget can be null if a replicated pawn ref hasn't resolved yet
|
||||||
|
// (late joiner). Don't overwrite the target with null in that case.
|
||||||
AActor* GazeTarget = NetActiveSpeakerPawn
|
AActor* GazeTarget = NetActiveSpeakerPawn
|
||||||
? static_cast<AActor*>(NetActiveSpeakerPawn)
|
? static_cast<AActor*>(NetActiveSpeakerPawn)
|
||||||
: static_cast<AActor*>(NetConnectedPawns.Last());
|
: static_cast<AActor*>(NetConnectedPawns.Last());
|
||||||
if (Gaze->TargetActor != GazeTarget)
|
if (GazeTarget && Gaze->TargetActor != GazeTarget)
|
||||||
{
|
{
|
||||||
Gaze->TargetActor = GazeTarget;
|
Gaze->TargetActor = GazeTarget;
|
||||||
Gaze->ResetBodyTarget();
|
Gaze->ResetBodyTarget();
|
||||||
|
|||||||
Reference in New Issue
Block a user