Programmatically spawned GeometryCollection has no physics?

Hi, I’m using 4.27 Chaos.

I’ve created a GeometryCollection in editor and I want to spawn it into my game at runtime via c++.

I’ve added a GeometryCollectionComponent to my actor and called SetRestCollection on it and passed the GeometryCollection. This seems to work and I do see the GeometryCollection mesh in the game. The issue is that it just hangs in the air and has no collisions. I expect it to fall to the ground and for it to collide with the player and the static mesh floor. This happens even if I enable gravity on the component and set its collision responses and channel. I also tried to break it via ApplyKinematicField(), but yeah, it doesn’t do anything either. If I call SetSimulatePhysics(true) on it, it just crashes.

I’ve tried a ton of different API calls and looked at the engine sources to see if I missed something, but nothing seems to work. It seems to be a more fundamental issue. The GeometryCollection is very simple. It’s based on a 2 triangle plane that I use everywhere in the game. It only has two pieces when fractured. All I did was create it, fracture it in the fracture editor, save it and load it at runtime.

Here’s a look at what the code looks like:

// In constructor
m_geometryCollectionComponent = CreateDefaultSubobject<UGeometryCollectionComponent>(STR_NAME_DESTRUCTIBLE_COMPONENT);

...

// At some point later during runtime.
if (m_geometryCollectionComponent)
{
    UGeometryCollection* coll = (UGeometryCollection*)StaticLoadObject(UGeometryCollection::StaticClass(), NULL, TEXT("GeometryCollection'/Game/FirstPerson/Meshes/Plan/Shape_Plane_GeometryCollection_Top.Shape_Plane_GeometryCollection_Top'"));

    if (coll)
    {
        m_geometryCollectionComponent->SetMaterial(0, material);

        m_geometryCollectionComponent->SetWorldLocationAndRotation(actorLocation, meshRotation);
        m_geometryCollectionComponent->SetRelativeScale3D(meshScale);
        m_geometryCollectionComponent->SetCollisionResponseToChannel(ECollisionChannel::ECC_Pawn, ECR_Ignore);
        m_geometryCollectionComponent->SetCollisionResponseToChannel(ECollisionChannel::ECC_WorldDynamic, ECR_Ignore);
        m_geometryCollectionComponent->SetCollisionObjectType(ECollisionChannel::ECC_Destructible);
        m_geometryCollectionComponent->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);

        m_geometryCollectionComponent->SetRestCollection(coll);

        m_geometryCollectionComponent->SetEnableGravity(true);
        //m_geometryCollectionComponent->SetSimulatePhysics(true);
        m_geometryCollectionComponent->SetCollisionResponseToChannel(ECollisionChannel::ECC_WorldStatic, ECR_Block);

        m_geometryCollectionComponent->ApplyKinematicField(1000.0f, actorLocation);
    }
}

From all I could gather from my experience and other Unreal programmers, you can’t create geometry collections this way in c++.

You HAVE to create a blueprint class that has the geometry collection already set in it. You can then load this blueprint class in c++ and it’ll work.

WARNING: Plane meshes will NOT work in Chaos. You have to do very thin cubes instead. I learned this the hard way.

I haven’t tried this, but someone from the Unreal Slackers Discord said he had success with this:

UGeometryCollectionComponent* TargetDMComp;
            TargetDMComp = Cast<UGeometryCollectionComponent>(AddComponentByClass(UGeometryCollectionComponent::StaticClass(), false, TargetSMComp->GetRelativeTransform(), true));
            TargetDMComp->SetRestCollection(*FoundCollection);
            FinishAddComponent(TargetDMComp, false, TargetSMComp->GetRelativeTransform());
            TargetDMComp->SetRestCollection(*FoundCollection);
            TargetDMComp->EditRestCollection(GeometryCollection::EEditUpdate::RestPhysicsDynamic, false);

I’d like to also state that doing any kind of stress to geometry collection in UE4.27 Chaos will result in crashes and it renders using it impossible. Hopefully UE5 doesn’t have these crashes.

1 Like

The solution is actually even simpler, at least it is in UE 5.4. All you need to do is call RecreatePhysicsState() on the GeometryCollectionComponent after setting the RestCollection. You don’t want to call EditRestCollection as this will edit all instances of the collection not just the one you are adding.

1 Like

You are my savior.

Is there a way to do this with blueprints?