Removing Input Contexts when Using the Enhanced Input System

fine to answer you vague open ended question more specifically
Q: “How to remove/swap Input Mapping Context at runtine”
-after 10-20 minutes of playing around with Intellisense
in a C++ project (blueprint projects made in 5.1.1 or older will need to add EnhancedInput to modules and/or add-ons as needed)
created some Input Actions, and an Input Mapping Context assigning them as such


then in the C++ Character class header “InputsCharacter.h”

// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "InputActionValue.h"
#include "InputsCharacter.generated.h"

UENUM(BlueprintType)
enum class EControllingState : uint8
{
	ECS_General = 0 UMETA(DisplayName=General),
	ECS_Driving = 1 UMETA(DisplayName=Driving)
};

UCLASS(config=Game)
class AInputsCharacter : public ACharacter
{
	GENERATED_BODY()

	/** Camera boom positioning the camera behind the character */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
	class USpringArmComponent* CameraBoom;

	/** Follow camera */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
	class UCameraComponent* FollowCamera;
	
	/** MappingContext */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
	class UInputMappingContext* DefaultMappingContext;

	// Begin Other Mapping Context
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
	class UInputMappingContext* DrivingMappingContext;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
	EControllingState CurrentControlState;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
	class UInputAction* AccelAction;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
	class UInputAction* TurnAction;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
	class UInputAction* BreakAction;
	// End Other Mapping Context

	/* Shared between both*/
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
	class UInputAction* ChangeInputAction;

	/** Jump Input Action */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
	class UInputAction* JumpAction;

	/** Move Input Action */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
	class UInputAction* MoveAction;

	/** Look Input Action */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
	class UInputAction* LookAction;

public:
	AInputsCharacter();
	

protected:

	void ChangeInput(EControllingState TargetScheme);

	/** Called for movement input */
	void Move(const FInputActionValue& Value);

	/** Called for looking input */
	void Look(const FInputActionValue& Value);

	// added for demonstation
	void SwapInput(const FInputActionValue& Value);

	void TurnVehicle(const FInputActionValue& Value);

	void AccelVehicle(const FInputActionValue& Value);

	void DeccelVehicle(const FInputActionValue& Value);

protected:
	// APawn interface
	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
	
	// To add mapping context
	virtual void BeginPlay();

public:
	/** Returns CameraBoom subobject **/
	FORCEINLINE class USpringArmComponent* GetCameraBoom() const { return CameraBoom; }
	/** Returns FollowCamera subobject **/
	FORCEINLINE class UCameraComponent* GetFollowCamera() const { return FollowCamera; }
};

then in the cpp added (will start at the end of the default constructor)

	// ... Class constructor above this

	CurrentControlState = EControllingState::ECS_General;
}

void AInputsCharacter::ChangeInput(EControllingState TargetScheme)
{
	//Add Input Mapping Context
	if (APlayerController* PlayerController = Cast<APlayerController>(Controller))
	{
		if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
		{
			// Mapping Context to remove
			UInputMappingContext* tempCurrentMappingContext = nullptr;
			switch ( CurrentControlState )
			{
			case EControllingState::ECS_Driving:
				tempCurrentMappingContext = DrivingMappingContext;
				break;
			default:
				tempCurrentMappingContext = DefaultMappingContext;
				break;
			}

			switch ( TargetScheme )
			{
			case EControllingState::ECS_Driving:
				Subsystem->RemoveMappingContext(tempCurrentMappingContext);
				Subsystem->AddMappingContext(DrivingMappingContext, 0);
				CurrentControlState = EControllingState::ECS_Driving;
				break;
			default:
				// Remove the current Mapping Context to prevent conflicts
				// it is just a pointer after all, UBT does complain if you try to use nullptr
				// it is safe to remove something that isn't registered as it will be ignored
				Subsystem->RemoveMappingContext(tempCurrentMappingContext);
				// Add the new Mapping Context
				Subsystem->AddMappingContext(DefaultMappingContext, 0);
				// change Enum state to prevent dumb bugs
				CurrentControlState = EControllingState::ECS_General;
				break;
			}
		}
	}
}

void AInputsCharacter::BeginPlay()
{
	// Call the base class  
	Super::BeginPlay();

	// Apply Mapping Context
	ChangeInput(CurrentControlState);
}

//////////////////////////////////////////////////////////////////////////
// Input

void AInputsCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent)
{
	// Set up action bindings
	if (UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent)) {

		EnhancedInputComponent->BindAction(AccelAction, ETriggerEvent::Triggered, this, &AInputsCharacter::AccelVehicle);
		
		EnhancedInputComponent->BindAction(BreakAction, ETriggerEvent::Triggered, this, &AInputsCharacter::DeccelVehicle);
		
		EnhancedInputComponent->BindAction(TurnAction, ETriggerEvent::Triggered, this, &AInputsCharacter::TurnVehicle);
		
		EnhancedInputComponent->BindAction(ChangeInputAction, ETriggerEvent::Triggered, this, &AInputsCharacter::SwapInput);
		
		//Jumping
		EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Triggered, this, &ACharacter::Jump);
		EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Completed, this, &ACharacter::StopJumping);

		//Moving
		EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &AInputsCharacter::Move);

		//Looking
		EnhancedInputComponent->BindAction(LookAction, ETriggerEvent::Triggered, this, &AInputsCharacter::Look);
	}

}

void AInputsCharacter::SwapInput(const FInputActionValue& Value)
{
	switch ( CurrentControlState )
	{
	case EControllingState::ECS_General:
		ChangeInput(EControllingState::ECS_Driving);
		break;
	default:
		ChangeInput(EControllingState::ECS_General);
		break;
	}
}
// Other class functions (leaving implementation up to reader)

then assigning the Mapping Context, and Input Actions in the class Blueprint to avoid hard PathString references (don’t want someone moving or renaming something making a runtime resolution bug and breaking our program)

character is able to move around while DefaultMappingContext is applied and when hitting the ChangeInputAction button logically becomes a Car (model does not change)

Even though the ActionBindings are not removed from the EnhancedInputComponent they are not processed if they are not in the Current Mapping Context, and the only value I can see in removing them at runtime is if you were to destroy their respective Mapping Context

for Unbinding what is effectively a Delegate from the EnhancedInputComponent the closest was needing to get the BindingIndex but I couldn’t figure that out in the time I spent just playing with the system.

The most charitable I can be about this is: “Now we both learned something”