I’m toying around with an idea on how to get an interface with a callable function from a broadcast-able global event. Lemme explain that a little better.
From this site: Global Events there’s a way to create a global event system that will broadcast a function across all objects that need it. I was able to get this working just fine.
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FGlobalEventDelegate_OnPostLoadGame);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FGlobalEventDelegate_OnGameStateChange, EGameState, oldGameState, EGameState, newGameState);
UCLASS()
class AMainGameState : public AGameState
{
GENERATED_BODY()
private:
/*other stuff*/
public:
UPROPERTY(BlueprintAssignable, BlueprintCallable, Category = "GlobalEvents") FGlobalEventDelegate_OnPostLoadGame OnPostLoadGame;
UPROPERTY(BlueprintAssignable, BlueprintCallable, Category = "GlobalEvents") FGlobalEventDelegate_OnGameStateChange OnGameStateChange;
/*other stuff*/
};
From this site: Interfaces in C++ there’s a way to create an interface in C++ and have it able to be used in blueprints. Again, I was able to get this working just fine.
MY question is: “Is there a way to combine the two?” I want to create an interface that automatically places itself in the list of functions to call when the OnGameStateChange global event is broadcasted.
This is what I have so far:
.h file
UINTERFACE(BlueprintType)
class UGameStateChangeInterface : public UInterface
{
GENERATED_UINTERFACE_BODY()
public:
};
class IGameStateChangeInterface
{
GENERATED_IINTERFACE_BODY()
public:
IGameStateChangeInterface();
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "GameStateChangeInterface") void OnGameStateChange(EGameState oldGameState, EGameState newGameState);
};
.cpp file
IGameStateChangeInterface::IGameStateChangeInterface()
{
UObject* thisAsObj = Cast<UObject>(this);
if(thisAsObj == nullptr)
return;
AMainGameState* gameState = //get the game state
if(gameState != nullptr)
{
gameState->OnGameStateChange.AddDynamic(this, &IGameStateChangeInterface::Execute_OnGameStateChange);
}
}
However, this doesn’t compile. It gives the error:
2>C:\Users\Frank\Documents\Unreal Projects\SanguineIsland\Source\SanguineIsland\Private\GameStateChangeInterface.cpp(28): error C2664: 'void TBaseDynamicMulticastDelegate<FWeakObjectPtr,void,EGameState,EGameState>::__Internal_AddDynamic<IGameStateChangeInterface>(UserClass *,void (__cdecl IGameStateChangeInterface::* )(EGameState,EGameState),FName)': cannot convert argument 2 from 'void (__cdecl *)(UObject *,EGameState,EGameState)' to 'void (__cdecl IGameStateChangeInterface::* )(EGameState,EGameState)'
I guess the important part of this is:
cannot convert argument 2 from 'void (__cdecl *)(UObject *,EGameState,EGameState)' to 'void (__cdecl IGameStateChangeInterface::* )(EGameState,EGameState)'
It seems like the AddDynamic function is assuming the thing passed in should be extending from UObject. Well, I assume the only reason it needs to be a UObject is so the unreal engine can track it, so I tried to pass in the thisAsObject pointer from the interface:
gameState->OnGameStateChange.AddDynamic(thisAsObj, &IGameStateChangeInterface::Execute_OnGameStateChange);
But that still gives an error:
cannot convert argument 2 from 'void (__cdecl *)(UObject *,EGameState,EGameState)' to 'void (__cdecl UObject::* )(EGameState,EGameState)'
I guess the main question I should be asking is: Is this even possible?
Edit:
On closer inspection of the error, it looks like the function type it’s expecting is:
void funcName(UObject*, EGameState, EGameState);
Why is this? I assume that when DECLARE_DYNAMIC_MULTICAST_DELEGATE is created, it has to create a wrapper function to get the object passed in calling the delegate, but how would that effect what I’m doing in the interface?