diff --git a/Unreal/PS_AI_Agent/Plugins/PS_AI_ConvAgent/Source/PS_AI_ConvAgent/Private/AnimNode_PS_AI_ConvAgent_Posture.cpp b/Unreal/PS_AI_Agent/Plugins/PS_AI_ConvAgent/Source/PS_AI_ConvAgent/Private/AnimNode_PS_AI_ConvAgent_Posture.cpp index 719207b..c2f2ef7 100644 --- a/Unreal/PS_AI_Agent/Plugins/PS_AI_ConvAgent/Source/PS_AI_ConvAgent/Private/AnimNode_PS_AI_ConvAgent_Posture.cpp +++ b/Unreal/PS_AI_Agent/Plugins/PS_AI_ConvAgent/Source/PS_AI_ConvAgent/Private/AnimNode_PS_AI_ConvAgent_Posture.cpp @@ -144,8 +144,6 @@ void FAnimNode_PS_AI_ConvAgent_Posture::CacheBones_AnyThread(const FAnimationCac RightEyeBoneIndex = FCompactPoseBoneIndex(INDEX_NONE); LeftEyeRefPoseRotation = FQuat::Identity; RightEyeRefPoseRotation = FQuat::Identity; - BodyBoneIndex = FCompactPoseBoneIndex(INDEX_NONE); - BodyBoneRefPoseRotation = FQuat::Identity; ChainBoneIndices.Reset(); ChainRefPoseRotations.Reset(); @@ -249,22 +247,6 @@ void FAnimNode_PS_AI_ConvAgent_Posture::CacheBones_AnyThread(const FAnimationCac ResolveEyeBone(DefaultRightEyeBone, RightEyeBoneIndex, RightEyeRefPoseRotation); } - // ── Resolve body bone for body yaw rotation ───────────────────── - // The body yaw offset is applied to "pelvis" (or first skeleton bone) - // to rotate the entire skeleton without modifying actor rotation. - { - static const FName DefaultBodyBone(TEXT("pelvis")); - const int32 MeshIdx = RefSkeleton.FindBoneIndex(DefaultBodyBone); - if (MeshIdx != INDEX_NONE) - { - BodyBoneIndex = RequiredBones.MakeCompactPoseIndex( - FMeshPoseBoneIndex(MeshIdx)); - BodyBoneRefPoseRotation = (MeshIdx < RefPose.Num()) - ? RefPose[MeshIdx].GetRotation() - : FQuat::Identity; - } - } - // ── Resolve ancestor chain for body drift compensation ──────────── // Walk from the parent of the first neck/head bone up to root. // This lets us measure how much the spine/torso animation has @@ -346,7 +328,6 @@ void FAnimNode_PS_AI_ConvAgent_Posture::Update_AnyThread(const FAnimationUpdateC CachedHeadCompensation = PostureComponent->GetHeadAnimationCompensation(); CachedEyeCompensation = PostureComponent->GetEyeAnimationCompensation(); CachedBodyDriftCompensation = PostureComponent->GetBodyDriftCompensation(); - CachedBodyYawOffset = PostureComponent->GetBodyYawOffset(); } } @@ -610,18 +591,6 @@ void FAnimNode_PS_AI_ConvAgent_Posture::Evaluate_AnyThread(FPoseContext& Output) return; } - // ── Apply body yaw rotation to pelvis bone ───────────────────────────── - // This replaces the old AddActorWorldRotation() approach — the actor rotation - // is never modified; the body turn is purely animation-driven (local, no replication). - if (FMath::Abs(CachedBodyYawOffset) > 0.1f - && BodyBoneIndex.GetInt() != INDEX_NONE - && BodyBoneIndex.GetInt() < Output.Pose.GetNumBones()) - { - const FQuat BodyYawQuat(FVector::UpVector, FMath::DegreesToRadians(CachedBodyYawOffset)); - FTransform& BodyTransform = Output.Pose[BodyBoneIndex]; - BodyTransform.SetRotation((BodyYawQuat * BodyTransform.GetRotation()).GetNormalized()); - } - // IMPORTANT: Even when posture is near-zero (head looking straight at target), // we still need to run compensation to REMOVE the animation's head contribution. // Only skip if BOTH posture is identity AND compensation is inactive (pure additive). diff --git a/Unreal/PS_AI_Agent/Plugins/PS_AI_ConvAgent/Source/PS_AI_ConvAgent/Private/PS_AI_ConvAgent_PostureComponent.cpp b/Unreal/PS_AI_Agent/Plugins/PS_AI_ConvAgent/Source/PS_AI_ConvAgent/Private/PS_AI_ConvAgent_PostureComponent.cpp index 97ff77c..61518b1 100644 --- a/Unreal/PS_AI_Agent/Plugins/PS_AI_ConvAgent/Source/PS_AI_ConvAgent/Private/PS_AI_ConvAgent_PostureComponent.cpp +++ b/Unreal/PS_AI_Agent/Plugins/PS_AI_ConvAgent/Source/PS_AI_ConvAgent/Private/PS_AI_ConvAgent_PostureComponent.cpp @@ -99,7 +99,6 @@ void UPS_AI_ConvAgent_PostureComponent::BeginPlay() // Apply the mesh forward offset so "neutral" aligns with where the face points. OriginalActorYaw = Owner->GetActorRotation().Yaw + MeshForwardYawOffset; TargetBodyWorldYaw = Owner->GetActorRotation().Yaw; - CurrentBodyWorldYaw = Owner->GetActorRotation().Yaw; if (bDebug) { @@ -180,7 +179,6 @@ void UPS_AI_ConvAgent_PostureComponent::ResetBodyTarget() if (AActor* Owner = GetOwner()) { TargetBodyWorldYaw = Owner->GetActorRotation().Yaw; - CurrentBodyWorldYaw = Owner->GetActorRotation().Yaw; } } @@ -335,14 +333,11 @@ void UPS_AI_ConvAgent_PostureComponent::TickComponent( if (bEnableBodyTracking) { const float BodyDelta = FMath::FindDeltaAngleDegrees( - CurrentBodyWorldYaw, TargetBodyWorldYaw); + Owner->GetActorRotation().Yaw, TargetBodyWorldYaw); if (FMath::Abs(BodyDelta) > 0.1f) { const float BodyStep = FMath::FInterpTo(0.0f, BodyDelta, SafeDeltaTime, BodyInterpSpeed); - // Track body facing internally instead of modifying the actor rotation. - // The AnimNode applies the delta as a bone rotation — purely local, - // no actor rotation change, no replication conflict. - CurrentBodyWorldYaw += BodyStep; + Owner->AddActorWorldRotation(FRotator(0.0f, BodyStep, 0.0f)); } } @@ -351,7 +346,7 @@ void UPS_AI_ConvAgent_PostureComponent::TickComponent( float DeltaYaw = 0.0f; if (!HorizontalDir.IsNearlyZero(1.0f)) { - const float CurrentFacingYaw = CurrentBodyWorldYaw + MeshForwardYawOffset; + const float CurrentFacingYaw = Owner->GetActorRotation().Yaw + MeshForwardYawOffset; DeltaYaw = FMath::FindDeltaAngleDegrees(CurrentFacingYaw, TargetWorldYaw); } @@ -464,11 +459,6 @@ void UPS_AI_ConvAgent_PostureComponent::TickComponent( // Eye yaw is negated to match ARKit curve direction convention. UpdateEyeCurves(-CurrentEyeYaw, CurrentEyePitch); - - // Body yaw offset = how much the body has turned relative to the actor's rotation. - // The AnimNode applies this as a bone rotation (pelvis) — purely local. - CachedBodyYawOffset = FMath::FindDeltaAngleDegrees( - Owner->GetActorRotation().Yaw, CurrentBodyWorldYaw) * CurrentActiveAlpha; } // ── Debug gaze lines ──────────────────────────────────────────────────── @@ -541,22 +531,21 @@ void UPS_AI_ConvAgent_PostureComponent::TickComponent( DebugFrameCounter++; if (DebugFrameCounter % 120 == 0) { - const float FacingYaw = CurrentBodyWorldYaw + MeshForwardYawOffset; + const float FacingYaw = Owner->GetActorRotation().Yaw + MeshForwardYawOffset; const FVector TP = TargetActor->GetActorLocation() + TargetOffset; const FVector Dir = TP - Owner->GetActorLocation(); const float TgtYaw = FVector(Dir.X, Dir.Y, 0.0f).Rotation().Yaw; const float Delta = FMath::FindDeltaAngleDegrees(FacingYaw, TgtYaw); UE_LOG(LogPS_AI_ConvAgent_Posture, Log, - TEXT("Posture [%s -> %s]: Delta=%.1f | Head=%.1f/%.1f | Eyes=%.1f/%.1f | Body: enabled=%s TargetYaw=%.1f BodyYaw=%.1f (offset=%.1f)"), + TEXT("Posture [%s -> %s]: Delta=%.1f | Head=%.1f/%.1f | Eyes=%.1f/%.1f | Body: enabled=%s TargetYaw=%.1f ActorYaw=%.1f"), *Owner->GetName(), *TargetActor->GetName(), Delta, CurrentHeadYaw, CurrentHeadPitch, CurrentEyeYaw, CurrentEyePitch, bEnableBodyTracking ? TEXT("Y") : TEXT("N"), TargetBodyWorldYaw, - CurrentBodyWorldYaw, - CachedBodyYawOffset); + Owner->GetActorRotation().Yaw); } } } diff --git a/Unreal/PS_AI_Agent/Plugins/PS_AI_ConvAgent/Source/PS_AI_ConvAgent/Public/AnimNode_PS_AI_ConvAgent_Posture.h b/Unreal/PS_AI_Agent/Plugins/PS_AI_ConvAgent/Source/PS_AI_ConvAgent/Public/AnimNode_PS_AI_ConvAgent_Posture.h index e2c8265..bff209f 100644 --- a/Unreal/PS_AI_Agent/Plugins/PS_AI_ConvAgent/Source/PS_AI_ConvAgent/Public/AnimNode_PS_AI_ConvAgent_Posture.h +++ b/Unreal/PS_AI_Agent/Plugins/PS_AI_ConvAgent/Source/PS_AI_ConvAgent/Public/AnimNode_PS_AI_ConvAgent_Posture.h @@ -139,20 +139,6 @@ private: * Cached from the component during Update. */ float CachedBodyDriftCompensation = 0.0f; - // ── Body yaw (animation-only body tracking) ────────────────────────── - - /** Bone to apply body yaw rotation to. Rotates the entire skeleton - * visually without modifying the actor rotation (no replication conflict). - * Default "pelvis" works for MetaHuman and most humanoid skeletons. */ - FCompactPoseBoneIndex BodyBoneIndex = FCompactPoseBoneIndex(INDEX_NONE); - - /** Reference pose rotation for the body bone. */ - FQuat BodyBoneRefPoseRotation = FQuat::Identity; - - /** Body yaw offset in degrees (relative to actor rotation). - * Cached from the component during Update. */ - float CachedBodyYawOffset = 0.0f; - #if !UE_BUILD_SHIPPING /** Frame counter for periodic diagnostic logging in Evaluate. */ int32 EvalDebugFrameCounter = 0; diff --git a/Unreal/PS_AI_Agent/Plugins/PS_AI_ConvAgent/Source/PS_AI_ConvAgent/Public/PS_AI_ConvAgent_PostureComponent.h b/Unreal/PS_AI_Agent/Plugins/PS_AI_ConvAgent/Source/PS_AI_ConvAgent/Public/PS_AI_ConvAgent_PostureComponent.h index a5097a8..4c9a117 100644 --- a/Unreal/PS_AI_Agent/Plugins/PS_AI_ConvAgent/Source/PS_AI_ConvAgent/Public/PS_AI_ConvAgent_PostureComponent.h +++ b/Unreal/PS_AI_Agent/Plugins/PS_AI_ConvAgent/Source/PS_AI_ConvAgent/Public/PS_AI_ConvAgent_PostureComponent.h @@ -273,15 +273,6 @@ public: * Scaled by activation alpha for smooth passthrough when inactive. */ float GetBodyDriftCompensation() const { return BodyDriftCompensation * CurrentActiveAlpha; } - /** Get body yaw offset in degrees (relative to actor's rotation). - * Applied by the AnimNode as a bone rotation — purely local, no replication. - * Thread-safe copy, blended by activation alpha. */ - float GetBodyYawOffset() const - { - FScopeLock Lock(&PostureDataLock); - return CachedBodyYawOffset; - } - /** Reset the persistent body yaw target to the actor's current facing. * Call this when re-attaching a posture target so body tracking starts * fresh instead of chasing a stale yaw from the previous interaction. */ @@ -330,12 +321,6 @@ private: * Same sticky pattern as TargetHeadYaw but for the body layer. */ float TargetBodyWorldYaw = 0.0f; - /** Interpolated actual body facing in world space. - * Replaces the old AddActorWorldRotation() approach — the actor rotation - * is never modified; instead this tracks the virtual body facing and the - * AnimNode applies the delta as a bone rotation (100% local, no replication). */ - float CurrentBodyWorldYaw = 0.0f; - /** Original actor yaw at BeginPlay (for neutral return when TargetActor is null). */ float OriginalActorYaw = 0.0f; @@ -353,10 +338,6 @@ private: /** Head bone rotation offset as quaternion (no Euler round-trip). */ FQuat CurrentHeadRotation = FQuat::Identity; - /** Body yaw offset in degrees (relative to actor rotation). - * Computed in TickComponent, read by AnimNode via GetBodyYawOffset(). */ - float CachedBodyYawOffset = 0.0f; - /** Cached skeletal mesh component on the owning actor (Body). */ TWeakObjectPtr CachedMesh;