Here my class. It’s an actor component that I am attaching to an object. This is the .h file:
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "HealthSubsystem.h"
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "SurvivalSystemComponent.generated.h"
UCLASS(ClassGroup=SurvivalSystemComponents, meta=(BlueprintSpawnableComponent), Blueprintable)
class CUSTOMTPC_API USurvivalSystemComponent : public UActorComponent
{
GENERATED_BODY()
private:
///<summary>
/// Health subsystem
///</summary>
UPROPERTY(EditAnywhere, Category = "Survival subsystems")
UHealthSubsystem* Health;
public:
// Sets default values for this component's properties
USurvivalSystemComponent();
//This is a pointer -> to a -> [constant UHealthSusbsytem]
UFUNCTION(BlueprintCallable, Category = "Survival subsystem methods")
UHealthSubsystem const* GetHealthSubsystem() const;
protected:
// Called when the game starts
virtual void BeginPlay() override;
public:
// Called every frame
virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
};
Ok and here is the .cpp file
// Fill out your copyright notice in the Description page of Project Settings.
#include "SurvivalSystemComponent.h"
#include "EngineMinimal.h"
#define DISPLAY_MESSAGE(message) if(GEngine){GEngine->AddOnScreenDebugMessage(-1, 2.0f, FColor::Yellow, TEXT(message));}
// Sets default values for this component's properties
USurvivalSystemComponent::USurvivalSystemComponent()
{
// Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features
// off to improve performance if you don't need them.
PrimaryComponentTick.bCanEverTick = true;
// ...
}
UHealthSubsystem const* USurvivalSystemComponent::GetHealthSubsystem() const
{
return Health;
}
// Called when the game starts
void USurvivalSystemComponent::BeginPlay()
{
Super::BeginPlay();
if (Health == nullptr)
{
Health = NewObject<UHealthSubsystem>();
Health->Initialize(100,100, 0, 0, true);
}
}
// Called every frame
void USurvivalSystemComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
if (Health != nullptr)
{
Health->SetDepletionRate(DeltaTime * 0.05f * 100);
Health->DepleteHealth();
}
}
Focus on the UHealthSubsystem object called Health. Also focus on the method GetHealthSubsystem();
The intent of that getter method is to return a pointer to a constant UHealthSubsystem. That means that you cannot use setter methods if you were to call GetHealthSubsystem. The syntax on where I put the const modifier keyword is based off the clockwise/spiral rule. Essentially you need to read it backwards, that is:
UHealthSubsystem const* GetHealthSubsystem() const;
[Note, the const at the end of course means that this method shouldn’t be modifying the class.]
This statement, if you read it right to left says “pointer to a constant UHealthSubsystem”.
So if I call GetHealthSubsystem().SomeSetterMethod(someValue), it shouldn’t work. I am mutating the object itself.
This is my intent. I also want to make it so that blueprints can read this object. If i didn’t put the UFUNCTION macro, everything complies. However, if i left it there, I get this compile error :
“Cannot convert from const UHealthSubsystem* to UHealthSubsystem*”.
“Conversion loses qualifiers”
“Cannot convert from const UHealthSubsystem* to UHealthSubsystem*”.
“Conversion loses qualifiers”
Why is this happening? Why does the compiler not understand that I am only going to return a immutable UHealthSubsystem pointer, who’s object that it is pointing to cannot be modified (although of course, the pointer itself can point to a different object).
Also, if I put the const keyword AFTER the “*” symbol, it compiles fine. Of course, why would I even be using this? This is saying that I can mutate the object but I can’t change where it points to.
And YES, UHealthSubsystem is a UObject. In fact, it inherits from a class called BaseSystem which is what inherits UObject.
Another note: It tell’s me the error comes from line 14 on the .h file. 0_0.
Here’s the error messages :
Info Compiling game modules for hot reload
Info Parsing headers for CustomTPCEditor
Info Running UnrealHeaderTool "F:\Projects\Unreal Projects\CustomTPC\CustomTPC.uproject" "F:\Projects\Unreal Projects\CustomTPC\Intermediate\Build\Win64\CustomTPCEditor\Development\CustomTPCEditor.uhtmanifest" -LogCmds="loginit warning, logexit warning, logdatabase error" -Unattended -WarningsAsErrors -installed
Info Reflection code generated for CustomTPCEditor in 3.9255561 seconds
Info Performing 4 actions (4 in parallel)
Info CustomTPC.generated.cpp
Info SurvivalSystemComponent.cpp
Error F:\Projects\Unreal Projects\CustomTPC\Source\CustomTPC\Public\SurvivalSystem\SurvivalSystemComponent.h(14) : error C2440: '=': cannot convert from 'const UHealthSubsystem *' to 'UHealthSubsystem *'
Error F:\Projects\Unreal Projects\CustomTPC\Source\CustomTPC\Public\SurvivalSystem\SurvivalSystemComponent.h(14) : note: Conversion loses qualifiers
Error F:\Projects\Unreal Projects\CustomTPC\Source\CustomTPC\Public/SurvivalSystem/SurvivalSystemComponent.h(14) : error C2440: '=': cannot convert from 'const UHealthSubsystem *' to 'UHealthSubsystem *'
Error F:\Projects\Unreal Projects\CustomTPC\Source\CustomTPC\Public/SurvivalSystem/SurvivalSystemComponent.h(14) : note: Conversion loses qualifiers
Info ERROR: UBT ERROR: Failed to produce item: F:\Projects\Unreal Projects\CustomTPC\Binaries\Win64\UE4Editor-CustomTPC-668.dll
Info Total build time: 9.21 seconds (Local executor: 0.00 seconds)