I have got a UStaticMeshComponent which I rotate and scale non uniformly, in order to have a cylinder which connects two points. After scaling, checking for collision with LineTraceSingleByChannel returns no hit results. Before scaling, everything works fine, i.e. I get a valid hit result. All this is in the standalone executable, not the editor.
How do I preserve collision (or recreate it) after scaling a static mesh?
I use the following code to create the component:
UStaticMeshComponent* AWireActor::createCylinder(FVector startPosition, FVector endPosition)
{
UStaticMeshComponent *cylinder = NewObject<UStaticMeshComponent>(this);
cylinder->RegisterComponent();
cylinder->AttachTo(RootComponent);
cylinder->SetMobility(EComponentMobility::Movable);
// Make the wire sleeker (scale start and end size down) and center it, since the mesh has it's oirigin on the side, not the center.
cylinder->SetRelativeScale3D(FVector(0.1f, 0.1f, 1.0f));
// roatate to match start and end
alignCylinder(startPosition, endPosition, cylinder);
UStaticMesh* meshToUse = Cast<UStaticMesh>(StaticLoadObject(UStaticMesh::StaticClass(), nullptr,
TEXT("StaticMesh'/Game/StarterContent/Shapes/Shape_Cylinder.Shape_Cylinder'")));
cylinder->SetStaticMesh(meshToUse);
cylinder->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
cylinder->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Block);
// cylinder->SetCollisionObjectType(ECollisionChannel::ECC_WorldDynamic);
cylinder->SetMaterial(0, cylinderMaterial);
return cylinder;
}
This code is used to move the cylinder to the correct position:
void AWireActor::alignCylinder(FVector start, FVector end, UStaticMeshComponent *cylinder)
{
// rotate by 90° around X-axis to correct for the cylinder being aligned on the Z instead of the X axis.
cylinder->SetWorldRotation(FRotator(90.0f, 0.0f, 0.0f));
// add the rotation of the vector between start and end to align the cylinder with it.
cylinder->AddWorldRotation((end - start).Rotation());
// place the cylinder in the end location, since it's pivot is in there.
cylinder->SetWorldLocation(end);
// scale the cylinder up to properly reach both ends.
FVector min, max;
cylinder->GetLocalBounds(min, max);
float zScale = ((start - end).Size() / max.Size());
cylinder->SetRelativeScale3D(FVector(0.1f, 0.1f, zScale));
}
Wierdly enough this (buggy) scaling code does not break collision. However it doesn’t always scale the component correctly, so it’s not usable:
void AWireActor::alignCylinder(FVector start, FVector end, UStaticMeshComponent *cylinder)
{
// rotate by 90° around X-axis to correct for the cylinder being aligned on the Z instead of the X axis.
cylinder->SetWorldRotation(FRotator(90.0f, 0.0f, 0.0f));
// add the rotation of the vector between start and end to align the cylinder with it.
cylinder->AddWorldRotation((end - start).Rotation());
// place the cylinder in the end location, since it's pivot is in there.
cylinder->SetWorldLocation(end);
// scale the cylinder up to properly reach both ends.
float radius = 0.0f, halfHeight = 0.0f;
cylinder->CalcBoundingCylinder(radius, halfHeight);
float zScale = ((start - end).Size() / (halfHeight * 2.0f));
cylinder->SetRelativeScale3D(FVector(0.1f, 0.1f, zScale));
GEngine->AddOnScreenDebugMessage(-1, LOG_TIME, FColor::Green, FString("Scaled to ") + FString::SanitizeFloat(zScale)
+ FString("Height is ") + FString::SanitizeFloat(halfHeight));
}
A similar problem has been presented here, however there’s no solution: Problems with collision when non-uniformly scaling character - Character & Animation - Epic Developer Community Forums
Previously I used splines to create these wires, however they always had the same collision issue as described here, hence I abandoned them in favour of regular static meshes. Could this be a similar issue?