Cook warning caused by game feature plugin gameplay tags & developer settings.

If an actor class, defined within a game feature plugin, uses a gameplay tag, also within that plugin’s config folder, is referenced by a property within UDeveloperSettings this will trigger warnings on cook.

“Invalid GameplayTag GameFeatureTagTest found in property /Script/MyGameFeatureRuntime.MyGameFeatureActor:Tag.”

This seems to occur regardless of whether the developer settings are saved in a project defaults .ini file or a .ini file within the plugin itself. It seems that this causes the actor class to be serialized before the game feature is registered and the tags .ini file has been loaded.

Steps to Reproduce
Create a game feature plugin for any project with the following elements.

A class implementing UDeveloperSettings with a Config property for an actor class.

UCLASS(Config = MyGameFeature, DefaultConfig, meta = (DisplayName = "MyGameFeatureSettings"))
class MYGAMEFEATURERUNTIME_API UMyGameFeatureSettings
    : public UDeveloperSettings {
  GENERATED_BODY()

  UPROPERTY(Config, EditAnywhere)
  TSubclassOf<AMyGameFeatureActor> ActorClass = nullptr;
};

A blueprintable actor class with a gameplay tag property

UCLASS(Blueprintable, Abstract, BlueprintType)
class MYGAMEFEATURERUNTIME_API AMyGameFeatureActor : public AActor {
  GENERATED_BODY()

public:
  UPROPERTY(EditAnywhere)
  FGameplayTag Tag = FGameplayTag::EmptyTag;
};

Make a new gameplay tag in a tags .ini file within the plugin’s config folder

Make a blueprint actor class based on the abstract C++ class above

Assign the gameplay tag to the class defaults of the blueprint actor and assign that actor class to the config value of the project settings

Cook the project

Hello, although inconvenient this is expected behavior for the reason you mentioned: developer settings are loaded as part of the module at engine start-up, before GFPs are registered.

I recommend soft referencing the actor class via TSoftClassPtr<AMyGameFeatureActor> and load the class when they’re relevant for gameplay via RequestAsyncLoad. This lets you retain the designer convenience of selecting the actor class in project settings, while not forcing the class to be loaded early. This will require a small refactor since the class won’t always be loaded already:

  • your game code needs to request the async load and defer spawning until the async load request is complete
  • alternatively, your main menu can async load of the class and store the reference in a game instance subsystem (to keep the class referenced) before continuing on to game modes where the class is spawned

The soft class ptr in developer settings has the added benefit that the class and all its (texture, mesh, anim bp) dependencies aren’t always in memory. Generally we discourage hard referencing classes in developer settings because most classes don’t have a valid reason to be loaded early, it introduces load order issues like the one you encountered and RAM overhead.

In the real project, perhaps something else still caused the actor class to be loaded early? Either way, I’m glad to hear you were already going the soft class ptr route. Have a nice day!

I had the same thought and did try this when I originally encountered this issue. It didn’t seem to help, but clearly it does solve the issue in the test-case I created so presumably I made a mistake somewhere. Thanks for your time.