Local Player (ULocalPlayer)
The local player refers to an object on a client machine that represents the player. A local player is created when registered to a world's UGameInstance, and is then initialized and eventually ready to interact with the game.
Initialization
The local player is created after the UWorld is constructed and UGameInstance is assigned to the world. The UGameInstance calls CreateLocalPlayer which creates a ULocalPlayer and also causes the world to create a player controller for the player by calling SetPlayer(NewLocalPlayer) on the controller. The Local Player is registered with the UGameInstance as a local player, passing in a unique identifier for the player in this particular game instance.
Local Player Context
Local Player Context (FLocalPlayerContext) is a struct declared in LocalPlayer.h that will "wrap" a ULocalPlayer and give you an insane amount of access methods that you're probably already doing on your own.
INFO
This is not a blueprint exposed struct.
Here are some problems FLocalPlayerContext can solve for you:
Consistent Access Methods
/**
* You can get Local Player in a number of ways, but
* establishing context is just as easy as constructing an instance
* of it like so.
*/
FLocalPlayerContext Context = FLocalPlayerContext(PlayerController->GetLocalPlayer());
APlayerController* MyController = Context.GetPlayerController();
AGameState* MyGameState = Context.GetMyGameState();
/** ... and so on */Check for LocalPlayer Association
FLocalPlayerContext exposes a method bool IsFromLocalPlayer(AActor* ActorToTest) that will check against the player state, player controller and player-controlled pawn to see if any of them are associated with the local player. This means an easier time checking against other Actors like network-owned player states or networked pawns.
You can even use this in UWidgetComponent logic to determine if a piece of UI attached to an Actor is owned by the local player or just an NPC.
Supercharge Widgets
You can use this context object and maybe a paradigm for data access to allow all of your systems to grab easy references to UObject and AActor pointers.
Well fuck, as it turns out, UUserWidget exposes a method:
UMG_API const FLocalPlayerContext& GetPlayerContext() const;Well. That's useful as hell. It even sets all of its instanced subwidgets in the widget tree. Here's SetPlayerContext from UUserWidget (lightly pseudocoded so Epic doesn't rock my shit).
/** God damn. This is cool */
void UUserWidget::SetPlayerContext(const FLocalPlayerContext& InPlayerContext)
{
PlayerContext = InPlayerContext;
CachedWorld.Reset();
if (/** Widget Tree is valid */)
{
/**
* 1. For each widget, run a Lambda function that accepts a
* UWidget* parameter
* 2. Cast the lambda param to UUserWidget. If valid, call
SetPlayerContext on it, passing in the InPlayerContext
*/
}
}At-a-glance
struct FLocalPlayerContext {
/** Access methods that let you establish context a number of ways */
ENGINE_API FLocalPlayerContext();
ENGINE_API FLocalPlayerContext(const class ULocalPlayer*, UWorld* = nullptr);
ENGINE_API FLocalPlayerContext(const class APlayerController*);
/** ... */
/** I genuinely think this is one of the best functions in this thing */
ENGINE_API bool IsFromLocalPlayer(const AActor* ActorToTest) const;
/** Getters for every common thing you find yourself trying to get anyway: */
ENGINE_API UGameInstance* GetGameInstance() const;
ENGINE_API class ULocalPlayer* GetLocalPlayer() const;
/**
* GetPlayerController, GetGameState, GetPlayerState, and GetPawn
* all also have templatized flavors of these functions in this context
* just in case you need to cast. They also allow passing in a boolean
* to perform a Cast vs. a CastChecked.
*/
ENGINE_API class APlayerController* GetPlayerController() const;
ENGINE_API class AGameStateBase* GetGameState() const;
ENGINE_API class APlayerState* GetPlayerState() const;
ENGINE_API class APawn* GetPawn() const;
/** Lmfao who the fuck uses this */
ENGINE_API class AHUD* GetHUD() const;
}Wow. What a utility! All for free!
Additional Notes
- This is probably stupid powerful if you combine it with a Viewmodel or something that can auto update.
- If you have a Player Controller reference that is valid, then it should be guaranteed you have a
ULocalPlayerto use.
