Hello everyone !
I have a problem with the usage of USceneComponent::SetWorldTransform
, It’s usage on some case seams to be highly imprecise (or I am working under false assumptions, I’m quite new to UE).
Basically I have a script which inherit from a USceneComponent
, and possess a function that goes like this :
void URWHHandleableElement::OnTranform_Implementation(const FTransform& newTransform, bool didMove, bool didRotate, bool didScale)
{
SetWorldTransform(newTransform);
}
My USceneComponent
is in a blueprint, all of its parent have an identity quaternion, and its rotation is relative to them.
What I expect is that the FTransform
of the USceneComponent
(ComponentToWorld
?) would have a rotation equal to the set newTransform
’s rotation.
What I get most of the time is a value that is similar but not at all exact, by quite a visible marging in fact.
(But the same newTransform
would always result in the same false result at the end).
void URWHHandleableElement::OnTranform_Implementation(const FTransform& newTransform, bool didMove, bool didRotate, bool didScale)
{
UE_LOG(LogTemp, Log, TEXT("[OnTranform_Implementation] SET : %s"), *RSTools::QuatToFString(newTransform.GetRotation()));
//LogTemp: [OnTranform_Implementation] SET : { W: 0.979653; X : 0.0; Y : 0.0; Z : -0.200698}
SetWorldTransform(newTransform);
UE_LOG(LogTemp, Log, TEXT("[OnTranform_Implementation] GET After : %s"), *RSTools::QuatToFString(GetComponentTransform().GetRotation()));
//LogTemp: [OnTranform_Implementation] GET After : { W: 0.969898; X : 0.0; Y : 0.0; Z : -0.24351}
}
For scale, this sometime represent an Euler difference of more than 3 degree. So calling again the function with the new rotation will move the object again when it should be standing still.
Looking at the USceneComponent
, I can see that it try to deduce a relative FTransform
from a parentToWorld
FTransform
.
So copying the code to function give this result :
'
UE_LOG(LogTemp, Log, TEXT("[OnTranform_Implementation] SET : %s"), *RSTools::QuatToFString(newTransform.GetRotation()));
//LogTemp: [OnTranform_Implementation] SET : { W: 0.979653; X : 0.0; Y : 0.0; Z : -0.200698}
const FTransform ParentToWorld = GetAttachParent()->GetSocketTransform(GetAttachSocketName());
FTransform RelativeTM = newTransform.GetRelativeTransform(ParentToWorld);
UE_LOG(LogTemp, Log, TEXT("[OnTranform_Implementation] ParentToWorld : %s"), *RSTools::QuatToFString(ParentToWorld.GetRotation()));
//LogTemp: [OnTranform_Implementation] ParentToWorld : { W: 1.0; X : 0.0; Y : 0.0; Z : 0.0}
UE_LOG(LogTemp, Log, TEXT("[OnTranform_Implementation] RelativeTM : %s"), *RSTools::QuatToFString(RelativeTM.GetRotation()));
//LogTemp: [OnTranform_Implementation] RelativeTM : { W: 0.977243; X : 0.0; Y : 0.0; Z : -0.212124}
It is to be noted than if I drop
SetWorldTransform(newTransform);
for
GetOwner()->SetActorTransform(newTransform);
Then all work as expected, GetComponentTransform().GetRotation()
now return precisely the rotation value of newTransform
. But my understanding is that in this case I would not move the component, but the owning AActor
, which is not quite what I would like to do.
Thank you for taking the time to read me, and I hope someone may be able to help me understand what is happening there.