How to throw a grabbed component with physics handle?

I managed to grab a component using a physics handle and GrabComponent(), I want to be able to throw my object, I can “throw” it by moving the camera right and left and release the mouse button, but I’d like to be able to right click and form a trajectory with the component with c++, how can I achieve this ?

Thanks for helping.

Hi, Drakota.

I was facing the same problem, and I had solved it using UPrimitiveComponent::AddImpulse() function. Here’s how I did it:

First, I made sure that I was saving the HitResult globally when line-tracing (ray-casting) on an object to grab. Then I retrieved the component being grabbed from the HitResult and applied an impulse on it.

void UGrabber::Throw()
{
	auto ComponentGrabbed = HitResult.GetComponent();
    int rate = 1000; /// Rate at which the impulse is applied.

	/// Checking if the object is first grabbed before throwing.
	if (HitResult.GetActor() && bIsObjectGrabbed)
	{
		PhysicsHandle->ReleaseComponent();

		/// (Using player's forward vector to determine direction of throw).
		ComponentGrabbed->AddImpulse(
			GetWorld()->GetFirstPlayerController()->GetActorForwardVector() * rate,
			NAME_None, /// No bone names for specific  objects.
			true /// Makes sure that mass is immaterial to the force.
		);

		bIsObjectGrabbed = false;
	}
}

In the above gist, bIsObjectGrabbed is a global Boolean which is set to true when the object is grabbed, and set to false when the object is released or thrown.

For some reason, if you hadn’t used line-trace to get the HitResult, where how to achieve it:

void UGrabber::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

	FVector PlayerViewPointLocation;
	FRotator PlayViewPointRotation;

	GetWorld()->GetFirstPlayerController()->GetPlayerViewPoint(
		PlayerViewPointLocation,
		PlayViewPointRotation
	);

	FVector LineTraceEnd = PlayerViewPointLocation + (PlayViewPointRotation.Vector() * Reach);

	/// Performing Line-Tracing (Ray Casting).
	FHitResult Hit;
	FCollisionQueryParams TraceParams(FName(TEXT("")), false, GetOwner());

	GetWorld()->LineTraceSingleByObjectType(
		Hit,
		PlayerViewPointLocation,
		LineTraceEnd,
		FCollisionObjectQueryParams(ECollisionChannel::ECC_PhysicsBody),
		TraceParams
	);

	/// Saving the output hit result for the grabber mechanism.
	HitResult = Hit;

	if (Hit.GetActor() != NULL)
	{
		UE_LOG(LogTemp, Log, TEXT("Line trace on: %s"), *Hit.GetActor()->GetName());
	}

	/// Setting Component's grabbed location to Ray-Cast end.
	if (PhysicsHandle->GrabbedComponent)
	{
		PhysicsHandle->SetTargetLocation(LineTraceEnd);
	}
}