I have a component whose structure is an hierarchy of SceneComponents like this:
Point
----Rotator
--------Placer
------------VizSphere (UStaticMeshComponent)
I am adding this component (a UPoint) to my Pawn, and then offsetting its relative location in X by 500 units, like so:
FName NewPointName = MakeUniqueObjectName(this, UPoint::StaticClass(), TEXT("Point"));
UPoint* NewPoint = NewObject<UPoint>(this, UPoint::StaticClass(), NewPointName);
NewPoint->SetupAttachment(PawnRoot);
NewPoint->RegisterComponent();
CurrentPoint = NewPoint;
CurrentPoint->SetRelativeLocation(FVector(500.0f, 0.0f, 0.0f));
What I discovered though, is that if I try to get the world location of all the various sub-components (Rotator, Placer, VizSphere), they return (0,0,0) even though the Point has been moved 500 units. Weird. Through trying to debug this, I discovered that if I set the relative rotation and location of each of these components to any non-zero value, then they suddenly get updated with the correct world location. This happens even if I immediately set the rotation and location back to zero again.
Here is some code showing this:
LogPosition(CurrentPoint->GetComponentLocation(), "Point Location: ");
LogPosition(CurrentPoint->PointRotator->GetComponentLocation(), "Rotator Location before: ");
CurrentPoint->PointRotator->SetRelativeLocation(FVector(0.1f, 0.0f, 0.0f));
CurrentPoint->PointRotator->SetRelativeRotation(FRotator(0.1f, 0.0f, 0.0f));
CurrentPoint->PointRotator->SetRelativeLocation(FVector(0.0f, 0.0f, 0.0f));
CurrentPoint->PointRotator->SetRelativeRotation(FRotator(0.0f, 0.0f, 0.0f));
LogPosition(CurrentPoint->PointRotator->GetComponentLocation(), "Rotator Location after: ");
LogPosition(CurrentPoint->PointPlacer->GetComponentLocation(), "Placer Location before: ");
CurrentPoint->PointPlacer->SetRelativeLocation(FVector(0.1f, 0.0f, 0.0f));
CurrentPoint->PointPlacer->SetRelativeRotation(FRotator(0.1f, 0.0f, 0.0f));
CurrentPoint->PointPlacer->SetRelativeLocation(FVector(0.0f, 0.0f, 0.0f));
CurrentPoint->PointPlacer->SetRelativeRotation(FRotator(0.0f, 0.0f, 0.0f));
LogPosition(CurrentPoint->PointPlacer->GetComponentLocation(), "Placer Location after: ");
LogPosition(CurrentPoint->VizSphere->GetComponentLocation(), "VizSphere Location before: ");
CurrentPoint->VizSphere->SetRelativeLocation(FVector(0.1f, 0.0f, 0.0f));
CurrentPoint->VizSphere->SetRelativeRotation(FRotator(0.1f, 0.0f, 0.0f));
CurrentPoint->VizSphere->SetRelativeLocation(FVector(0.0f, 0.0f, 0.0f));
CurrentPoint->VizSphere->SetRelativeRotation(FRotator(0.0f, 0.0f, 0.0f));
LogPosition(CurrentPoint->VizSphere->GetComponentLocation(), "VizSphere Location after: ");
The LogPosition function is just debugging a vector position to UE_LOG. Here is the output of the above code:
Point Location: 500.0, 0.0, 0.0
Rotator Location before: 0.0, 0.0, 0.0
Rotator Location after: 500.0, 0.0, 0.0
Placer Location before: 0.0, 0.0, 0.0
Placer Location after: 500.0, 0.0, 0.0
VizSphere Location before: 0.0, 0.0, 0.0
VizSphere Location after: 500.0, 0.0, 0.0
As you can see, the Point’s location is correct immediately. But the Rotator, Placer, and VizSphere’s locations are only correct after setting their relative rotation and location to some tiny value, and then setting them back to zero again.
What’s going on here? Why do these components need their relative transforms to be fiddled with before they inherit the correct world location?