Local Player
The local player refers to a player on a client machine that is typically associated with a few things:
- Player Controller (
APlayerController) - Player State (
APlayerState) - Pawn (
APawn) - Game State (
AGameState) - Game Mode (
AGameModeBase) - Game Instance (
UGameInstance)
Wow, that's a lot of shit to keep track of. If you want to support local multiplayer or local couch co-op, it gets worse! Fortunately, we have FLocalPlayerContext to help with that.
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.
