Hello,
I’m working on a vehicle game in c++. So far, I got a vehicle model with only 4 wheels and root bone which is working perfectly with UE4’s WheeledVehicle system. What I’m trying to do is creating door, hood, baggage, wiper etc. animations. After I seen a lot of difficulties in only bone based solutions, I decided to use physics constraint components for connecting physical-movable parts to the car body.
http://burakertugrul.com/files/VehicleBug/Works.gif
I have properly set all necessary physics constraint components in the blueprint up. Works perfectly when I press play. I have created two modules on this. First one is disabling physics constraint components and turning collisions, physics simulation of relevant static mesh components off to be able to change rotations of these parts without physics interaction. This module works correctly.
http://burakertugrul.com/files/VehicleBug/Stopping.gif
FConstraintAndComponent* Current;
for (int32 i = 0; i < ConstraintsAndComponents.Num(); i++)
{
Current = &ConstraintsAndComponents[i];
if (Current->PhysicsConstraintComponent)
{
if (Current->PhysicsConstraintComponent->IsValidLowLevel())
{
Current->PhysicsConstraintComponent->DestroyComponent(false);
}
}
if (Current->StaticMeshComponent)
{
if (Current->StaticMeshComponent->IsValidLowLevel())
{
Current->StaticMeshComponent->SetSimulatePhysics(false);
Current->StaticMeshComponent->SetCollisionProfileName(FName("NoCollision"));
Current->StaticMeshComponent->AttachTo(GetMesh(), NAME_None, EAttachLocation::KeepRelativeOffset, true);
Current->StaticMeshComponent->SetRelativeTransform(FTransform(FRotator::ZeroRotator, FVector::ZeroVector, FVector(1.0f, 1.0f, 1.0f)));
}
}
}
But weirdly, second module which is created to spawn a new UPhysicsConstraintComponent and to assign initial parameters of ConstraintInstance to the newly created one, works buggy. It creates the new constraint and assign limits correctly, but it never stops swinging. Doors are behaving just like a chicken that wants to fly.
http://burakertugrul.com/files/VehicleBug/Buggy.gif
FConstraintAndComponent* Current;
for (int32 i = 0; i < ConstraintsAndComponents.Num(); i++)
{
Current = &ConstraintsAndComponents[i];
if (Current->PhysicsConstraintComponent)
{
if (Current->PhysicsConstraintComponent->IsValidLowLevel())
{
Current->PhysicsConstraintComponent->DestroyComponent(false);
}
}
TArray<UActorComponent*> StaticMeshComponents = this->GetComponentsByClass(UStaticMeshComponent::StaticClass());
bool FirstFound = false, SecondFound = false, SecondIsTheMesh = false;
UPrimitiveComponent* ConstraintComponent_1 = nullptr;
UPrimitiveComponent* ConstraintComponent_2 = nullptr;
UStaticMeshComponent* TempStaMeshComp = nullptr;
if (Current->Constraint_ComponentName_2 == FName("Mesh"))
{
SecondFound = true;
SecondIsTheMesh = true;
ConstraintComponent_2 = GetMesh();
}
for (int32 j = 0; j < StaticMeshComponents.Num(); j++)
{
TempStaMeshComp = (UStaticMeshComponent*)StaticMeshComponents[j];
if (TempStaMeshComp)
{
if (TempStaMeshComp->ComponentTags.Num() > 0)
{
if (!FirstFound)
{
if (TempStaMeshComp->ComponentTags[0] == Current->Constraint_ComponentName_1)
{
FirstFound = true;
ConstraintComponent_1 = TempStaMeshComp;
if (SecondFound) break;
else continue;
}
}
if (!SecondFound)
{
if (TempStaMeshComp->ComponentTags[0] == Current->Constraint_ComponentName_2)
{
SecondFound = true;
ConstraintComponent_2 = TempStaMeshComp;
if (FirstFound) break;
else continue;
}
}
}
}
}
if (FirstFound && SecondFound)
{
if (Current->StaticMeshComponent)
{
if (Current->StaticMeshComponent->IsValidLowLevel())
{
Current->StaticMeshComponent->SetSimulatePhysics(true);
Current->StaticMeshComponent->SetCollisionProfileName(FName("PhysicsActor"));
}
}
FConstraintInstance ConstraintInstance;
ConstraintInstance.AngularRotationOffset = Current->AngularRotationOffset;
ConstraintInstance.AngularSwing1Motion = Current->Swing1Motion;
ConstraintInstance.AngularSwing2Motion = Current->Swing2Motion;
ConstraintInstance.AngularTwistMotion = Current->TwistMotion;
ConstraintInstance.Swing1LimitAngle = Current->Swing1Motion_Angle;
ConstraintInstance.Swing2LimitAngle = Current->Swing2Motion_Angle;
ConstraintInstance.TwistLimitAngle = Current->TwistMotion_Angle;
ConstraintInstance.AngularDriveMode = EAngularDriveMode::SLERP;
ConstraintInstance.bDisableCollision = 1;
FString IxToAppend = FString::FromInt(GeneratedConstraintNo++);
FString NameOfComponent = Current->ActualConstraintComponentName.ToString();
Current->PhysicsConstraintComponent = NewObject<UPhysicsConstraintComponent>(this, FName(*NameOfComponent.Append(IxToAppend)));
Current->PhysicsConstraintComponent->ConstraintInstance = ConstraintInstance;
Current->PhysicsConstraintComponent->AttachTo(Current->ConstraintComponentParent, NAME_None, EAttachLocation::KeepRelativeOffset, false);
Current->PhysicsConstraintComponent->RegisterComponent();
Current->PhysicsConstraintComponent->SetRelativeTransform(Current->Constraint_RelativeTransform);
Current->PhysicsConstraintComponent->ComponentTags.Add(Current->Constraint_ComponentName_1);
Current->PhysicsConstraintComponent->ComponentName1.ComponentName = Current->Constraint_ComponentName_1;
Current->PhysicsConstraintComponent->ComponentName2.ComponentName = Current->Constraint_ComponentName_2;
Current->PhysicsConstraintComponent->OverrideComponent1 = ConstraintComponent_1;
Current->PhysicsConstraintComponent->OverrideComponent2 = ConstraintComponent_2;
Current->PhysicsConstraintComponent->ConstraintInstance.ConstraintBone1 = NAME_None;
Current->PhysicsConstraintComponent->ConstraintInstance.ConstraintBone2 = SecondIsTheMesh == true ? FName("Root") : NAME_None;
Current->PhysicsConstraintComponent->UpdateConstraintFrames();
Current->PhysicsConstraintComponent->ConstraintInstance.InitConstraint(Current->PhysicsConstraintComponent,
ConstraintComponent_1->GetBodyInstance(NAME_None),
ConstraintComponent_2->GetBodyInstance(SecondIsTheMesh == true ? FName("Root") : NAME_None),
1.0f);
}
}
I have tried changing all of the parameters, disabling soft limits, raising or lowering stiffness or damping etc. Didn’t work. Thank you for your help in advance.