Use CameraComponent for view point and gaze target (VR/FPS compatibility)
- InteractionComponent: GetPawnViewPoint() now prefers UCameraComponent over PlayerController::GetPlayerViewPoint() — fixes agent selection in VR where the pawn root stays at spawn while the HMD moves freely - GazeComponent: ResolveTargetPosition() uses camera first for locally controlled pawns (VR HMD / FPS eye position), falls back to bone chain for NPCs and remote players in multiplayer Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
e5f40c65ec
commit
8ad66ae4d5
@ -58,48 +58,59 @@ static FVector ResolveTargetPosition(const AActor* Target, bool bAutoEyes,
|
|||||||
{
|
{
|
||||||
if (!Target) return FVector::ZeroVector;
|
if (!Target) return FVector::ZeroVector;
|
||||||
|
|
||||||
if (bAutoEyes)
|
if (!bAutoEyes)
|
||||||
{
|
{
|
||||||
// Try to find a Face mesh with eye bones on the target
|
// Manual mode: actor origin + user-defined offset
|
||||||
TArray<USkeletalMeshComponent*> SkelMeshes;
|
return Target->GetActorLocation() + ManualOffset;
|
||||||
const_cast<AActor*>(Target)->GetComponents<USkeletalMeshComponent>(SkelMeshes);
|
|
||||||
|
|
||||||
for (const USkeletalMeshComponent* SMC : SkelMeshes)
|
|
||||||
{
|
|
||||||
if (!SMC) continue;
|
|
||||||
|
|
||||||
if (SMC->DoesSocketExist(TargetEyeBoneL) && SMC->DoesSocketExist(TargetEyeBoneR))
|
|
||||||
{
|
|
||||||
// Midpoint between both eye bones
|
|
||||||
return (SMC->GetSocketLocation(TargetEyeBoneL)
|
|
||||||
+ SMC->GetSocketLocation(TargetEyeBoneR)) * 0.5f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback: head bone on any mesh
|
|
||||||
for (const USkeletalMeshComponent* SMC : SkelMeshes)
|
|
||||||
{
|
|
||||||
if (!SMC) continue;
|
|
||||||
if (SMC->DoesSocketExist(TargetHeadBone))
|
|
||||||
{
|
|
||||||
return SMC->GetSocketLocation(TargetHeadBone);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback: CameraComponent — the canonical eye position for
|
|
||||||
// first-person pawns and any actor with an active camera.
|
|
||||||
if (const UCameraComponent* Cam =
|
|
||||||
const_cast<AActor*>(Target)->FindComponentByClass<UCameraComponent>())
|
|
||||||
{
|
|
||||||
return Cam->GetComponentLocation();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Final fallback: actor origin + height offset
|
|
||||||
return Target->GetActorLocation() + FVector(0.0f, 0.0f, FallbackHeight);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Manual mode: actor origin + user-defined offset
|
// For locally controlled pawns (VR/FPS player), prefer the CameraComponent.
|
||||||
return Target->GetActorLocation() + ManualOffset;
|
// In VR the pawn's skeletal mesh may stay at the spawn point while the HMD
|
||||||
|
// moves freely — using eye bones would make the agent look at the floor.
|
||||||
|
if (const APawn* Pawn = Cast<APawn>(Target))
|
||||||
|
{
|
||||||
|
if (Pawn->IsLocallyControlled())
|
||||||
|
{
|
||||||
|
if (const UCameraComponent* Cam =
|
||||||
|
const_cast<AActor*>(Target)->FindComponentByClass<UCameraComponent>())
|
||||||
|
{
|
||||||
|
return Cam->GetComponentLocation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// For other targets (NPCs, remote players): bone chain.
|
||||||
|
TArray<USkeletalMeshComponent*> SkelMeshes;
|
||||||
|
const_cast<AActor*>(Target)->GetComponents<USkeletalMeshComponent>(SkelMeshes);
|
||||||
|
|
||||||
|
for (const USkeletalMeshComponent* SMC : SkelMeshes)
|
||||||
|
{
|
||||||
|
if (!SMC) continue;
|
||||||
|
if (SMC->DoesSocketExist(TargetEyeBoneL) && SMC->DoesSocketExist(TargetEyeBoneR))
|
||||||
|
{
|
||||||
|
return (SMC->GetSocketLocation(TargetEyeBoneL)
|
||||||
|
+ SMC->GetSocketLocation(TargetEyeBoneR)) * 0.5f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const USkeletalMeshComponent* SMC : SkelMeshes)
|
||||||
|
{
|
||||||
|
if (!SMC) continue;
|
||||||
|
if (SMC->DoesSocketExist(TargetHeadBone))
|
||||||
|
{
|
||||||
|
return SMC->GetSocketLocation(TargetHeadBone);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CameraComponent fallback for non-locally-controlled targets that have one.
|
||||||
|
if (const UCameraComponent* Cam =
|
||||||
|
const_cast<AActor*>(Target)->FindComponentByClass<UCameraComponent>())
|
||||||
|
{
|
||||||
|
return Cam->GetComponentLocation();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Final fallback: actor origin + height offset.
|
||||||
|
return Target->GetActorLocation() + FVector(0.0f, 0.0f, FallbackHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─────────────────────────────────────────────────────────────────────────────
|
// ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
#include "GameFramework/Pawn.h"
|
#include "GameFramework/Pawn.h"
|
||||||
#include "GameFramework/PlayerController.h"
|
#include "GameFramework/PlayerController.h"
|
||||||
#include "Camera/PlayerCameraManager.h"
|
#include "Camera/PlayerCameraManager.h"
|
||||||
|
#include "Camera/CameraComponent.h"
|
||||||
#include "TimerManager.h"
|
#include "TimerManager.h"
|
||||||
#include "Net/UnrealNetwork.h"
|
#include "Net/UnrealNetwork.h"
|
||||||
|
|
||||||
@ -434,7 +435,17 @@ void UPS_AI_ConvAgent_InteractionComponent::GetPawnViewPoint(FVector& OutLocatio
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to get the player controller's camera view (most accurate for first/third person).
|
// Prefer the CameraComponent directly — most reliable for VR (HMD) and FPS (eye level).
|
||||||
|
// In VR the pawn's actor location stays at the spawn point while the HMD moves freely,
|
||||||
|
// so GetPlayerViewPoint() may not reflect the actual head position.
|
||||||
|
if (UCameraComponent* Cam = Owner->FindComponentByClass<UCameraComponent>())
|
||||||
|
{
|
||||||
|
OutLocation = Cam->GetComponentLocation();
|
||||||
|
OutDirection = Cam->GetForwardVector();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback: PlayerController view point (camera manager pipeline).
|
||||||
if (APawn* Pawn = Cast<APawn>(Owner))
|
if (APawn* Pawn = Cast<APawn>(Owner))
|
||||||
{
|
{
|
||||||
if (APlayerController* PC = Cast<APlayerController>(Pawn->GetController()))
|
if (APlayerController* PC = Cast<APlayerController>(Pawn->GetController()))
|
||||||
@ -446,7 +457,7 @@ void UPS_AI_ConvAgent_InteractionComponent::GetPawnViewPoint(FVector& OutLocatio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback: use actor location and forward.
|
// Final fallback: actor transform.
|
||||||
OutLocation = Owner->GetActorLocation();
|
OutLocation = Owner->GetActorLocation();
|
||||||
OutDirection = Owner->GetActorForwardVector();
|
OutDirection = Owner->GetActorForwardVector();
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user