Calling SetNotifyRigidBodyCollision() on skeletal meshes doesn't work

When you have a USkeletalMeshComponent that has “Simulation Generates Hit Events” set to false by default, calling SetNotifyRigidBodyCollision(true) won’t actually apply the new setting to the body instances. This is because in FBodyInstance::UpdatePhysicsFilterData(), it checks if it’s on a skeletal mesh, then it uses the notify collisions value stored in the skeletal meshes BodyInstance member to determine whether to enable hit events.

The problem is that the USkeletalMeshComponent::SetNotifyRigidBodyCollisions() override doesn’t actually update the value on its BodyInstance member, it only updates the ones in the Bodies array, leading to the function call doing basically nothing. I haven’t been able to check this in 4.14 sorry, but I didn’t see a fix in the release notes.

Hello,

I don’t see any direct changes to that function between 4.13 and 4.14 myself. Would it be possible for you to provide a reproduction case of some sort? Either a list of steps or a sample project would be useful. I’m not familiar with this function or how to access what it is setting.

Ok so I checked around some more and it turns out it’s been like this for ages and it might be intended behaviour, it just seems badly designed and doesn’t have behaviour consistent with other primitives. At this point though, it might break too much in current projects for it to be worth changing it, since you can work around it easily. So this would be more of a design decision than a bug fix.

To see the issue, create a BP with a skeletal mesh, enable collisions, enable “Simulation Generates Hit Events”, and attach an event to the OnComponentHit event and add a breakpoint on it so you know it’s being called. Go to the skeletal meshes physics asset and turn on “Simulation Generates Hit Events” on a few of the individual bone bodies. Now play and make something hit those bodies so you know everything’s set up right and the event is firing.

Now go back to the skeletal mesh component on the BP and turn off “Simulation Generates Hit Events” and instead call SetNotifyRigidBodyCollision(true) on the skeletal mesh during begin play. Now play again and the hit events won’t fire. You would expect that SetNotifyRigidBodyCollision() would enable hit events the same as it does for static meshes, but it doesn’t.

What it’s really doing is overriding all the notify bools on the individual bone bodies (TArray Bodies member var) , rather than setting it for the skeletal mesh component itself (FBodyInstance *BodyInstance member var, which is the one you see in BP defaults).

Skeletal mesh component has other functions specifically for setting notify on bone bodies, it would be more useful and consistent to have SetNotifyRigidBodyCollision() affect BodyInstance only, and leave the individual bones alone. So the fix would be to change the code to this

void USkeletalMeshComponent::SetNotifyRigidBodyCollision(bool bNewNotifyRigidBodyCollision) { BodyInstance->SetInstanceNotifyRBCollision(bNewNotifyRigidBodyCollision); OnComponentCollisionSettingsChanged(); }

Thank you for that information. There was one thing I needed to change when following your steps and that was to enable Simulate Physics on the actor with the skeletal mesh, since Simulation Generates Hit Events only affects physics simulation. After doing that, I’m seeing the same behavior you’re seeing.

As you mentioned, I’m not sure if this would be considered a bug as this could be intentional but I’ll need to pose that to the people in charge of this part of the engine’s development. I’ll try speaking to them and let you know.

Hello,

I’m not sure why I’m seeing different results now but I’m not seeing this behavior anymore when testing this again. In the below screenshot, you can see the setup for my blueprint with the skeletal mesh. With Simulation Generates Hit Events disabled and even without it enabled on any of the bodies in the Physics Asset, the print string connected to OnComponentHit is still triggered when I walk into the actor with Pawn whose collision is coming from a capsule component.

What about in C++?

As mentioned above, I had this issue until I added a line to manually enable rigid body collision on the skeletal mesh component body instance.

I can confirm that this works for me as well. In my case, I added SetInstanceNotifyRBCollision after calling SetNotifyRigidBodyCollision. Without this line of code, SetNotifyRigidBodyCollision does nothing.

Thanks :slight_smile:

Thank you for this.

I could not figure out why my quick Blueprint test worked, but doing a similar thing in C++ but using PrimitiveRoot->SetNotifyRigidBodyCollision(true) didn’t have the same results.

Adding the following before SetNotifyRigidBodyCollision() solved it:

		if (USkeletalMeshComponent* SkeletalMeshComponent = Cast<USkeletalMeshComponent>(PrimitiveRoot))
		{
			SkeletalMeshComponent->BodyInstance.SetInstanceNotifyRBCollision(true);
		}

And yes, this does seem a bit backwards :slight_smile:

1 Like