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.