Set Collision Response on Instanced Static Mesh at Runtime

I have a custom trace channel (“Interact” in the image below), defaulted to ignore. At run time, I want to change certain instanced static mesh components to block the channel. Using the “Set Collision Response to Channel” node seems like it should work–and indeed, “Get Collision Response to a Channel” returns “Blocked” after executing the node (and “Ignore” before executing, as expected). So it seems like everything is working properly; but then a SphereTraceByChannel using the custom trace channel does not actually hit the instance. It works as I expect with static meshes, and the trace works with instanced static meshes if I set the collision in the editor rather than at run time. I was able to reproduce this in the default top-down template.

Starting the level with everything set to ignore the channel, executing “Set Collision Response to Channel” on both the static mesh (cube) and the instanced static mesh (sphere) results in hitting the static mesh but not the instanced static mesh:

268441-hit.jpg

Is this intended behavior for instanced static meshes? If so, why does “Get Collision Response to Channel” not match the actual collision behavior? Is there any way around this?

1 Like

In case anyone else wants to accomplish something similar, here’s the workaround I’ve settled on for now:
I duplicated the instanced static mesh component for the actor, setting the altered collision settings as desired on the duplicate component, and then whenever I want to update the collision settings I instead add an instance of the duplicate ISM using the transform of the original ISM, and remove the instance of of the original ISM.

This appears to still be the behavior even as recent as 4.26, whether a bug or intentional.

As an additional workaround that may be simpler, disabling and enabling collision on the instanced static mesh seems to updated the collision response. I’ve only tested it with trace channels and not full collision, but expect it works to fix that as well.

332170-workaround.png

2 Likes

This is still a thing in UE5.0 is someone else wonders…
Thanks for posting this, i started to lose my mind… :smiley:

My workaround for now is to delete all instances, change the profile, and recreate the instances.

This issue gets some good chunk of sanity out of me.

Same here haha. Glad I’m not alone

I’m trying to create a building that has several floors using modular assets, with the idea of using Instanced static meshes… Its a top down game, so when the player enters any floor, I want the floors above them (including every static mesh and NPCs) to go invisible, but I also need for to continue to patrol as usual. In order for this to work, I have to change the collision response to channel for the camera (so the camera clips through those hidden assets) and the camera boom distance does not change for the player upon entering, and the collision response to the channel of the mouse clicks, so I can click through the invisible assets, allowing the player to navigate as if those upper floors didn’t exist.

I can’t really disable and re-enable the collision of the ISMs, because if I hide the roof of the first level, which is the floor of the second level, the npcs above will fall down to the ground floor…
Removing and recreating the instances will not work either, because the npcs will still fall through the floor…

Is there another way to update the collisions settings for the instanced static meshes at runtime?

Since this issue seems to still be an issue at least with 5.2, figured I’d give this my solution in case anyone else also runs into it.
While disabling and enabling the collision works, that may also break other responses momentarily, so I found this neat little method buried in there.

InstancedStaticMeshComponent* MeshInst;

// ...

for (FBodyInstance* body : MeshInst->InstanceBodies)
{
	body->CopyRuntimeBodyInstancePropertiesFrom(&MeshInst->BodyInstance);
}

For a BP you’d have to throw something into a BlueprintFunctionLibrary it seems. Something like this (Unfortunately this still requires a C++ project, not sure how to get it into a BP only project short of modifying the engine itself…):

// .h
// class UMyBlueprintFunctionLibrary : ....
UFUNCTION(BlueprintCallable, Category = "InstancedStaticMesh Utilities")
void CopyCollisionResponses(class UInstancedStaticMeshComponent* Component);

// .cpp
#include "Components/InstancedStaticMeshComponent.h"

void UMyBlueprintFunctionLIbrary::CopyCollisionResponses(UInstancedStaticMeshComponent* Component)
{
	for (FBodyInstance* body : Component->InstanceBodies)
	{
		body->CopyRuntimeBodyInstancePropertiesFrom(&MeshInst->BodyInstance);
	}
}

Hope this helps someone :slight_smile: