new to c++ and cant set each actor with a health component i made to have a different health value

Hi, im new to c++ and have been learning it for the last month or so. Ive tried to create a health component which ive added to the player and my enemies, whenver i try to set the default health value on each character that has the component the health either gets set back to the health of the last character i set the value on or my unreal crashes. Im not sure why this is happening as in blueprint i am able to do this without any problems.

My health components header:

#pragma once

include “CoreMinimal.h”
include “Components/ActorComponent.h”
include “BaseCharacter.h”
include “HealthComponent.generated.h”

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FHealthComponentDeadSignature, AController*, causer);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FHealthComponentDamagedSignature, float, NewHealth, float, MaxHealth, float, ChangeInHealth);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FPlayerRespawnedSignature, float, MaxHealth);

UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
class CPPMAINPROJECT_API UHealthComponent : public UActorComponent
{
GENERATED_BODY()

public:
// Sets default values for this component’s properties
UHealthComponent();

UPROPERTY(BlueprintAssignable)
FHealthComponentDeadSignature OnHealthComponentDead;

UPROPERTY(BlueprintAssignable)
FHealthComponentDamagedSignature OnHealthComponentDamaged;

UPROPERTY(BlueprintAssignable)
FPlayerRespawnedSignature OnPlayerRespawned;

UPROPERTY(BlueprintReadOnly, visibleAnywhere)
bool CanTakeDamage;

UPROPERTY(VisibleAnywhere, BlueprintReadWrite);
float _MaxHealth;

protected:

UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
float _CurrentHealth;

UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
bool AttachedToPlayer;

UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
ABaseCharacter* OwningCharacter;

UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
AController* DamageCauser;

virtual void BeginPlay() override;

private:
UFUNCTION()
void DamageTaken(AActor* DamagedActor, float Damage, const UDamageType* DamageType, AController* instigator, AActor* Causer);

UFUNCTION()
void PlayerRespawned();

};

My Health components cpp:

include “HealthComponent.h”
include “PlayerCharacter.h”

// Sets default values for this component’s properties
UHealthComponent::UHealthComponent()
{
CanTakeDamage = true;
_MaxHealth = 100;
}

// Called when the game starts
void UHealthComponent::BeginPlay()
{
Super::BeginPlay();

_CurrentHealth = _MaxHealth;

OwningCharacter = Cast<ABaseCharacter>(GetOwner());

if (IsValid(OwningCharacter))
{

	OwningCharacter->OnTakeAnyDamage.AddDynamic(this, &UHealthComponent::DamageTaken);

	if (OwningCharacter->IsA(APlayerCharacter::StaticClass()))
	{
		AttachedToPlayer = true;
	}
}

}

void UHealthComponent::DamageTaken(AActor* DamagedActor, float Damage, const UDamageType* DamageType,
AController* Instigator, AActor* Causer)
{
if (OwningCharacter->CanTakeDamage == true)
{
const float change = FMath::Min(_CurrentHealth, Damage);
_CurrentHealth-= change;
_CurrentHealth = FMath::Clamp(_CurrentHealth, 0 , _MaxHealth);

	OnHealthComponentDamaged.Broadcast(_CurrentHealth, _MaxHealth, change);

	OwningCharacter->TakeDamageEvent_Implementation(Causer);

	if (_CurrentHealth <= 0.0f )
	{
	
		OwningCharacter->Execute_DeathEvent(OwningCharacter, Instigator);

		if(AttachedToPlayer == true)
		{
			PlayerRespawned();
		}
	
		GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("DEAD")));
	}

}

}

void UHealthComponent::PlayerRespawned()
{
_CurrentHealth = _MaxHealth;
OnPlayerRespawned.Broadcast(_MaxHealth);
}

Im currently setting the default value in the health components initilisation as this is the only way that works, i know that the health component is set to “visibleAnywhere” instead of “EditAnywhere” but ive done this to prevent accidentally changing the value and crashing the game.

Components added in c++ and stored under a UPROPERTY should always be marked VisibleAnywhere instead of EditAnywhere. EditAnywhere leads to blueprint corruption when dealing with components. At that point only recreating of a blueprint asset gets rid of odd problems.

All your properties are missing property initialisation in the example code you show. This leads to undefined behavior.

You are calling the “_Implementation” version of a function when you should be calling the non implementation version “TakeDamageEvent”.

You are looping. If owning character takes damage then call health component DamageTaken, then call OwningCharacter->TakeDamageEvent. It’s a loop?

I hope that the issue is solved once you fix the errors I see right now. Else, let me know and we can look at the updated code.

I’ve made a plugin a while back which can be used as a health component (or stamina, or literally anything else) which I placed online for sale. You can also get that for a working system and a good code example:

https://ferrefy.com/documentation/status-effects-plugin/

Ferrefy Plugin: Status Effects | Fab

1 Like