Hello!
We’re using FBlackboardKeySelector a lot in our custom Utility AI system, to provide key filtering when editing assets (similar to how they’re used for behavior tree nodes). The problem I’ve noticed while profiling is that it instantiates a LOT of UObjects when our Utility AI asset gets initialized, which causes framerate spikes when any AI archetype appears for the first time.
I thought of a quick solution: since the filtering doesn’t seem all that useful in non-editor build configurations, I simply made the factory functions empty stubs for those, and it drastically improved the performance (see the code snippet below). My colleagues have suggested to post this here, first to see if there’s a reason why I shouldn’t do this, and if it might be interesting to have this optimization officially as part of the engine.
Thanks!
#if WITH_EDITOR
AIMODULE_API void AddObjectFilter(UObject* Owner, FName PropertyName, TSubclassOf<UObject> AllowedClass);
AIMODULE_API void AddClassFilter(UObject* Owner, FName PropertyName, TSubclassOf<UObject> AllowedClass);
AIMODULE_API void AddEnumFilter(UObject* Owner, FName PropertyName, UEnum* AllowedEnum);
AIMODULE_API void AddNativeEnumFilter(UObject* Owner, FName PropertyName, const FString& AllowedEnumName);
AIMODULE_API void AddIntFilter(UObject* Owner, FName PropertyName);
AIMODULE_API void AddFloatFilter(UObject* Owner, FName PropertyName);
AIMODULE_API void AddBoolFilter(UObject* Owner, FName PropertyName);
AIMODULE_API void AddVectorFilter(UObject* Owner, FName PropertyName);
AIMODULE_API void AddRotatorFilter(UObject* Owner, FName PropertyName);
AIMODULE_API void AddStringFilter(UObject* Owner, FName PropertyName);
AIMODULE_API void AddNameFilter(UObject* Owner, FName PropertyName);
AIMODULE_API void AddStructFilter(UObject* Owner, FName PropertyName, const UScriptStruct* AllowedStruct);
template<typename T>
void AddStructFilter(UObject* Owner, FName PropertyName)
{
AddStructFilter(Owner, PropertyName, TBaseStructure<T>::Get());
}
#else
AIMODULE_API void AddObjectFilter(UObject* Owner, FName PropertyName, TSubclassOf<UObject> AllowedClass) {}
AIMODULE_API void AddClassFilter(UObject* Owner, FName PropertyName, TSubclassOf<UObject> AllowedClass) {}
AIMODULE_API void AddEnumFilter(UObject* Owner, FName PropertyName, UEnum* AllowedEnum) {}
AIMODULE_API void AddNativeEnumFilter(UObject* Owner, FName PropertyName, const FString& AllowedEnumName) {}
AIMODULE_API void AddIntFilter(UObject* Owner, FName PropertyName) {}
AIMODULE_API void AddFloatFilter(UObject* Owner, FName PropertyName) {}
AIMODULE_API void AddBoolFilter(UObject* Owner, FName PropertyName) {}
AIMODULE_API void AddVectorFilter(UObject* Owner, FName PropertyName) {}
AIMODULE_API void AddRotatorFilter(UObject* Owner, FName PropertyName) {}
AIMODULE_API void AddStringFilter(UObject* Owner, FName PropertyName) {}
AIMODULE_API void AddNameFilter(UObject* Owner, FName PropertyName) {}
AIMODULE_API void AddStructFilter(UObject* Owner, FName PropertyName, const UScriptStruct* AllowedStruct) {}
template<typename T>
void AddStructFilter(UObject* Owner, FName PropertyName) {}
#endif //WITH_EDITOR