How to get play character's skeletal mesh and attach a hat to it?

I wanted to implement a picking up hats functionality as shown in this video (Unreal Engine 4 - Attach Weapon to Hand - YouTube) using C++ (putting a hat pickup on the ground and if the player overlap with the hat, the hat will be destroyed and be attached to the player character’s “headSocket” socket).

I search the Unreal documentation and found these methods:

  1. SetupAttachment(USceneComponent * InParent, FName InSocketName)

  2. AttachToComponent(USceneComponent * InParent, const FAttachmentTransformRules & AttachmentRules, FName InSocketName)

They both need a reference to the skeletal mesh of the PlayerCharacter as the 1st parameter.

I tried passing the second line:

auto PlayerCharacter = UGameplayStatics::GetPlayerCharacter(GetWorld(), 0);

PlayerCharacter->GetMesh();

But it seemed not to work.

Other posts that I came across:

https://forums.unrealengine.com/development-discussion/c-gameplay-programming/11354-attach-actor-to-socket-via-c?22881-Attach-Actor-to-socket-via-C=&viewfull=1

Can anyone tell me how to correctly use SetupAttachment() and AttachToComponent() or how to correctly reference the Skeletal mesh of PlayerCharacter?

Here are my codes:

HatPickup.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Components/StaticMeshComponent.h"
#include "Components/SphereComponent.h"
#include "Engine/SkeletalMesh.h"
#include "Components/SkeletalMeshComponent.h"
#include "HatPickup.generated.h"

UCLASS()
class WINTERCABIN_API AHatPickup : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	AHatPickup();

	//hat static mesh
	UPROPERTY(VisibleAnywhere, Category = Mesh)
	UStaticMeshComponent* HatMesh;
	
	//overlap detection sphere
	UPROPERTY(VisibleAnywhere, Category = Mesh)
	USphereComponent* CollisionSphere;

	UPROPERTY(VisibleAnywhere, Category = Mesh)
	USkeletalMesh* PlayerMesh;
	
	UPROPERTY(VisibleAnywhere, Category = Mesh)
	USkeletalMeshComponent* PlayerMeshComponent;

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	UFUNCTION()
	void Pickuped();

	// declare overlap begin function
	UFUNCTION()
	void OnOverlapBegin(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
};

HatPickup.cpp

#include "HatPickup.h"
#include "Kismet/GameplayStatics.h"
#include "ConstructorHelpers.h"


// Sets default values
AHatPickup::AHatPickup()
{
 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

	//Hat mesh
	HatMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Hat"));
	static ConstructorHelpers::FObjectFinder<UStaticMesh> HatMeshAsset(TEXT("/Game/_Mesh/Props/Clothing/Hat.Hat"));
	if (HatMeshAsset.Succeeded())
	{
		HatMesh->SetStaticMesh(HatMeshAsset.Object);
	}
	RootComponent = HatMesh;

	//Collision sphere
	CollisionSphere = CreateDefaultSubobject<USphereComponent>(TEXT("CollisionShpere"));
	CollisionSphere->SetupAttachment(RootComponent);
	CollisionSphere->InitSphereRadius(50.0f);
}

// Called when the game starts or when spawned
void AHatPickup::BeginPlay()
{
	Super::BeginPlay();
	
	CollisionSphere->OnComponentBeginOverlap.AddDynamic(this, &AHatPickup::OnOverlapBegin);
}

// Called every frame
void AHatPickup::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

void AHatPickup::Pickuped()
{
	if (PlayerMeshComponent)
	{
		HatMesh->SetupAttachment(PlayerMeshComponent, TEXT("headSocket"));
		Destroy();
	}
}

void AHatPickup::OnOverlapBegin(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	
	if (OtherActor && (OtherActor != this) && OtherComp && OtherActor)
	{
		PlayerMeshComponent = Cast<USkeletalMeshComponent>(OtherActor);
		Pickuped();
	}
}
  1. Create an event called OnHatPickup(AStaticMeshComponent* HatSM) on your player character

  2. Call that inside the OnOverlapBegin function in your AHatPickup class

  3. Inside the OnHatPickup function in your player class type:

    if (HatSM)
    {
    	HatSM->AttachToComponent(GetMesh(), FAttachmentTransformRules(EAttachmentRule::SnapToTarget, true), FName("headSocket"));
    }

OnHatPickup(AStaticMeshComponent* HatSM) should be written as OnHatPickup(UStaticMeshComponent* HatSM). But thank you anyway for answering this question.You gave inspiration that I should declare a HatSM variable inside my player character class, and show the mesh on the Hat class is pickup up. I will try this implementation.