4.6 UPrimitiveComponent::UnWeldFromParent() crash

Hi,
I have blueprint with some destructible components attached to static mesh component, and when I’m changing a level contanins this BP to another and again to mentioned level, then close the editor the engine will crash.

Stack trace:

 	UE4Editor-Core-Win64-Debug.dll!StaticFailDebug(const wchar_t * Error, const char * File, int Line, const wchar_t * Description, bool bIsEnsure) Line 190	C++
 	UE4Editor-Core-Win64-Debug.dll!FDebug::AssertFailed(const char * Expr, const char * File, int Line, const wchar_t * Format, ...) Line 224	C++
 	UE4Editor-Engine-Win64-Debug.dll!FBodyInstance::InitBody(UBodySetup * Setup, const FTransform & Transform, UPrimitiveComponent * PrimComp, FPhysScene * InRBScene, physx::PxAggregate * InAggregate) Line 959	C++
>	UE4Editor-Engine-Win64-Debug.dll!UPrimitiveComponent::UnWeldFromParent() Line 681	C++
 	UE4Editor-Engine-Win64-Debug.dll!USceneComponent::DetachFromParent(bool bMaintainWorldPosition) Line 927	C++
 	UE4Editor-Engine-Win64-Debug.dll!USceneComponent::OnComponentDestroyed() Line 260	C++
 	UE4Editor-Engine-Win64-Debug.dll!UActorComponent::BeginDestroy() Line 303	C++
 	UE4Editor-Engine-Win64-Debug.dll!USceneComponent::BeginDestroy() Line 1273	C++
 	UE4Editor-Engine-Win64-Debug.dll!UPrimitiveComponent::BeginDestroy() Line 733	C++
 	UE4Editor-Engine-Win64-Debug.dll!UMeshComponent::BeginDestroy() Line 20	C++

This assert was fired BodyInstance.cpp-> FBodyInstance::InitBody:

// whenever update filter, this check will trigger, it seems it's best to know when we initialize body instead. 
check(BodySetup.IsValid());

The engine was trying to unweld destructible component but body instance for this component was invalid!

I started digging why engine welding destructible components.

First of all the destructible component in BP isn’t flagged with bAutoWeld, bAutoWeld is set to false.
I think this flag is ommited by engine in the USceneComponent::AttachTo, not sure if it is a bug or feature, I believe the engine should check bAutoWeld before welding:

>	UE4Editor-Engine-Win64-Debug.dll!UPrimitiveComponent::WeldToImplementation(USceneComponent * InParent, FName ParentSocketName, bool bWeldSimulatedChild) Line 625	C++
 	UE4Editor-Engine-Win64-Debug.dll!USceneComponent::AttachTo(USceneComponent * Parent, FName InSocketName, EAttachLocation::Type AttachType, bool bWeldSimulatedBodies) Line 905	C++
 	UE4Editor-Engine-Win64-Debug.dll!USceneComponent::K2_AttachTo(USceneComponent * InParent, FName InSocketName, EAttachLocation::Type AttachLocationType, bool bWeldSimulatedBodies) Line 711	C++
 	UE4Editor-Engine-Win64-Debug.dll!USceneComponent::execK2_AttachTo(FFrame & Stack, void * const Result) Line 82	C++
 	UE4Editor-CoreUObject-Win64-Debug.dll!UFunction::Invoke(UObject * Obj, FFrame & Stack, void * const Result) Line 3699	C++
 	UE4Editor-CoreUObject-Win64-Debug.dll!UObject::CallFunction(FFrame & Stack, void * const Result, UFunction * Function) Line 395	C++

Second why destructibles are welded ???

I am looking at UPrimitiveComponent::WeldToImplementation function

BI->bWelded = true;
//There are multiple cases to handle:
//Root is kinematic, simulated
//Child is kinematic, simulated
//Child always inherits from root
//if root is kinematic simply set child to be kinematic and we're done
if (RootComponent->IsSimulatingPhysics(SocketName) == false)
{
	BI->WeldParent = NULL;
	SetSimulatePhysics(false);
	return false;	//return false because we need to continue with regular body initialization
}

//root is simulated so we actually weld the body
FTransform RelativeTM = RootComponent == AttachParent ? GetRelativeTransform() : GetComponentToWorld().GetRelativeTransform(RootComponent->GetComponentToWorld());	//if direct parent we already have relative. Otherwise compute it
RootBI->Weld(BI, GetComponentToWorld());
BI->WeldParent = RootBI;

BI->bWelded = true; is set before RootBI->Weld(BI, GetComponentToWorld()); why?

What is means ? Is it welded or not?

Besides, why BI->bWelded is set to true without checking RootBI->Weld(BI, GetComponentToWorld()); result?

I moved BI->bWelded = true; under if (RootComponent->IsSimulatingPhysics(SocketName) == false) check.

//There are multiple cases to handle:
//Root is kinematic, simulated
//Child is kinematic, simulated
//Child always inherits from root

//if root is kinematic simply set child to be kinematic and we're done
if (RootComponent->IsSimulatingPhysics(SocketName) == false)
{
	BI->WeldParent = NULL;
	SetSimulatePhysics(false);
	return false;	//return false because we need to continue with regular body initialization
}

BI->bWelded = true;
//root is simulated so we actually weld the body
FTransform RelativeTM = RootComponent == AttachParent ? GetRelativeTransform() : GetComponentToWorld().GetRelativeTransform(RootComponent->GetComponentToWorld());	//if direct parent we already have relative. Otherwise compute it
RootBI->Weld(BI, GetComponentToWorld());
BI->WeldParent = RootBI;

And I can’t reproduce this crash anymore

Conclusions:

  1. I think welding destructibles should be disabled by default
  2. Set BI->bWelded = true; when the Weld function welded something.

What do you guys think about it?

Regards

Pierdek

bump …

bump again and again

Hi sorry for the long wait.
There have been some fixes for welding code which should be in the 4.7 preview so I’d be curious to know if the issue still happens (though it sounds like you can’t repro it).

The welding code needs a big refactor which makes some of the logic hard to follow.
We have a plan to do this in the coming year which will hopefully help with a lot of these issues.

Please let me know if this is still crashing, sorry for the pain!