Multiplayer UnPossess

Hi,

Currently, I’m handling all input logic inside my Player Controller, using the Enhanced Input system. The mapping context is selected based on the possessed pawn - e.g. a humanoid pawn can walk, jump, etc.

Since the Possess is/must be executed on the server side only, I created a client-side BP-implementable event, something like this:

// header
UFUNCTION(BlueprintImplementableEvent, BlueprintCosmetic, DisplayName = "On Possess (Client)")
void ClientOnPossess(APawn* InPawn);

// cpp
void AMyPlayerController::AcknowledgePossession(APawn* InPawn)
{
	Super::AcknowledgePossession(InPawn);

	ClientOnPossess(InPawn); // <-- called here
}

This way, I can add the appropriate mapping context based on the possessed pawn on the client side. Since the mapping context is added based on the pawn, it would make sense to remove the mapping context in response to UnPossess.

However, there is no engine-side enforcement that the UnPossess is called/executed on the server side. Also, I could not find any suitable method that is called on the client side when the unpossessing is finished. There are multiple possible outcomes:

  1. Calling UnPossess on the client side only: the server does not know about the change in the possession state, so it starts to emit errors that the networked movement handling fails.
  2. Calling UnPossess on the server side only: the client is not notified, and it keeps processing input, and if the callbacks of the input actions are not null-safe, it will simply crash.
  3. Calling UnPossess on the server side, which in turn calls the UnPossess on the client side. In this case, there is a small amount of time when the server and client disagree in the pawn possession state. Networked UnPossess posted by anonymous | blueprintUE | PasteBin For Unreal Engine

Am I missing something? In my opinion, if calling the UnPossess on the client side is invalid, then it should be enforced by the engine to be called on the server only - similarly to the Possess function.

I’m thinking on using other functions, e.g. OnRep_Pawn or OnPossessedPawnChanged to track the possessed pawn instead of relying on the OnPossess and OnUnPossess events.