How i can disable specific body collision in physics asset on runtime?

Hello everyone! How i can disable specific body collision in physics asset on runtime? For example, i need disable arm or leg collision in Mannequin. I try use GetPhysicsAsset()->DisableCollision but it not work.

267120-безымянныи.png

1 Like

Have you found a solution?

No (8 characters needed)

ok, I found the answer!

HideBoneByName() does actually work as intended. I tested it on my project and confirmed with C++ implementation.
HideBoneByName is implemented in USkinnedMeshComponent and inside it calls HideBone(). HideBone() is overridden in USkeletalMeshComponent and it does account for EPhysBodyOp option and it effectively terminates all collisions for this bone and its children by calling TermBodiesBelow(). The only things is that collision bodies are still visible in debug (that what was confusing me, and I thought that collisions are still there). So what is needed to use for PhysBodyOption is “PBO_Term” to disable collisions.

If you do not want to hide a bone but just disable a collision, I would imagine you just need to call TermBodiesBelow()

void USkeletalMeshComponent::HideBone( int32 BoneIndex, EPhysBodyOp PhysBodyOption)
{
	Super::HideBone(BoneIndex, PhysBodyOption);

	if (!SkeletalMesh)
	{
		return;
	}

	if (BoneSpaceTransforms.IsValidIndex(BoneIndex))
	{
		BoneSpaceTransforms[BoneIndex].SetScale3D(FVector::ZeroVector);
		bRequiredBonesUpToDate = false;

		if (PhysBodyOption != PBO_None)
		{
			FName HideBoneName = SkeletalMesh->RefSkeleton.GetBoneName(BoneIndex);
			if (PhysBodyOption == PBO_Term)
			{
				TermBodiesBelow(HideBoneName);
			}
		}
	}
	else
	{
		UE_LOG(LogSkeletalMesh, Warning, TEXT("HideBone: Invalid Body Index has entered. This component doesn't contain buffer for the given body."));
	}
}

Thanks for help!

Hi, is this reversible? As far as I tried, once you terminate PBO you can’t turn it back on.

Try this It’s Work For me. can also set at runtime: GetMesh()->GetBodyInstance(BoneName)->SetShapeCollisionEnabled(0, ECollisionEnabled::NoCollision);

1 Like

Can you publish this as a standalone function that can be used in blueprint? Really need it…

In SkeletalMeshComponent.cpp add this function:

    void USkeletalMeshComponent::ChangeCollisionOnPhysicsBody(int32 BoneIndex, ECollisionEnabled::Type CollisionType)
{	
	FBodyInstance* BI = GetBodyInstance();
	if(BI && BI->GetCollisionEnabled() != CollisionType)
	{		
		BI->SetShapeCollisionEnabled(BoneIndex, CollisionType);		
	}
} 

In SkeletalMeshComponent.h, add the declaration:

   UFUNCTION(BlueprintCallable, Category = "Components|SkeletalMesh")
	void ChangeCollisionOnPhysicsBody(int32 BoneIndex, ECollisionEnabled::Type CollisionType);

Then you can call it from blueprint

350112-tes.png

EDIT: Nvm, illYay is right, I don’t think this is a solution.

Does this actually work for you?

I tried something similar where I wanted to change collision profiles on a per bone basis.

    BodyInstance->SetCollisionProfileName(<SomeName>);

But this ends up returning the main skeletal mesh’s settings for exactly this.

https://github.com/EpicGames/UnrealEngine/blob/99b6e203a15d04fc7bbbf554c421a985c1ccb8f1/Engine/Source/Runtime/Engine/Private/PhysicsEngine/BodyInstance.cpp#L903

For example, after I try to set impulse on a bone after detaching it for a dismemberable mesh system, it fails because the main skeleton is set to the CharacterMesh profile and not Ragdoll like I’m trying to set the body part to.

It almost seems like it’s actually a bug if this works for you, but it does give the desired behavior. I want that code in BodyInstance.cpp to not exist too, but you’d probably have to modify the source and there might be some unintended consequences.

I also noticed in the code:

BI->SetShapeCollisionEnabled(BoneIndex, CollisionType);

BoneIndex being passed is normally the ShapeIndex in the body, not the mesh bone index. A Body should have multiple shapes. I also tried this code and it failed.

For anyone finding this via Google, I implemented @llPLUKll solution. It works for me. I added it as a function to my custom library:

void UCustomBlueprintFunctionLibrary::ChangeCollisionOnPhysicsBody(USkeletalMeshComponent* skeletalMesh, FName boneName, ECollisionEnabled::Type CollisionType)
{
	skeletalMesh->GetBodyInstance(boneName)->SetShapeCollisionEnabled(0, CollisionType);
}
4 Likes

This works. Thanks!

How this made in blueprints without c++?

unfortunately there is no access to individual physics bodies within blueprint, gotta go into c++

To anyone trying to find an easy solution I can recommend this plugin: Collision Disabler in Code Plugins - UE Marketplace

I getting errors in visual studio. Clear declaration in meshcomponent inposible because it read only looks…


Don’t use my solution, it doesn’t work. I’m not sure if you can change collision settings on a per body level. I will dig into it more when I have time

I create cusstum library but don known how get reference of that library?
Untitled
Edit I fixed that. Instead void ChangeCollisionOnPhysicsBody(USkeletalMeshComponent* skeletalMesh, FName boneName, ECollisionEnabled::Type CollisionType); in .h I set static void ChangeCollisionOnPhysicsBody(USkeletalMeshComponent* skeletalMesh, FName boneName, ECollisionEnabled::Type CollisionType);