From cd7444f4d2c0561a956a8669a6975bde7bc6885b Mon Sep 17 00:00:00 2001 From: cit110 <840418418@qq.com> Date: Sun, 26 Apr 2026 17:11:57 +0800 Subject: [PATCH] Fix retarget display mesh initialization --- .../PHYCharacterMeshBridgeComponent.cpp | 25 ++++++++++++++++++- .../PHYCharacterMeshBridgeComponent.h | 3 +++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/Source/PHY/Private/Animation/PHYCharacterMeshBridgeComponent.cpp b/Source/PHY/Private/Animation/PHYCharacterMeshBridgeComponent.cpp index 6c2e002..1c6ae00 100644 --- a/Source/PHY/Private/Animation/PHYCharacterMeshBridgeComponent.cpp +++ b/Source/PHY/Private/Animation/PHYCharacterMeshBridgeComponent.cpp @@ -18,6 +18,14 @@ UPHYCharacterMeshBridgeComponent::UPHYCharacterMeshBridgeComponent(const FObject PrimaryComponentTick.bCanEverTick = false; } +void UPHYCharacterMeshBridgeComponent::BeginPlay() +{ + Super::BeginPlay(); + + // 构造期或 PlayerState 职业同步可能早于显示 Mesh 注册,运行时再确认一次。 + RefreshFollowPoseMode(); +} + void UPHYCharacterMeshBridgeComponent::InitializeMeshBridge(ACharacter* Character, USkeletalMeshComponent* InDisplayMeshComponent) { SourceMeshComponent = Character ? Character->GetMesh() : nullptr; @@ -185,6 +193,16 @@ void UPHYCharacterMeshBridgeComponent::ConfigureRetargetFollowPose() return; } + if (!DisplayMeshComponent->GetSkeletalMeshAsset()) + { + return; + } + + if (!SourceMeshComponent->IsRegistered() || !DisplayMeshComponent->IsRegistered()) + { + return; + } + TSubclassOf RetargetAnimClass = ResolveRetargetDisplayAnimClass(); if (!RetargetAnimClass) { @@ -204,6 +222,8 @@ void UPHYCharacterMeshBridgeComponent::ConfigureRetargetFollowPose() DisplayMeshComponent->SetAnimInstanceClass(RetargetAnimClass); } + DisplayMeshComponent->InitAnim(true); + if (!CurrentRetargeter.IsValid()) { UE_LOG(LogTemp, Warning, TEXT("PHYCharacterMeshBridgeComponent: DisplayMesh %s needs an IK Retargeter for cross-skeleton follow pose."), *GetNameSafe(DisplayMeshComponent)); @@ -213,7 +233,10 @@ void UPHYCharacterMeshBridgeComponent::ConfigureRetargetFollowPose() UPHYRetargetPoseAnimInstance* RetargetAnimInstance = Cast(DisplayMeshComponent->GetAnimInstance()); if (!RetargetAnimInstance) { - UE_LOG(LogTemp, Warning, TEXT("PHYCharacterMeshBridgeComponent: DisplayMesh %s did not create a UPHYRetargetPoseAnimInstance."), *GetNameSafe(DisplayMeshComponent)); + UE_LOG(LogTemp, Warning, TEXT("PHYCharacterMeshBridgeComponent: DisplayMesh %s did not create a UPHYRetargetPoseAnimInstance. AnimClass=%s AnimInstance=%s"), + *GetNameSafe(DisplayMeshComponent), + *GetNameSafe(DisplayMeshComponent->GetAnimClass()), + *GetNameSafe(DisplayMeshComponent->GetAnimInstance())); return; } diff --git a/Source/PHY/Public/Animation/PHYCharacterMeshBridgeComponent.h b/Source/PHY/Public/Animation/PHYCharacterMeshBridgeComponent.h index 4edf583..3e9ed9c 100644 --- a/Source/PHY/Public/Animation/PHYCharacterMeshBridgeComponent.h +++ b/Source/PHY/Public/Animation/PHYCharacterMeshBridgeComponent.h @@ -72,6 +72,9 @@ public: FSoftObjectPath GetCurrentRetargeter() const { return CurrentRetargeter; } protected: + /** @brief 组件进入运行时后重新确认 Follow Pose 模式,覆盖构造期组件未注册的情况。 */ + virtual void BeginPlay() override; + /** @brief 应用配置中的源运动 Mesh 和 AnimClass 默认值。 */ void ApplySourceDefaults();