Download

Component has local offset when spawn (located at world 0,0,0)

Hi!

I have created a simple actor in c++ with a scene component as root, a box component and a static mesh component.



        UPROPERTY(EditDefaultsOnly, Category = "Cell")
	USceneComponent* RootCmp;

	UPROPERTY(EditDefaultsOnly, Category = "Cell")
	UBoxComponent* DetectorCmp;

	UPROPERTY(EditDefaultsOnly, Category = "Cell")
	UStaticMeshComponent* CellMesh;


The constructor code is:



	RootCmp = CreateDefaultSubobject<USceneComponent>(TEXT("Root"));	
	SetRootComponent(RootCmp);

	DetectorCmp = CreateDefaultSubobject<UBoxComponent>(TEXT("Detector"));	
	DetectorCmp->AttachToComponent(RootCmp, FAttachmentTransformRules::KeepRelativeTransform);	
	
	CellMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("CellMesh"));
	CellMesh->AttachToComponent(RootCmp, FAttachmentTransformRules::KeepRelativeTransform);	


it’s pretty simple but I have an issue… When I spawn my object into the world, the box and static mesh components are located at world 0,0,0 so they have a local offset relative to my root component.

I have tried to set the relative location at 0,0,0 after AttachToComponent line and I have used SetupAttachment instead of AttachToComponent with no success. What’s wrong??

Thanks!

Use SetupAttachment instead of AttachToComponent, if you’re doing this in the constructor. Also, use the ObjectInitializer version of the Constructor. Not doing so nearly always causes headaches or random hard-to-track issues. e.g:



AMyClass::AMyClass(const FObjectInitializer& OI)
: Super(OI)
{
    	RootCmp = OI.CreateDefaultSubobject<USceneComponent>(this, TEXT("Root"));
	SetRootComponent(RootCmp);
}


Are you sure the Root Component isn’t also at world origin?

Had a similar problem…
I would spawn a weapon Actor, and StaticMeshComponent’s relative location would go crazy. I couldn’t get it to reset to 0, and have a gun at socket location. I listened this advice, and it worked like it should. :slight_smile:

Here’s the code:
ExampleWeapon.h


//It is important to use ObjectInitializer version, since RootComponent attachment can get buggy when trying to set it up in the constructor.
    AUrathaWeapon(const FObjectInitializer& OI);

    UPROPERTY(EditDefaultsOnly, Category = "Weapon")
    UBoxComponent* WeaponRoot;

    UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Weapon")
    UStaticMeshComponent* WeaponMeshComponent;

ExampleWeapon.cpp


AUrathaWeapon::AUrathaWeapon(const FObjectInitializer& OI) : Super(OI)
{
     // 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;

    //This is a recommendable way to create sub object when attachment to RootComponent is buggy (e.g. relative location is screwed).
    WeaponRoot = OI.CreateDefaultSubobject<UBoxComponent>(this, FName("WeaponRoot"));
    SetRootComponent(WeaponRoot);

    WeaponMeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(FName("WeaponMeshComponent"));
    //Use this instead of AttachToComponent when doing this in the constructor. Interestingly enough, AttachToComponent works as intended in Blueprint.
    WeaponMeshComponent->SetupAttachment(WeaponRoot);
}

ExampleCharacter.cpp


if (WeaponBlueprint)
    {
        //UE4 sometimes struggles with passing socket name as TEXT("SocketName"). Using this instead...
        FName SocketName("WeaponSocket");
        FActorSpawnParameters spawnParams;
        spawnParams.Owner = this;

        //Spawn weapon at 0,0,0 with 0,0,0 rotation. A precaution...
        Weapon = GetWorld()->SpawnActor<AUrathaWeapon>(WeaponBlueprint, FVector(0.f, 0.f, 0.f), FRotator(0.f, 0.f, 0.f), spawnParams);
        UE_LOG(LogTemp, Warning, TEXT("Weapon spawned!"));

        //Attach to player's hand. FINALLY WORKING!
        Weapon->AttachToComponent(GetMesh(), FAttachmentTransformRules::SnapToTargetIncludingScale, SocketName);
    }