Hello,
I’m trying to create an Enemy Manager module in a plugin, which will be part of my generic game framework but I’m failing to decide in which class design and pattern to choose. Basically, the Enemy Manager is an invisible object, where you have to initially add some string identifiers to it that will be added to an array. Also events/delegates/functions have to be exposed to be accessible in Blueprint.
Sorry if those questions will appear to be silly, but I come from Unity and the approach there is to have a GameObject, i.e. Game Manager where I drag an “EnemyManager” script/component and then I can make the GameObject static (so it will stay alive between levels/scenes - in case I have only one set of enemies) or also I can just have one specific Game Manager GameObject per scene and each scene can have its own set of enemies added to the manager. Notice this Game Manager object is not something visual, it is kept alive invisible in the level, as a framework functionality.
As another example let’s consider an Input Manager. You have only one in your game, but you can define your custom controls and have them saved in an array in the Input Manager. Then it has events that are fired when a key is pressed and you can also call functions from it.
Issues/Questions:
-
How to create a singleton/static class that is accessible from Blueprint?
-
How to create a static Delegate/Event? At the moment I have the static function AddEnemy and of course it fails to call the non static event, but at the same time I didn’t find a way to create a static event.
-
Overall, what would be the best way to design this?
-
Forgetting the whole singleton thing, how to design the Enemy Manager as it where spawnable one time per map and that has to be exposed to Blueprint, but since it is an invisible part of the game framework it can’t be a Component of an object. What could it be defined as? Should I create instances of UEnemyManager manually in Blueprint and then just call the functions non statically, linking to the Target slot? How can I get a similar Unity approach that I explained?
-
EDIT 1: I am failing to see beyond the “Unity’s way” (been using that engine full time and daily for the past 3 years!). For instance, on the level blueprint I tried to call Add Enemy on Event Begin Play, but then it won’t allow me to create an instance of EnemyManager. Then it also doesn’t offer me way to listen to OnEnemyAdded anywhere because I don’t have an instance of EnemyManager. So is UBlueprintFunctionLibrary the correct parent class to choose?
Example code that I tried and it failed because I didn’t find a way to declare the delegate static and also because I am feeling I am not getting the “Unreal” way to do it:
// .h
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnEnemyAddedSignature, FName, Identifier);
UCLASS()
class UEnemyManager : public UBlueprintFunctionLibrary
{
GENERATED_UCLASS_BODY()
/** Add enemy type to be initialised */
UFUNCTION(BlueprintCallable, Category = "Enemy Manager")
static void AddEnemy(FName Identifier);
/** Called when an enemy is successfully added to the manager */
UPROPERTY(BlueprintAssignable, Category = "Enemy Manager")
FOnEnemyAddedSignature OnEnemyAdded;
static TArray<FName> EnemyIdentifiers;
};
// .cpp
UEnemyManager::UEnemyManager(const FPostConstructInitializeProperties& PCIP)
: Super(PCIP)
{
}
void UEnemyManager::AddEnemy(FName Identifier)
{
EnemyIdentifiers.Add(Identifier);
// Of course this won't work because OnEnemyAdded is not static... so how to?
OnEnemyAdded.Broadcast(Identifier);
}