Platform-specific subsystem implementations from Platform Extension plugin

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?