Can't get this event from C++ to be fired in Blueprint

Hey, guys!

I’m so frustrated, because I’ve been sitting for hours on google, trying to figure this out.
I have this BlueprintNativeEvent in C++, and I can access it in my Blueprint, but it never gets called. See code below for details about my setup for this.

I have no issue accessing the variables or anything else than get this event fired.
The only thing I want now is to see “FINALLY!!!” pop up on my screen.

Other solutions I’ve tried
Changing it to BlueprintImplementable and made the modification in my code for it to work, but still nothing.
Removing the parent node for the event.
With and without “BlueprintCallable”

How it looks in my blueprint. This is the event graph in the child Blueprint:

.h file:

	//For updating HUD
	UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "HUDEvent")
	void UpdateCurrentAmmoHud();
	void UpdateCurrentAmmoHud_Implementation();

.cpp file:

void UTP_WeaponComponent::Fire()
{
	if (Character == nullptr || Character->GetController() == nullptr)
	{
		return;
	}

	// Try and fire a projectile
	if (ProjectileClass != nullptr)
	{
		UWorld* const World = GetWorld();
		if (World != nullptr)
		{
			
			APlayerController* PlayerController = Cast<APlayerController>(Character->GetController());
			if (PlayerController != nullptr)
			{
				//Decrements amount of bullets in clip
				CurrentAmmoInClip--;
				//Updates the hud through BP implementation
				UpdateCurrentAmmoHud_Implementation();

				const FVector StartLoc = PlayerController->PlayerCameraManager->GetCameraLocation();;
				const FVector ShootDirection = PlayerController->PlayerCameraManager->GetCameraRotation().Vector();
				FVector EndLoc = StartLoc + ShootDirection * ShootingDistance;

				FHitResult HitResult;
				FCollisionQueryParams CollisionParams;
				CollisionParams.AddIgnoredActor(Character); //Excludes weapon owner from the line trace. You can't shoot yourself :D
				
				//Determines if it is a hit or not
				bool ShotHit = World->LineTraceSingleByChannel(HitResult, StartLoc, EndLoc, ECC_Visibility, CollisionParams);
				DrawDebugLine(GetWorld(), StartLoc, EndLoc, FColor::Orange, false, 2.0f);

				if (ShotHit)
				{	
					//Draws a small red box at the hit location
					DrawDebugBox(GetWorld(), HitResult.ImpactPoint, FVector(5, 5, 5), FColor::Red, false, 2.0f);
				}
				IsReloadable = true;
				if (CurrentAmmoInClip != MaxClipCapacity || CurrentReserveAmmo != 0) 
				{ 
					ReloadWeapon();
				}
				else { return; }
			}
		}
	}

void UTP_WeaponComponent::UpdateCurrentAmmoHud_Implementation()
{
	//GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, TEXT("Weapon fired"));
}

I’ve also tried changing:

UpdateCurrentAmmoHud_Implementation();

to

Can you try removing “_Implementation” from the call to UpdateCurrentAmmoHud?

Here’s a quick wiki on the topic of calling blueprint from C++

Yes the only place you should use _implementation is inside the .cpp file function implementation.

Remove void UpdateCurrentAmmoHud_Implementation(); from the .h file and when you call it in UTP_WeaponComponent::Fire() you should call UpdateCurrentAmmoHud()

Are you sure that blueprint class is really what you expect? Common mistake is that you create a c++ class i.e. ABaseWeaponActor instead of blueprint class BP_BaseWeapon.
ABaseWeaponActor* weapon = SpawnActor< ABaseWeaponActor>(…) - at this point engine doesn’t know about a blueprint part. You need to transfer a pointer of class type (BP_BaseWeapon) to your spawning code from editor. TSubclassof< ABaseWeaponActor> weaponClass; - recive some where in editor and spawn exactly this class. (In our case it will be BP_BaseWeapon).
Since your problem in actorcomponent it could be the problem of spawning actor itself.
Also you can try to delegate the event call to owner actor.

P.S. It’s better not to call ammo update from other parts. Get the pointer of widget and update through it.
I.e. GetHUD()->GetAmmoWidget()->CurrentAmmo->SetText(CurrentAmmoInClip);

our insight into the blueprint class issue is invaluable. Guiding others away from the common trap of mismatching classes and emphasizing the TSubclassOf approach highlights your expertise. Also, suggesting widget communication through the HUD showcases your efficient coding approach.

Thanks for your reply. Yes, I have tried that to no avail.

Thanks for your suggestion. After trying this as well, I can confirm it compiles, but the event in the event graph still doesn’t fire. It’s very weird.

Thanks for providing a safe option. I’ve been aware of this, but that requires me to build a new HUD widget in C++, which I have in BP instead right now. Can’t access it otherwise it seems.

I think you should call UpdateCurrentAmmoHud() instead of UpdateCurrentAmmoHud_Implementation()

If still not working, adding UE_LOG to these red line mark, so we can tell if the function is executed as expected.

Thanks to everyone helping me out here. My problem is finally solved, and it feels great!

I went for your solution, kind of. I dumped my current HUD and replaced it with one made in C++. With some guidance of a Youtube video on UMG in C++.

HUD Header:


#pragma once

#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "FirstPersonHUD.generated.h"

UCLASS(Abstract)
class FIRSTPERSON_API UFirstPersonHUD : public UUserWidget
{
	GENERATED_BODY()

/*
* HUD FUNCTIONS--------------------------------------------------------------------------------------------------------------
*/
public:
	void SetHealth(float CurrentHealth, float MaxHealth);
	void SetCurrentAmmo(int CurrentAmmo, int CurrentReserveAmmo);

/*
* HUD WIDGETS----------------------------------------------------------------------------------------------------------------
*/
public:
	UPROPERTY(EditAnywhere, meta = (BindWidget))
	class UProgressBar* HealthBar;

	UPROPERTY(EditAnywhere, meta = (BindWidget))
	class UTextBlock* CurrentAmmoText;

	UPROPERTY(EditAnywhere, meta = (BindWidget))
	class UTextBlock* CurrentReserveAmmoText;
};

HUD .cpp:



#include "FIrstPersonHUD.h"
#include "Components/ProgressBar.h"
#include "Components/TextBlock.h"

/*
* ---------------------------------------------------------------------------------------------------------------------------
*/
void UFirstPersonHUD::SetHealth(float CurrentHealth, float MaxHealth)
{
	if (HealthBar)
	{
		HealthBar->SetPercent(CurrentHealth / MaxHealth);
	}
}
/*
* ---------------------------------------------------------------------------------------------------------------------------
*/
void UFirstPersonHUD::SetCurrentAmmo(int CurrentAmmo, int CurrentReserveAmmo)
{
	if (CurrentAmmoText && CurrentReserveAmmoText)
	{
		FText stringCurrentAmmo = FText::AsNumber(CurrentAmmo);
		CurrentAmmoText->SetText(stringCurrentAmmo);

		FText stringCurrentReserveAmmo = FText::AsNumber(CurrentReserveAmmo);
		CurrentReserveAmmoText->SetText(stringCurrentReserveAmmo);
	}
}

WeaponComponent header:

	// For updating HUD
	UFUNCTION(BlueprintCallable)
		void UpdateCurrentAmmoHud(int AmmoToUpdate, int ReserveAmmoToUpdate);

WeaponComponent .cpp:

Some code ....
Character->PlayerHUD->SetCurrentAmmo(AmmoToUpdate, ReserveAmmoToUpdate);

Is there any downside to go the extra step through my character reference to get to the PlayerHUD? That is where I set the constructor values for the HUD anyway, and had a reference to Character from before, so I didn’t mind it.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.