Okay, poking through engine code has led to a couple discoveries:
- Each object which can have a subsystem has a
FSubsystemCollectionassociated with it. ThisFSubsystemCollectiontakes a template, so to use myGameInstanceexample,UGameInstancecontainsFSubsystemCollection<UGameInstanceSubsystem>. - When the GameInstance
Initfunction gets called, theFSubsystemCollectionlooks at everything which inherits fromUGameInstanceSubsystem(or whatever subsystem it’s using at the time). IfUSubsystem->ShouldCreateSubsystemreturns true, then it’ll create the associated subsystem as a new object, parented to whatever theFSubsystemCollectionsays its parent should be (UGameInstance, in our case). So in reality, all our subsystems get created as children of our main system. - The end result is that you can call
UGameInstance->GetSubsystemwith any valid child class ofUGameInstanceSubsystemand it’ll return an instance of that class. It’s similar to having a component on an actor. - By itself, a subsystem doesn’t actually do anything. Nothing gets called on it, and it doesn’t override any functions. You have
InitializeandDeinitializeto start and stop the subsystem, but otherwise it’s an open book as to what you do with it. It just makes code clearer for non-actor objects which could benefit from a component-like interface.