Hi, I have the following setup:
I have a CharacterClass which has several Components which all inherit from a BaseComponent class. In the BeginPlay of the BaseComponent class I run a protected RegisterComponent(UBaseComponent* Component) method which the child classes all run as RegisterComponent(this). My BaseComponent class then stores the references to the child classes by trying a cast to their specific class types. I have the BaseComponent class log out a message when a child component is successfully registered. This happens for all of them.
Now I’m trying to access the reference of ChildComponentClass1 from ChildComponentClass2 for example. Seeing as the instance pointers I have stored on the BaseComponent class is protected, I’d expect to be able to access this pointer, but when I do a null check from ChildComponentClass1, ChildComponentClass2 is not initialised. Am I doning something super nooby, or can anyone suggest a better way of letting component classes communicate without having to involve my container class (CharacterClass)?
Here is the relevant source code.
BaseComponent.h
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class MYGAME_API UBaseComponent : public UActorComponent
{
GENERATED_BODY()
public:
// Sets default values for this component's properties
UBaseComponent();
protected:
// Called when the game starts
virtual void BeginPlay() override;
void RegisterComponent(class UBaseComponent* Component);
bool IsSafePointer(class UBaseComponent* Component, FString ComponentName);
//keep a reference to all components so they can be recalled
class UChildComponent1* ChildComponent1 = nullptr;
class UChildComponent2* ChildComponent2 = nullptr;
class UChildComponent3* ChildComponent3 = nullptr;
};
BaseComponent.cpp
#include "MyGame.h"
#include "ChildComponent1.h"
#include "ChildComponent2.h"
#include "ChildComponent3.h"
#include "BaseComponent.h"
// Called when the game starts. BeginPlay() should be run as Super::BeginPlay() on each child class to register them
void UBaseComponent::BeginPlay()
{
Super::BeginPlay();
/** Calls the RegisterComponent Method and passes its own instance in, registering a pointer to itself for other components to access */
RegisterComponent(this);
}
// BeginPlay should be run as Super::BeginPlay on each child class to register them
void UBaseComponent::RegisterComponent(UBaseComponent * Component)
{
// Try to cast to each component sub-type and if successfull, register pointer and return out of the method
ChildComponent1 = Cast<UChildComponent1>(Component);
if (ChildComponent1 != nullptr)
{
UE_LOG(LogTemp, Warning, TEXT("Registered %s "), *ChildComponent1 ->GetName());
return;
}
ChildComponent2 = Cast<UChildComponent2>(Component);
if (ChildComponent2 != nullptr)
{
UE_LOG(LogTemp, Warning, TEXT("Registered %s "), *ChildComponent2 ->GetName());
return;
}
//etc...
}
bool UBaseComponent::IsSafePointer(UBaseComponent * Component, FString ComponentName = FString("Undefined"))
{
if (Component != nullptr)
{
return true;
}
else
{
UE_LOG(LogTemp, Error, TEXT("Component Pointer Test Failed on: %s"), *ComponentName);
return false;
}
}
The Child Classes simply extend UBaseComponent and run Super::BeginPlay(). Then at some point after all child components are registered, Child 1 tries to access Child 2 though the IsSafePointer method which in turn fails. Child 1 has Child 2’s .h file included in its .cpp file.
Any ideas?
Many thanks in advance!
Nik