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.
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.