Hi,
I have migrated over here from the CryEngine and am having a little trouble with UE4s class templates. I am currently building a character properties system that is split into different subsystems. So for example there is a system that manages health and a different system that handles a characters movement setup. The idea behind this setup is that you can combine different templates for the different systems into different characters. I had already programmed this for CryEngine and it worked. As I am currently migrating this into UE4 I ran into a problem with the UE4 classes.
To enable reflection and blueprint setup, which seems to be key in UE4, my classes need to be subclasses of the UE class templates. I read the overview for the classes and decided to let my classes inherit from UActorComponent as my system would be a subobject of an Actor and it should be tickable. That seemed to work for a single component. But apparently ActorComponents can’t be subobjects of ActorComponents, which admiditly makes sense but is also somewhat problematic as I now don’t know from what class to inherit my classes…
To the technical part:
I want to build the following hierachy:
Actor->HealthStats->Individual health components (Array)
Here the class HealthStats:
#pragma once
#include "HealthComponent.h"
#include "Components/ActorComponent.h"
#include "CharacterHealthStats.generated.h"
UCLASS()
class UCharacterHealthStats : public UActorComponent
{
GENERATED_UCLASS_BODY()
enum EHealthComponents {
HEALTH = 0,
ARMOR,
LAST
};
UPROPERTY(EditDefaultsOnly, Category = HealthComponents)
TSubobjectPtr<UHealthComponent> m_healthComponents[LAST];
Update(float frameTime);
};
// .CPP starts here
UCharacterHealthStats::UCharacterHealthStats(const class FPostConstructInitializeProperties& PCIP)
: Super(PCIP)
{
m_healthComponents[HEALTH] = PCIP.CreateDefaultSubobject<UHealthComponent>(this, TEXT("Health"));
m_healthComponents[ARMOR] = PCIP.CreateDefaultSubobject<UHealthComponent>(this, TEXT("Armor"));
}
UCharacterHealthStats::Update(float frameTime) {
//Call Update(frameTime) for all components
}
Here is the code for UHealthComponent:
#pragma once
#include "HealthComponent.generated.h"
UCLASS()
class UHealthComponent : UActorComponent
{
GENERATED_UCLASS_BODY()
UFUNCTION(BlueprintCallable, Category = Functions)
void Update(float time);
UFUNCTION(BlueprintCallable, Category = Functions)
void Drain(float drain);
UPROPERTY(EditDefaultsOnly, Category = Values)
int32 m_maxValue;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Values)
float m_value;
};
UHealthComponent::UHealthComponent(const class FPostConstructInitializeProperties& PCIP)
: Super(PCIP)
{
m_maxValue = 100;
m_value = 100;
}
void UHealthComponent::Update(float frameTime) {
//Do what needs to be done
}
A few last things to note:
- As you can see neither of the two need any kind of “worldly” representation
- It doesn’t matter to me wether the system itself or the actor ticks the classes, but I would prefer the Actor to do it.
So I hope this gives you enough information to be able to help me.
Best regards!