My apologies, I took a random example from SocialManager.cpp (from the OnlineFramework), and they do in fact implement their own GetGameInstance function, so this wasn’t a good example on its own.
Anyway, since the question turns out to not be as trivial as I expected, it’s time to take a step back and do something that I should have done from the get go, which is: Are you asking the right question?
See.. The thing with architectural issues for frameworks as experienced as UE is, when you’re encountering weird difficulties and it feels like the engine is fighting you on this.. It’s often because you’re accidentally pushing against inevitable constraints.
For instance, it doesn’t make sense to worry about accessing the EnhancedInputSubsystem for a “main menu”, if you don’t have a way to display that main menu. You won’t be able to push the widgets to it, if you don’t have a reference to the viewport. And which class represents the ui?.. AHUD! Which is a responsibility of the PlayerController.
So really, by trying to go around the Player Controller.. All you’re doing is taking the risk of accessing the game instance too early.
Rather, you should make sure that your “main menu” input settings are read in a location that ensures that everything is ready for you. For instance, inside a PlayerController virtual function like PostInitializeComponents() (which can spawn the default hud class, so you know it’s good for that sort of stuff if you wait until after the Super::PostInitializeComponents())
Or inside a child class of AHUD itself. This way, you can have multiple HUD subclasses to swap between different UIs.. Some games do it this way.
Or, perhaps even better, read the settings from inside a child class of the LocalPlayer itself! After all, EPIC is clearly telling us with the EnhancedInput subsystem, that it’s a business for the LocalPlayer.. So why not lean into it, and have your own code reside in an override of ULocalPlayer::PlayerAdded?
–
..And if you really want to know how to access the GameInstance without going through the world:
First option: Create your own GameInstanceSubsystem. From there you can easily get a reference to the GameInstance, and you know for a fact that such a subsystem is spawned when the GameInstance is ready.. However, there is no guarantee that you won’t be too early to get a reference to the LocalPlayer!
Second option: Use GEngine. There are various functions there to get the LocalPlayer from weird references, like using a UPendingNetGame or a UGameViewportClient.. Pretty unorthodox way to go about it though. If you manage to get a hold of the WorldList, you can iterate on it (outside of the editor it should only have one or two UWorld instances in it, all valid) and find the reference to the GameInstance that they share.. But again, you’re fighting the UE framework by doing this, which is usually a red flag that you’re doing things out-of-order and therefore may run into references that are not yet ready.