Hi there,
This is an interesting question for me also so thanks for it. Good observation, never encountered it before.
Edit :
Actually wrote a lot of suggestions before but editing now since I think replicated the issue and found reason. This happening because the actor’s RigidBody is not default root probably under a scene component. Make it root and think it will work.
to
Why happenns, after actor’s set simulated since its not the root, simulated object detaches not hierarcy wise but physics solver takes over. Actor is there root scene component there but they are ignored. When we stop simulating the physics ofcourse it doesn’t snaps back but stays where ever its in the world. If we get the root component and make sure their transforms are same and then we do whatever attachement / transform it will work.
Attach Simulated (false) component to Actors Root.
Or ofcourse you can just get Actor’s Component Simulated (false) and attach to your component too.
On deeper level there should be some kind of mismatch / desync maybe so I will make further investigation around it.
Hope this works and let me know.
Edit 2:
So I check and actually its what I suspected and here is the comment by Epic
// So the primitive component when you check the details panel bool calls this.
void UPrimitiveComponent::SetSimulatePhysics(bool bSimulate)
{
BodyInstance.SetInstanceSimulatePhysics(bSimulate);
}
// This calls a core function found over here
ENGINE_API void SetInstanceSimulatePhysics(bool bSimulate, bool bMaintainPhysicsBlending=false, bool bPreserveExistingAttachment = false);
// Comment by Epic basically saying we break / detach from parent if bPreserveExistingAttachment not set true.
/**
* @param bPreserveExistingAttachments If true then any existing attachment between the owning component and
* its parent will be preserved, even when switching to simulate (most likely useful for skeletal meshes
* that are parented to a moveable component). If false then the owning component will be detached
* from its parent if this is the root body and it is being set to simulate.
*/
// If we say true in the execution of it basically it will also carry the actor with it. This seems like a design choice which makes sense kinda. However this can be also exposed to designer atleast or with a special function.
//So basically I did that without modifying the code created a BlueprintFunctionLibrary and wrapped this function.
MyPhysicsLibrary.h
#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "MyPhysicsLibrary.generated.h"
/**
*
*/
UCLASS()
class VACUUMGUNPROTOTYPE_API UMyPhysicsLibrary : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable, Category = "Physics", meta=(DefaultToSelf="SimComponent", CompactNodeTitle="Custom Physics Simulate"))
static void SetSimulatePhysicsWithAttachment(UPrimitiveComponent* SimComponent, bool bSimulate, bool bPreserveAttachment = true);
};
MyPhysicsLibrary.cpp
#include "MyPhysicsLibrary.h"
#include "Components/PrimitiveComponent.h"
#include "PhysicsEngine/BodyInstance.h"
void UMyPhysicsLibrary::SetSimulatePhysicsWithAttachment(UPrimitiveComponent* SimComponent, bool bSimulate, bool bPreserveAttachment)
{
if (SimComponent)
{
if (FBodyInstance* BI = SimComponent->GetBodyInstance())
{
BI->SetInstanceSimulatePhysics(bSimulate, false, bPreserveAttachment);
}
}
}
Go inside the Actor, change nothing leave with parent scene component, didn’t check simulation true from details but used this function at begin play.
Detail : This should work as expected without creating this strange behaviour.
So if its really important for your case you can just create a C++ class from editor or IDE wrap this or directly copy paste .h .cpp with correct api and you can use this.