👆

Simulated Touch With Input Swapping

Problem:

So swapping keyboard with touch input is quite easy by default in unreal engine all you need is one function which is called ActivateTouchInterface.

PlayerController->ActivateTouchInterface(TouchInterface);

If you provide no touch interface it will switch your input from touch to mouse and keyboard, but our problem is that our project has pixel streaming enabled which means it always run on a remote PC. To support touch even in that scenario we have to simulate mouse as touch input, this can be done in project settings:

You can find this setting in Engine→Input inside your project settings.

With this option enabled there is now another issue at hand upon switching to keyboard at runtime will mess up your camera controls even if you turn this option off in Input Settings.

We noticed this bug in our testing phase and found out that this maybe happening because of the DefaultInput Config is still set to false even if you change your bUseMouseForTouch inside the input settings.

Upon manually writing in that DefaultInput Config still didn’t solve the issue because turns out the engine is still overwriting it.

Solution:

In order to fix this issue we came across a function inside SlateApplication there is function called:

void FSlateApplication::SetGameIsFakingTouchEvents(const bool bIsFaking, FVector2D* CursorLocation)

So in our function where we swap the inputs we call this function via getting the slate application and it fixed the issue.

Change Platform UI:

My UI get’s added to viewport on begin play and it pops up 2 buttons which player needs to choose which input mode they want to use.

Here is how the Widget blueprint looks like:

Construct:

Desktop Button:

Mobile Button:

The main thing you will notice here is that we created a custom function in our game instance class which swaps the input given the UTouchInterface

Game Instance:

Create a new game instance class, honestly it might be better to move this function into player controller but I choose game instance for this example.

	UFUNCTION(BlueprintCallable, Category = "Input")
	void ToggleTouchInterface(APlayerController* PlayerController, UTouchInterface* TouchInterface);

Implementation:

void UMyGameInstance::ToggleTouchInterface(APlayerController* PlayerController, UTouchInterface* TouchInterface)
{
	if (!IsValid(PlayerController))
	{
		return;
	}

	AMyPlayerController* MyPlayerController = Cast<AMyPlayerController>(PlayerController);
	if (IsValid(MyPlayerController))
	{
		return;
	}

	const bool bIsUsingTouch = IsValid(TouchInterface);

	MyPlayerController->ToggleTouchInput(bIsUsingTouch);

	PlayerController->ActivateTouchInterface(TouchInterface);
}

before calling the ActivateTouchInterface we run a custom function which we created in our player controller called: ToggleTouchInput this takes a Boolean as parameter which determines if we are using touch or not.

Toggle Touch Input In Player Controller:


void AMyPlayerController::ToggleTouchInput(bool IsUsingTouch)
{
	UInputSettings* InputSettings = UInputSettings::GetInputSettings();
	if (!InputSettings)
	{
		return;
	}

	InputSettings->bUseMouseForTouch = IsUsingTouch;
	InputSettings->SaveConfig();

	FSlateApplication::Get().SetGameIsFakingTouchEvents(IsUsingTouch);

	GConfig->SetBool(TEXT("/Script/Engine.InputSettings"), TEXT("bAlwaysShowTouchInterface"), IsUsingTouch, FPaths::ProjectConfigDir() + "DefaultInput.ini");
	GConfig->SetBool(TEXT("/Script/Engine.InputSettings"), TEXT("bUseMouseForTouch"), IsUsingTouch, FPaths::ProjectConfigDir() + "DefaultInput.ini");
	GConfig->Flush(false, FPaths::ProjectConfigDir() + "DefaultInput.ini");
}

Nothing fancy here at first all we are doing is getting and saving the input settings with our new input mode, after that we call the function from Slate application and update our touch mode there as well.

Once that is finished for sake completion we save the Booleans in our Default input config as well.

Hope this helps, it is quite common for Clients to demand both touch and desktop controls in pixel streaming projects, switching them isn’t as straight forward since you need to be using simulated touch from the get go.