Cannot disable collision of Components when Actor has collision disabled. Please reconsider UE-61876

When you disable the collision of an Actor and then try to set CollisionEnabled of an attached PrimitiveComponent to NoCollision, the PrimitiveComponent will keep its former CollisionEnabled setting internally.
The bug report has been declared as “Won’t Fix” without a public statement.

The behavior can be reproduced by the following example, where “Component” is a registered Component of “Actor”:

	Actor->SetActorEnableCollision(true);
	Component->SetCollisionEnabled(ECollisionEnabled::QueryOnly);
	UE_LOG(LogTemp, Warning, TEXT("CollisionEnabled: %i"), (int)Component->GetCollisionEnabled());
	// Prints 1 = QueryOnly. This is correct.

	Actor->SetActorEnableCollision(false);
	Component->SetCollisionEnabled(ECollisionEnabled::NoCollision);
	Actor->SetActorEnableCollision(true);
	UE_LOG(LogTemp, Warning, TEXT("CollisionEnabled: %i"), (int)Component->GetCollisionEnabled());
	// Still prints 1 = QueryOnly. Should print 0 = NoCollision instead.

This is the result of the following code in PrimitiveComponentPhysics.cpp line 894

void UPrimitiveComponent::SetCollisionEnabled(ECollisionEnabled::Type NewType)
{
	if (BodyInstance.GetCollisionEnabled(bCheckOwner=true) != NewType)    // <--- this line
	{
		BodyInstance.SetCollisionEnabled(NewType);

		EnsurePhysicsStateCreated();
		OnComponentCollisionSettingsChanged();

		if(IsRegistered() && BodyInstance.bSimulatePhysics && !IsWelded())
		{
			BodyInstance.ApplyWeldOnChildren();
		}
	}
}

As can be seen “if (BodyInstance.GetCollisionEnabled(bCheckOwner=true) != NewType)” checks the owner’s settings and thus, if the owner’s collision is disabled and NewType equals NoCollision as well the method does nothing although the PrimitiveComponent’s internal setting is unequal to NewType.
Using bCheckOwner=false in the if-query could fix the problem.

Or even something along the following lines:

void UPrimitiveComponent::SetCollisionEnabled(ECollisionEnabled::Type NewType)
{
	if (BodyInstance.GetCollisionEnabled(false) != NewType)
	{
		bool const bHasReallyChanged = BodyInstance.GetCollisionEnabled(true) != NewType;

		BodyInstance.SetCollisionEnabled(NewType);

		if (bHasReallyChanged)
		{
			EnsurePhysicsStateCreated();
			OnComponentCollisionSettingsChanged();

			if (IsRegistered() && BodyInstance.bSimulatePhysics && !IsWelded())
			{
				BodyInstance.ApplyWeldOnChildren();
			}
		}
	}
}

Could you kindly reconsider this bug report or give a statement on why this bug won’t be fixed?

1 Like