Non-BlockAll collision on objects added during ConstructionScript

I have a ConstructionScript that calls a C++ function. The C++ function adds several components to the actor. I’m trying to add a UBoxComponent in order to block the player from moving through an area, and I’m getting odd behavior I cannot explain.

If I have it set to BlockAll, it modifies the navmesh as appropriate and the player cannot walk in this area. I don’t know if it’s registering actual collisions, because if I use a different collision profile name, the player can walk right through it.

I know the collision profile works on its own because a component added manually to the actor behaves as expected. I also know it’s placed in the right spot because I can see the outline of the box in the editor.

So, everything works independently; but when I try to make a component with that collision enabled, stuff breaks.

Code included:

// "Parent" is a component that this is meant to be a child of - I'm attaching many components to this and, with this exception, they all work as expected
UBoxComponent *component = ConstructObject<UBoxComponent>(UBoxComponent::StaticClass(), Parent);
component->bCreatedByConstructionScript = true;
component->AttachTo(Parent);
component->SetBoxExtent(FVector(300, 300, 300)); // just for the sake of making it big enough that I can walk through it easily
component->SetCollisionProfileName("PlayerBlocker"); // this is the custom collision profile name; I've walked through this in the debugger and it's finding the right profile
component->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
component->bCanEverAffectNavigation = true; // I think this might be the default value
component->bShouldUpdatePhysicsVolume = true; // This, and the next line, are probably unnecessary, but shouldn't hurt
component->UpdatePhysicsVolume(true);
component->RegisterComponent(); // This is supposed to register the physics data, but as near as I can tell it's registered before then

Any ideas? I am out of them.

Alright, finally tracked down the issue.

It appears that the process of playing the game goes through all the game entities and makes copies of them. This requires that the game entities be marked properly for copying. There’s an internal array which lists the components which should be copied. You don’t have to poke this array manually, though - here’s the magic incantation:

myactor->FinishAndRegisterComponent(mynewcomponent);

Keep in mind that the broken behavior caused by not doing this seems to be inconsistently broken. Sometimes it works. Sometimes it doesn’t! It’s very unpredictable.

Note that this function calls RegisterComponent on its own, so you don’t have to do it yourself.

As near as I can tell, this works by registering a component to be serialized. This would imply to me that you should always use this if you expect your games to save properly and/or network travel to work properly.

Finally, keep in mind that Weird Stuff might happen if you accidentally call this twice on the same component. You’ll end up with two entries in the serializable-components array. Is that a problem? I dunno! But it sounds like it might be a problem, so be careful.

I don’t know if this is the right solution, but it seems to be a working solution, so I’ll take it.