Enabling physics and then disabling it removes ability to attach to socket

Hello.

I’m doing this:

GetMesh()->SetSimulatePhysics(true);

And afterwards

GetMesh()->SetSimulatePhysics(false);

but setting it to false doesn’t seem to revert what has been done by SetSimulatePhysics(true) to 100%, because before I set it to true, I can do this:

MyCubeObject->AttachRootComponentTo(SomePawn->GetMesh(), NAME_None, EAttachLocation::SnapToTarget) ; which is not possible after setting SetSimulatePhysics(false).

To clarify: I want to have a static cube in the map, pick it up so it is attached to my pawn. Then I can press a button and throw it into the world, while activating physics so it looks like I threw a box in front of me.
This works, but if I touch the box afterwards to pick it up again, I cannot attach it to my pawn again.

To me it seems like SetSimulatePhysics(true) is doing something to my mesh that I cannot revert. I’m using DetachRootComponentFromParent() before trying to re-attach of course.

If I try to attach the cube again after I dropped it, it relocates to some point in the middle of the map and stays there instead of moving with my pawn, above the head of the pawn.

Does anyone have an idea?

Try to put the bodies to sleep:


Mesh->SetSimulatePhysics(false);
Mesh->SetAllBodiesSimulatePhysics(false);
Mesh->PutAllRigidBodiesToSleep();

My Mesh is just a UStaticMeshComponent, so SetAllBodiesSimulatePhysics doesn’t work. And PutAllRigidBodiesToSleep also didn’t work :frowning:

Try calling


RecreatePhysicsState()

on the StaticMeshComponent (so not on ‘GetMesh()’).

I’m not 100% sure whether that’s the thing that makes it work, but in our code we Actors with UStaticMeshComponents that we can attach and detach to characters as often as we like because that’s how our weapons work, and we’re also often disabling physics (when adding to inventory) and enabling physics again (when dropping the weapon from inventory into the world) and I haven’t noticed any issues where this sometimes doesn’t work. I took a quick look at our code and RecreatePhysicsState() is the only thing I see right now that could influence this.

Thanks, but that also didn’t work. Sigh.

It seems to be different, if I call GetMesh()->AttachTo(…) instead of GetRootComponent()->AttachTo … maybe somehow the root component gets tinkered with and fails on me :frowning:

I resolved my problem. My cube object was having a “DummyRoot” (mindless copy from UT’s Codebase).
I changed this:

RootComponent = ObjectInitializer.CreateDefaultSubobject<USceneComponent, USceneComponent>(this, TEXT(“DummyRoot”), false);
Mesh = ObjectInitializer.CreateDefaultSubobject<UStaticMeshComponent>(this, TEXT(“Cube”));
GetMesh()->AttachParent = RootComponent;

to this:

Mesh = ObjectInitializer.CreateDefaultSubobject<UStaticMeshComponent>(this, TEXT(“Cube”));
RootComponent = GetMesh();

and now all my calls and static / simulated physics switches work :slight_smile:

Experienced a similar issue when using a sub-classed blueprints as part of our inventory system.
The solution I ended up using was to grab the first primitive component in PostInitializeComponents() and use that as the actual root component.
I also found that static meshes often have collision enabled by default which could cause the player to collide with their own items.



    Super::PostInitializeComponents();

    if (!IsPendingKill())
    {
        TArray<UPrimitiveComponent*> Components;
        GetComponents(Components);

        const UPrimitiveComponent* RootPrimComp = Cast<UPrimitiveComponent>(GetRootComponent());
        bool bFoundPrimitiveRoot = (RootPrimComp != nullptr);
            
        for(UPrimitiveComponent* Component : Components)
        {
            // Make sure we have a proper primitive as our root component and not a 'default scene root'.
            if (!bFoundPrimitiveRoot)
            {
                RootComponent = Component;
                bFoundPrimitiveRoot = true;
            }
                    
            // Static mesh based inventory items often have collision enabled by default.
            // Just in case this is the case now, set every component to no collision.
            Component->SetSimulatePhysics(false);
            Component->SetCollisionProfileName(UCollisionProfile::NoCollision_ProfileName);
        }