I’ve been looking at behavior for Platform Extensions, but I’m uncertain as to how I can achieve platform-specific implementations of a subsystem from a plugin.
For example, I want to have a plugin that has a shared implementation of a subsystem which doesn’t get instantiated or registered. I then want to have platform-specific derived subsystems in Platform Extension plugins which will be instantiated and registered with the subsystem collection. Will the engine handle subsystem registration automagically, or will I need to write bespoke functionality in the module, or do I need to have a platform-agnostic implementation that defers to platform-specific implementations where appropriate?
Thanks!
Hi,
I would suggest looking to TextToSpeech subsystem as an example:
- D:\UE_5.5\Engine\Plugins\Experimental\TextToSpeech\Source\TextToSpeech\Public\TextToSpeechEngineSubsystem.h
- D:\UE_5.5\Engine\Plugins\Experimental\TextToSpeech\Source\TextToSpeech\Private\TextToSpeechEngineSubsystem.cpp
- d:\UE_5.5\Engine\Platforms\PS5\Plugins\Experimental\TextToSpeech\Source\TextToSpeech\…
- D:\UE_5.5\Engine\Platforms\PS4\Plugins\Experimental\TextToSpeech\Source\TextToSpeech\…
- D:\UE_5.5\Engine\Platforms\Switch\Plugins\Experimental\TextToSpeech\Source\TextToSpeech\…
- D:\UE_5.5\Engine\Platforms\XboxCommon\Plugins\Experimental\TextToSpeech\Source\TextToSpeech\…
The way it is structured, you have a high level subsystem that contains common code and then get platform specific implementation. If for a given platform or condition you don’t want to instantiate the subsystem, you can override the following function from USubsystem base class
virtual bool ShouldCreateSubsystem(UObject* Outer) const { return true; }
I think that’s close enough to your requirements to be a good starting point. Take a look and let me know if you that makes sense to you or if you have questions.
Regards,
Patrick
Hi,
The TextToSpeeh is a good example of plugin platform extension with a subsystem specialized per platform. For your case, I would use a structure where the UMySubsystem is the public interface. Everything else would be implementation specific.
[Image Removed]The UMySubsystem just need to create the proper concrete class and delegate everything to the implementation. Then, you can structure your implementation the way you want. You can have a base common class (FMyBaseSubsystem) that you can override in plugin platform extensions as you wish. The engine uses this kind of approach in many places.
Base module: \Engine\Plugins\Experimental\TextToSpeech\Source\TextToSpeech\Private\TextToSpeechModule.cpp is a good example:
virtual void StartupModule() override { PlatformFactory = MakeShared<FPlatformTextToSpeechFactory>(); }
Plugin extension that defines the factory: \Engine\Platforms\PS5\Plugins\Experimental\TextToSpeech\Source\TextToSpeech\Private\PS5TextToSpeechFactory.h
`lass FPS5TextToSpeechFactory : public ITextToSpeechFactory
{
public:
FPS5TextToSpeechFactory() = default;
virtual ~FPS5TextToSpeechFactory() = default;
virtual TSharedRef Create() override;
};
typedef FPS5TextToSpeechFactory FPlatformTextToSpeechFactory;`If for some reasons you want to have a base subsystem + platform specific subsystems that expose extra public platform specific API… then you could use a similar idea. You will have to experiment, but I think you could declare your base subsystem as abstract, then declare your platform specific subsystem in platform extension plugin… I’m not sure this is your use case… I would probably design the system differently depending how it is expected to be used.
UCLASS(Abstract) class UMySubsystemBase : public UEngineSubsystem { GENERATED_BODY() }; ... class UMySubsystemGDK: public UMySubsystemBase { };
Regards,
Patrick
It doesn’t appear that TextToSpeech has platform-specific subsystem implementations, but instead uses a factory pattern to construct smaller-scope objects that then implement an interface called by the subsystem.
My intention is to have the subsystem itself be the interface, and allow platform extensions to extend/override subsystem behavior, but because of the way subsystems are automagically detected and injected, I feel like that isn’t possible?
Could I have the platform-agnostic subsystem return false from ShouldCreateSubsystem, and then have the platform-specific implementations override that to true?