Revert animation-only body tracking — restore AddActorWorldRotation
The pelvis bone rotation approach didn't work in practice. Reverts to the previous AddActorWorldRotation() body tracking (replicated actor rotation). Thread-safety fix and deprecated IsValid() removal are kept. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
677f08e936
commit
7f92dcab51
@ -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).
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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<USkeletalMeshComponent> CachedMesh;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user