Download

Having a problem with understanding BlueprintNative

I’m trying to achieve simple interaction between player and HUD. The player must call HUD’s function to make it unfold inventory tab.
I found several examples how to make a BlueprintNativeEvent, here’s what I have in my HUD class header:



UCLASS(Blueprintable)
class TEST_API UMyHUDBase : public UUserWidget
{
    GENERATED_BODY()
public:
    void ToggleInventory();

    UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
    void OnToggleInventory();
    virtual void OnToggleInventory_Implementation();
}

And in source:



// Just a wrapper, I know that I should be able to call OnToggleInventory directly.
void UMyHUDBase::ToggleInventory()
{
    UE_LOG(LogTemp, Error, TEXT("Trying to call OnToggleInventory..."));
    OnToggleInventory();
}

void UMyHUDBase::OnToggleInventory_Implementation()
{
    UE_LOG(LogTemp, Error, TEXT("Unimplemented OnToggleInventory is called!"));
}

And here’s what I have in my blueprint derived from UMyHUDBase and set as HUD in the level blueprint BeginPlay event:
Blueprint Implementation.png

As soon as I call ToggleInventory on the player controller’s HUD (cast to UMyHUDBase), the editor crashes with no crash log opened.
ToggleInventory alone is called with no issues, so the problem is in the BlueprintNativeEvent function.
After the crash it leaves two lines in my clipboard that say “failed to find function OnToggleInventory”.

I don’t understand where do I mistake because I don’t see any differences in my code from the examples I found. Restarting the editor and recompiling every time is very frustrating, I’ll appreciate any help with my problem.

Would you post a picturea about how you called function OnToggleInventory?

Why are you declaring OnToggleInventory_Implementation()? You declare *OnToggleInventory *and implement OnToggleInventory_Implementation.

If I do that compiler says that UMyHUDBase doesn’t have memeber *OnToggleInventory_Implementation *to implement. I found that weird too, but some examples’ headers contained the _Implementation declaration along with the event itself so I just went on with it.

By now I think I figured out what caused the trouble. I called the function like that:


void AMyPawn::ActionOpenPawnInventory()
{
AController* controller = GetController();
APlayerController* playerController;

if (controller != NULL && (playerController = (APlayerController*)controller) != NULL)
{
    AHUD* hud = playerController->GetHUD();
    UMyHUDBase* myHUDBase;
    if (hud != NULL && (myHUDBase = (UMyHUDBase*)hud) != NULL)
    {
        UE_LOG(LogTemp, Error, TEXT("Trying to ToggleInventory..."));
        myHUDBase->ToggleInventory();
    }
        else
        {
            UE_LOG(LogTemp, Error, TEXT("Unable to cast to USGHUDBase"));
        }
    }
}

I just missed that I cast *UUserWidget *derived object to AHUD, and for some reason the cast itself worked and *myHUDBase *wasn’t NULL.
Now everything works fine.
I have one more question though: how should I check my casts to make sure that the resulting pointer is valid in order to avoid situations like that?

The cast “worked” because you are using a C-style cast which will try to cast in many ways.

In Unreal Engine you should always use


Cast<AHud>(MyPointer)

on UObjects instead of C-style


(AHud*)MyPointer

You don’t have to check if hud is NULL before Casting, since the cast will safely fail if it is a nullptr anyway.
You should also use nullptr instead of NULL when specifically checking for null pointers.

Thanks for your answer, sometimes it is really hard to find a good tutorial or example so errors happen from time to time to newbies like me with no obvious reason.

Tutorials never cover every scenario, you will learn bits and pieces along the way. The important thing is to keep learning even for the professionals.

You learn the most when you encounter errors and solve them instead of writing it correctly the first time.