UE5 Template Mismatch During Attaching of Instanced Component

Hello Unreal Engine Community,

I’m encountering a problem with my Unreal Engine 5 project and could really use some help. I have a Blueprint named BP_VRPawn which is derived from a C++ class AVRPawn. The main issue is that the Skeletal Mesh representing the hands is not being attached to the MotionControllers. Another issue is that the first time I open the folder containing BP_VRPawn, or the first time I open the Blueprint itself, the Visual Studio debugger stops, and I receive the following log error:

[2023-12-09T15:00:14.495Z]LogOutputDevice: Error: Ensure condition failed: false [File:D:\build\++UE5\Sync\Engine\Source\Runtime\Engine\Private\Components\SceneComponent.cpp] [Line: 2012] 
[2023-12-09T15:00:14.495Z]LogOutputDevice: Error: Template Mismatch during attachment. Attaching instanced component to template component. Parent 'RightHandComponent' (Owner 'Default__BP_VRPawn_C') Self 'MotionController' (Owner 'BP_VRPawn_C_0').

No other changes have been made to BP_VRPawn other than setting Meshes to visualize the HMD, controllers and hands.

Here’s an overview of my class setup in C++:

UVRHandComponent is a custom component that holds a MotionController and a HandMesh. Its code is structured as follows:

VRHandComponent.h:

UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent))
class PROJECT_SHIBAINU_API UVRHandComponent : public USceneComponent
{
    GENERATED_BODY()

public:
    UVRHandComponent();
    
    // Function to set the tracking source
    UFUNCTION(BlueprintCallable, Category = "VR")
    void SetTrackingSource(const FName NewSource);
    
protected:
    virtual void BeginPlay() override;
    
    UPROPERTY(VisibleAnywhere)
    UMotionControllerComponent* MotionController;

    UPROPERTY(VisibleAnywhere)
    USkeletalMeshComponent* HandMesh;
};

VRHandComponent.cpp:

UVRHandComponent::UVRHandComponent()
{
    MotionController = CreateDefaultSubobject<UMotionControllerComponent>(TEXT("MotionController"));
    MotionController->SetupAttachment(this);

    HandMesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("HandMesh"));
    HandMesh->SetupAttachment(MotionController);

    HandMesh->SetCollisionEnabled(ECollisionEnabled::NoCollision);
}

void UVRHandComponent::SetTrackingSource(const FName NewSource)
{
    if (MotionController)
    {
        MotionController->SetTrackingMotionSource(NewSource);
    }
}

The AVRPawn inherits from ACharacter and builds upon the UVRHandComponents:

VRPawn.h:

UCLASS()
class PROJECT_SHIBAINU_API AVRPawn : public ACharacter
{
    GENERATED_BODY()

public:
    AVRPawn();

protected:
    virtual void BeginPlay() override;
    
    UPROPERTY(VisibleAnywhere)
    UCameraComponent* VRPlayerCamera;
    
    UPROPERTY(VisibleAnywhere)
    UStaticMeshComponent* VRHeadsetMesh;
    
    UPROPERTY(VisibleAnywhere)
    UVRHandComponent* LeftHandComponent;
    
    UPROPERTY(VisibleAnywhere)
    UVRHandComponent* RightHandComponent;

    // Rest of the code...
};

VRPawn.cpp:

AVRPawn::AVRPawn()
{
    // Set this pawn to call Tick() every frame.
    PrimaryActorTick.bCanEverTick = true;

    // Instantiate a new SceneComponent and set it as the root component
    RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));

    // Instantiate VROrigin and attach it to RootComponent
    VROrigin = CreateDefaultSubobject<USceneComponent>(TEXT("VROrigin"));
    VROrigin->SetupAttachment(RootComponent);

    // Disable collision for the capsule component
    GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::NoCollision);

    // Initialize the camera component for the VR pawn and attach it to VROrigin
    VRPlayerCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("VRPlayerCamera"));
    VRPlayerCamera->SetupAttachment(VROrigin);

    // Initialize the static mesh component to represent the headset
    VRHeadsetMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("VRHeadsetMesh"));
    VRHeadsetMesh->SetupAttachment(VRPlayerCamera);

    // Disable collision for the VR headset mesh
    VRHeadsetMesh->SetCollisionEnabled(ECollisionEnabled::NoCollision);

    // Initialize the camera position arrow and attach it to the capsule component
    CameraPositionArrow = CreateDefaultSubobject<UArrowComponent>(TEXT("CameraPositionArrow"));
	CameraPositionArrow->SetupAttachment(GetCapsuleComponent());

    // Initialize the VR hand components
    LeftHandComponent = CreateDefaultSubobject<UVRHandComponent>(TEXT("LeftHandComponent"));
    if (LeftHandComponent)
    {
        LeftHandComponent->SetupAttachment(VROrigin);
        LeftHandComponent->SetTrackingSource(TEXT("LeftGrip"));
    }

    RightHandComponent = CreateDefaultSubobject<UVRHandComponent>(TEXT("RightHandComponent"));
    if (RightHandComponent)
    {
        RightHandComponent->SetupAttachment(VROrigin);
        RightHandComponent->SetTrackingSource(TEXT("RightGrip"));
    }

}

Here are the screenshots provided showing how the BP_VRPawn components are set up in the Unreal Engine 5 editor:


If anyone has experience with this sort of problem or can spot anything in my code that I’m overseeing, your input would be greatly appreciated. Thank you in advance for your help!

Best,

This worked for me…

void UMyComponent::OnRegister()
{
    Super::OnRegister();

    // TODO: BUGBUG: Work around the 'Template Mismatch during attachment. Attaching instanced component to template component.' problem.
    // Remove after Epic acknowledges and fixes this long-standing bug or provides guidance.
    // The constructor-initialized components, upon non-CDO instantiation/initialization, are getting CDO references for their attached parents, instead of instance references.
    // A work-around...
    //     - Use SetupAttachment(), per usual in the constructor to establish the parent-child relationship for CDOs.
    //     - Use AttachToComponent() to override those errant CDO references with instance references, in your USceneComponent::OnRegister() override.
    this->MySubComponent1->AttachToComponent(this->GetAttachmentRoot(), FAttachmentTransformRules::KeepRelativeTransform);
    this->MySubComponent2->AttachToComponent(this->MySubComponent1, FAttachmentTransformRules::KeepRelativeTransform);
}