Download

PhysicsHandleComponent doesn't move when SetTargetLocation() is called in C++

I’m trying to implement a grab/drop feature in my project, so that the user can pick up objects that have physics. I need to do it in C++, but since there is plenty of material on this with Blueprints and almost none in C++ I started implementing the feature in Blueprint, and it works. The steps are these:

  1. If a certain key is pressed, do a line trace
  2. If the line trace hit something, create a Physics Handle Component in the current actor and call GrabComponent on the hit component
  3. If the key is released, call ReleaseComponent on the Physics Handle Component

In the Tick function, if there is a grab component I just call SetTargetLocation on the Physics Handle passing a location just in front of the camera (so that the user can move and the object stays in front of him), like this (sorry, it’s kind of messy):
785b8c4b8b223fd0d61289c63ca3127e0c6ee7d3.png

Now, this works pretty much like in this video:

I started implementing this in C++, doing exactly the same things. The code looks like this:



    // If the mouse button was clicked and no component is grabbed
    if(GEngine->GetFirstLocalPlayerController(GetWorld())->IsInputKeyDown(EKeys::LeftMouseButton) && mMovedComponent == nullptr)
    {
        FHitResult hitResult;
        FVector rayStart;
        FVector rayEnd;

        rayStart = FirstPersonCameraComponent->GetComponentLocation();
        rayEnd = rayStart + FirstPersonCameraComponent->GetForwardVector() * 10000;

        // Doing line trace to check if I hit something
        bool hitFound = GetWorld()->LineTraceSingleByChannel(hitResult, rayStart, rayEnd, ECollisionChannel::ECC_Visibility);

        if(hitFound)
        {
            // Saving the reference to the hit component and setting it to simulate physics
            mMovedComponent = hitResult.Component.Get();
            mMovedComponent->SetSimulatePhysics(true);

            // Creating the handle
            mPhysicsHandle = NewObject<UPhysicsHandleComponent>(this, TEXT("PhysicsHandle"));

            // Setting the initial location of the handle
            FVector loc = UGameplayStatics::GetPlayerCameraManager(GetWorld(), 0)->GetCameraLocation();
            FRotator rot = UGameplayStatics::GetPlayerCameraManager(GetWorld(), 0)->GetCameraRotation();
            mPhysicsHandle->SetTargetLocationAndRotation(loc, rot);

            // Grabbing the hit component
            mPhysicsHandle->GrabComponent(mMovedComponent, NAME_None, hitResult.ImpactPoint, false);
        }
    }
    // If the player keeps pressing the mouse, I move the physics handle so that it stays in front of the camera
    else if(GEngine->GetFirstLocalPlayerController(GetWorld())->IsInputKeyDown(EKeys::LeftMouseButton) && mMovedComponent != nullptr)
    {
        FVector loc = UGameplayStatics::GetPlayerCameraManager(GetWorld(), 0)->GetCameraLocation();
        FRotator rot = UGameplayStatics::GetPlayerCameraManager(GetWorld(), 0)->GetCameraRotation();

        // I create the new location so that is just in front of the player
        loc += rot.Quaternion().GetForwardVector() * 200;

        mPhysicsHandle->SetTargetLocation(loc);
    }
    // If the player is no longer pressing the key I release the physics handle
    else if(mMovedComponent != nullptr && !GEngine->GetFirstLocalPlayerController(GetWorld())->IsInputKeyDown(EKeys::LeftMouseButton))
    {
        mMovedComponent->SetSimulatePhysics(false);
        mMovedComponent = nullptr;
        mPhysicsHandle->ReleaseComponent();
    }


This code kind of works, meaning that the handle is created and it starts in the right spot. The problem is that it NEVER moves, even though “mPhysicsHandle->SetTargetLocation(loc)” is called at each subsequent tick and the new vector is correct (I print it in the log at each tick so I could see the values).

I don’t understand, why isn’t the handle moving?!

Nevermind. Since Physics Handles are Components, they need to be registered when created. I added a call to RegisterComponent() and now it works, the handle moves around as expected.
The fact that it grabbed the object even though wasn’t registered got me confused.

The added code looks like this, in case anyone wants to implement the grab/drop feature in C++:



// Creating the handle
mPhysicsHandle = NewObject<UPhysicsHandleComponent>(this, TEXT("PhysicsHandle"));

mPhysicsHandle->RegisterComponent(); // <--- new line


I had the same problem but registering the component didn’t fix it.
However, I am new to Game Development, could you please help me understand why components need to be explicitly registered?
I’ve never had the need to do this before