Disable physics of a grabbed mesh after release

So I have a grabber component to grab objects and release them with a physics handle. What I am trying to do is, once I grab a mesh, physics simulation is activated but what I want is once I release the item and drops to the ground after 3 seconds to disable its physics.

I tried to do it via the Grabber.cpp USceneComponent but I have a hard time setting the FTimer Delegate.

Can you please either tell me what I am doing wrong or suggest another solution.

if (PhysicsHandle->GetGrabbedComponent() != nullptr)
{
	FTimerDelegate TimerDelegate = FTimerDelegate::CreateUObject(this, DisablePhysicsAtReleasedComponent(PhysicsHandle->GetGrabbedComponent()), false);

	GetWorld()->GetTimerManager().SetTimer(
		TimerHandle,
		TimerDelegate,
		DisablePhysicsDelay,
		false
	);
	
	// PhysicsHandle->GetGrabbedComponent()->SetSimulatePhysics(false);
	PhysicsHandle->ReleaseComponent();
}

void UGrabber::DisablePhysicsAtReleasedComponent(UPrimitiveComponent* GrabbedComponent)
{
	GrabbedComponent->SetSimulatePhysics(false);
}

What is the observed behaviour of your attempted solution? How does it differ from the expected behaviour?

For starters the timer is not working… :sweat_smile: I get an error that the says :

No viable function.
Argument types: UGrabber*, void, bool.
Candidates considered:
static TDelegate<TDelegate<void()>::RetValType(), FDefaultDelegateUserPolicy> CreateUObject<UserClass, VarTypes...>(UserClass* InUserObject, TMemFunPtrType<false, UserClass, TDelegate<void()>::RetValType(VarTypes...)>::Type InFunc, VarTypes...) (in class TDelegate<void(), FDefaultDelegateUserPolicy>)
conversion of 2nd argument 'DisablePhysicsAtReleasedComponent(PhysicsHandle->GetGrabbedComponent())' is ill-formed: cannot convert void to parameter type TMemFunPtrType<false, UGrabber, TDelegate<void()>::RetValType(bool)>::Type (aka void(UGrabber::*)(bool))
static TDelegate<TDelegate<void()>::RetValType(), FDefaultDelegateUserPolicy> CreateUObject<UserClass, VarTypes...>(const UserClass* InUserObject, TMemFunPtrType<true, UserClass, TDelegate<void()>::RetValType(VarTypes...)>::Type InFunc, VarTypes...) (in class TDelegate<void(), FDefaultDelegateUserPolicy>)
conversion of 2nd argument 'DisablePhysicsAtReleasedComponent(PhysicsHandle->GetGrabbedComponent())' is ill-formed: cannot convert void to parameter type TMemFunPtrType<true, UGrabber, TDelegate<void()>::RetValType(bool)>::Type (aka void(UGrabber::*)(bool) const)

Have you used a timer successfully in the past? Why don’t you try setting a timer that logs a message with UE_LOG after a few seconds, just so you can figure out how to use timers (without complicating it with all the physics stuff)

Here is an example of how I set a timer:

GetWorldTimerManager().SetTimer(
   MyTimerHandle,
   this,
   &AMyActor::MyFunction,
   1, /*bLoop*/ true);

From the error message it seems you are passing one of the arguments to a wrong parameter, or in the wrong way.

In particular, I think the second argument of this:

	FTimerDelegate TimerDelegate = FTimerDelegate::CreateUObject(this, DisablePhysicsAtReleasedComponent(PhysicsHandle->GetGrabbedComponent()), false);

is wrong. DisablePhysicsAtReleasedComponent is a void-returning function, so making a function call to it as an argument will never work. You need to refer to it as a pointer-to-member function like &UGrabber::DisablePhysicsAtReleasedComponent or, alternatively, call it in a lambda expression: [???] { DisablePhysicsAtReleassedComponent(???); } and pass the lambda expression as the argument.

Ok, thanks to Rider I figured out what was the problem. It fixed it for me by doing something similar to cast, see below.

	GetWorld()->GetTimerManager().SetTimer(
		TimerHandle,
		GrabbedComponent,
		FTimerDelegate::TMethodPtr<UPrimitiveComponent>(&UPhysicsDisabler::DisablePhysicsOnOwningActor),
		5,
		false);

The only change I did was to create USceneComponent that disables physics on the owning actor.