// You probably want to do this from your GameInstance subclass ... // Namespace level in header DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnInputModeChanged, int, PlayerIndex, EInputMode, InputMode); ... // In class declaration: protected: TSharedPtr InputDetector; public: /// Event raised when input mode changed between gamepad / keyboard / mouse UPROPERTY(BlueprintAssignable) FOnInputModeChanged OnInputModeChanged; UFUNCTION(BlueprintCallable) EInputMode GetLastInputModeUsed(int PlayerIndex = 0) const { return InputDetector->GetLastInputMode(PlayerIndex); } UFUNCTION(BlueprintCallable) bool LastInputWasGamePad(int PlayerIndex = 0) const { return GetLastInputModeUsed(PlayerIndex) == EInputMode::Gamepad; } ... // In source // Do this at startup somewhere void MyExampleGameInstance::CreateInputDetector() { if (!InputDetector.IsValid()) { InputDetector = MakeShareable(new FInputModeDetector()); FSlateApplication::Get().RegisterInputPreProcessor(InputDetector); InputDetector->OnInputModeChanged.BindUObject(this, &USnukaGameInstance::OnInputDetectorModeChanged); } } // Do this at shutdown void MyExampleGameInstance::DestroyInputDetector() { if (InputDetector.IsValid()) { FSlateApplication::Get().UnregisterInputPreProcessor(InputDetector); InputDetector.Reset(); } } void MyExampleGameInstance::OnInputDetectorModeChanged(int PlayerIndex, EInputMode NewMode) { // Propagate dynamic multicast event, everyone else should listen on this OnInputModeChanged.Broadcast(PlayerIndex, NewMode); }