How to attache mesh to parent socket

Hi,

I’m trying to create a Helicopter Pawn by following this tutorial:

But I would like to do it in C ++.
I created a C ++ class deriving from Pawn and I added the static meshes of the different elements to it.
But I am unable to place the rotors on the sockets of the body as is done in Blueprint in the video.

The rotors are displayed but remain in the Zero position and rotate. I use SetupAttachment() with the parent socket name as 2nd argument.
Do I have to do anything else to make this work?

This is my code:

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

	// Structure to hold one-time initialization
	struct FConstructorStatics
	{
		ConstructorHelpers::FObjectFinderOptional<UStaticMesh> BodyMesh;
		ConstructorHelpers::FObjectFinderOptional<UStaticMesh> MainRotorMesh;
		ConstructorHelpers::FObjectFinderOptional<UStaticMesh> MainRotorBladesMesh;
		ConstructorHelpers::FObjectFinderOptional<UStaticMesh> RearRotorMesh;
		ConstructorHelpers::FObjectFinderOptional<UStaticMesh> RearBladeMesh;
		FConstructorStatics()
			: BodyMesh(TEXT("/Game/Assets/Helicopter/main_body.main_body"))
			, MainRotorMesh(TEXT("/Game/Assets/Helicopter/main_rotor.main_rotor"))
			, MainRotorBladesMesh(TEXT("/Game/Assets/Helicopter/main_rotor_blade.main_rotor_blade"))
			, RearRotorMesh(TEXT("/Game/Assets/Helicopter/rear_rotor.rear_rotor"))
			, RearBladeMesh(TEXT("/Game/Assets/Helicopter/rear_rotor_blade.rear_rotor_blade"))
		{
		}
	};
	static FConstructorStatics ConstructorStatics;

	// Create static mesh component
	BodyMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Body_Mesh"));
	BodyMesh->SetStaticMesh(ConstructorStatics.BodyMesh.Get());	
	RootComponent = BodyMesh;

	MainRotorMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Main_Rotor_Mesh"));
	MainRotorMesh->SetStaticMesh(ConstructorStatics.MainRotorMesh.Get());
	MainRotorMesh->SetupAttachment(BodyMesh, "main_rotor"); // Does not set good position and rotation

	MainRotorBladesMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Main_Rotor_Blades_Mesh"));
	MainRotorBladesMesh->SetStaticMesh(ConstructorStatics.MainRotorBladesMesh.Get());	
	MainRotorBladesMesh->SetupAttachment(MainRotorMesh);
	
	RearRotorMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Rear_Rotor_Mesh"));
	RearRotorMesh->SetStaticMesh(ConstructorStatics.RearRotorMesh.Get());	
	RearRotorMesh->SetupAttachment(BodyMesh, "trail_rotor"); // Does not set good position and rotation

	RearBladeMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Rear_Blade_Mesh"));
	RearBladeMesh->SetStaticMesh(ConstructorStatics.RearBladeMesh.Get());	
	RearBladeMesh->SetupAttachment(RearRotorMesh);
}

If i put the SetupAttachment() functions in BeginPlay(), it change nothing.
If i put the SetupAttachment() functions in OnConstruction(), le position of the rotor is change but is not in the good position.

Maybe i should use other functions ?

I have already tested with the same result :frowning:

I’ve noticed that attaching to sockets doesn’t work all that well in the constructor. Try executing attachment either under OnConstruction() or BeginPlay(), that should do the trick.

YOu can try using AttachToComponent() instead of SetupAttachment(), and try various options for FAttachmentTransformRules

i have noticed that:

UStaticMeshSocket* socket = (UStaticMeshSocket*)BodyMesh->GetSocketByName(FName("main_rotor"));
// => return NULL

UStaticMeshSocket* socket2 = (UStaticMeshSocket*)BodyMesh->GetStaticMesh()->FindSocket(FName("main_rotor"));
// => return NULL


FVector socketLocation = BodyMesh->GetSocketLocation("main_rotor");
FString msg = FString::Printf(TEXT("socketLocation: %f %f %f"), socketLocation.X, socketLocation.Y, socketLocation.Z);
GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, msg );
// => Display the location of the body not the socket


TArray<FName> socketNamesList = BodyMesh->GetAllSocketNames();
FString msgNum = FString::Printf(TEXT("Socket Num: %d"), socketNamesList.Num());
GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, msgNum); // Display 2. It's OK

for (int i = 0; i < socketNamesList.Num(); i++)
{
		FName name = socketNamesList[i];
		GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, name.ToString()); // Display "main_rotor" and "trail_rotor"
}

Why some functions seems to find the “main_rotor” soket and other function seems to nor find it ?
It seems tha my socket is not used by SetupAttachment() ou AttachToComponent()

I think here: BodyMesh->GetSocketLocation(“main_rotor”); you should also use FName:

  1. BodyMesh->GetSocketLocation(FName(“main_rotor”));