It seems like static is the way to go. I’ve read answers on here which suggest that the static keyword is for variables etc which don’t change much. That’s a misconception. A static data member or function is in the class scope, so the value is the same for each object of the class. It will retain it’s value between calls to a function if used in a function, or in every object of the class.
I’ve done a bunch of different tests and it seems as if its also possible to make a static delegate signature, and fire a delegate in the interface from a virtual function in one class, that’s bound to a function in another class. In the header of the interface;
DECLARE_DELEGATE_OneParam( FDelegateSignature, AActor* )
UINTERFACE(MinimalAPI)
class UTestInterface : public UInterface
{
GENERATED_UINTERFACE_BODY()
};
class MY_API ITestInterface
{
GENERATED_IINTERFACE_BODY()
static bool GetTestBool();
static void SetTestBool(bool NewValue);
static void AddToTestArray(AActor* Other);
static void RemoveFromTestArray(AActor* Other);
static int32 GetArraySize();
virtual void FireDelegate(AActor* TestActor) = 0;
static FDelegateSignature MyTestDelegate;
private:
static TArray<AActor*> TestArray;
static bool bTestBool;
};
In the cpp:
UTestInterface::UTestInterface(const class FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
}
TArray<AActor*> ITestInterface::TestArray = {};
FDelegateSignature ITestInterface::MyTestDelegate = {};
bool ItestInterface::bTestBool = true;
bool ITestInterface::GetTestBool()
{
return bTestBool;
}
void ITestInterface::SetTestBool(bool NewValue)
{
bTestBool = NewValue;
}
void ITestInterface::AddToTestArray(AActor* Other)
{
TestArray.Add(Other);
}
void ITestInterface::RemoveFromTestArray(AActor* Other)
{
TestArray.Remove(Other);
}
int32 ITestInterface::GetTestArraySize()
{
return TestArray.Num();
}
It’s important to remember to override the pure virtual function in every class that uses the interface, otherwise it won’t compile. Then in the constructor of the UObject where the delegate will fire I’ve got;
MyTestDelegate.BindUObject(this, &UMyUObjectClass::SomeFunction);
And in the class that is sending, in the function that overrides the pure virtual FireDelegate interface function I’ve got;
MyTestDelegate.Execute(TestActor);
This all works fine. I can use the static delegate to send messages directly from one class to another, or I can store info in the static data members of the interface and access those from objects that share the interface when needed.
I’ve made a few assumptions here so, anyone who’s expert at coding, please comment if I’ve done something wrong or unsound!
EDIT: I think maybe the reason why static data members are (seemingly, reading between the lines) discouraged in UE4 is because they are initialized when the program starts. So it looks like in the editor, they retain their value even between begin plays. Which means that, if you do this, you probably need to reset the static data members when the level unloads, or at some point that guarantees you begin a fresh play session with the static data members as you expect them to be.