Do you use Set Input Mode Game Only node in your game? Have you experienced any strange behavior of a user input controller? If yes, stick with me, I am going to shed some light on how this function works under the hood.
Unreal Engine 4 has three input modes:
- Game Only
- UI Only
- Game and UI.
In a couple of words, Game Only mode is for a game controller; UI Only mode is for UI, obviously; and Game and UI – is best suited for games with rich UI (e.g. a typical RTS). I won’t go into details – that’s not the purpose of this blog post. If you need info you may check this video – it is pretty helpful.
It covers pretty much everything you need to know. Except for one thing, though. And the author is missing it. It is Set Input Mode Game Only and how it is different from the UE4 default input mode.
Set Input Mode Game Only problem
When I was implementing a menu for my game I faced a problem similar to this one: https://answers.unrealengine.com/questions/420047/an-lmb-event-is-only-triggered-with-a-double-click.html
After quitting the menu and switching back to Game Only mode, I had to click twice or double click in order to get the mouse back to work. I tried using Set Input Mode Game and UI but that was not exactly what I wanted. Now the reason why Game Only mode did not work is that the mode is not exactly the default mode of UE4.
Let’s examine Project Settings -> Input section of a UE4 project. You will see that Default Viewport Mouse Capture Mode may have the following possible values:
A default value could be “Capture Permanently Including Initial Mouse Down” or another one. The problem, however, is that Set Input Mode Game Only resets this option to “Capture Permanently” value. And if it is not your default value, your game will run not as you expect.
The solution
Now let’s check the source code. Open WidgetBluprintLibrary.cpp and the method UWidgetBlueprintLibrary::SetInputMode_GameOnly
You see, that calling this method just creates a new object with no arguments and that is equal to setting Default Viewport Mouse Capture Mode to “Capture Permanently”. And if you need other values you will have to initialize input mode manually.
I made a small helper function in my player controller class. It is not universal but suits my needs perfectly. Have a look – it may be something you are looking for:
void MyPlayerController::SetInputModeGameOnly(
bool InConsumeCaptureMouseDown)
{
FInputModeGameOnly InputMode;
InputMode.SetConsumeCaptureMouseDown(
InConsumeCaptureMouseDown);
SetInputMode(InputMode);
}
Thx man it was driving me crazy, ue started doing this bug even tho the same setup was applied from beginning and working well… Took me a while to find your article but it was worth every second.
Thx again man
You’re welcome.
I’m glad, you found it helpful
Thanks SYT, that’s the cause of my current trouble with UE4, I’ll try to solve using your solution or related similar.
Great! Thx!
You are welcome, iijavix
For those of use that do not use C++ often, could you detail what you did with that code?
And how would you go about calling that function then?
Hello!
I made a different version of SetInputModeGameOnly function, which sets another value for “Default Viewport Mouse Capture Mode” setting. This differs from the default implementation.
I don’t think you can do the same trick in BP, but you can basically copy-paste my code snippet to your C++ controller class and declare this function as BP Callable:
Add this annotation to a function definition: UFUNCTION(BlueprintCallable).
This will allow calling this function from a blueprint.
This is not exactly on topic of GameOnly, but GameAndUI. Perhaps you could point me in the right direction for a solution. I’m not able to get mouse axis or mouse delta input unless rmb or lmb is down in this mode. What I’m intending is activating a “mouse look around” with a keyboard key (such as, you’re holding Left Alt, camera turning around happens with mouse, except it doesn’t). Switching to GameOnly for the duration of “mouse look around” works just fine, but is not an option in my project. I am to stick to GameAndUI only. Any ideas on how I could work around this?
You might want to look at Axis Values section in the blueprint editor.
https://imgur.com/soSwB9P
But first, define axis mappings.
It would be a bit silly if I didn’t define axis mappings now, would it?
That Input mode just refuses to take any axis input from the mouse unless lmb or rmb are down. My chosen mouse pan key is a keyboard key.
I’ve ended up doing a less than elegant, but working solution for this:
I’ve made two methods to trigger lmb pressed/released and obviously a bool to know the “fake”. (Mouse cursor is hidden during camera panning by design, so clicking anything is not going to matter either way. To make a little more sense of this, it’s is for a 3rd person MMO style controls that include keyboard, mouse turning, mouse panning, UI, click targeting etc.)
Using them like so:
void ASomethingCharacter::MousePanEnd()
{
TriggerMouseLMBReleased();
if (SomethingController->bShowMouseCursor == false){ SomethingController->bShowMouseCursor = true;}
if (CameraSnapBack){CenterView();}
}
And a similar one for pan start with a press, but I won’t take up a bunch of room here pasting all that. Of course, the real lmb is aware of the “lie” and won’t be triggered by the mouse panning impostor. xD
Is that possible for you to intercept mouse axis input in your widget? UserWidgets have a lot of useful event handlers – you might put your mouse pan code there.
I imagine that this could be possible, but we would like to keep all char movement and camera work in one cpp to avoid spaghetti monster and debug hell later. The fact that a different person is working on UI is also a factor in my project. So far all is fine with a fake pointer event to slate, will see how it plays out as this movement system gets more evolved.
Here’s code if it’s ever useful for someone with a similar need to imitate a mouse click for whatever reason:
#include “SlateApplication.h”
FSlateApplication& SlateApp = FSlateApplication::Get();
FPointerEvent MouseDownEvent(
0,
SlateApp.CursorPointerIndex,
SlateApp.GetCursorPos(),
SlateApp.GetLastCursorPos(),
SlateApp.GetPressedMouseButtons(),
EKeys::LeftMouseButton,
0,
SlateApp.GetPlatformApplication()->GetModifierKeys()
);
TSharedPtr GenWindow;
SlateApp.ProcessMouseButtonDownEvent(GenWindow, MouseDownEvent);
So, are you supposed to call MyPlayerController::SetInputModeGameOnly(false), to set the Default Viewport Mouse Mode to EMouseCaptureMode::CapturePermanently_IncludingInitialMouseDown?
Wouldn’t be better to both overload and overwrite the APlayerController::SetInputMode() and APlayerController::ApplyInputMode(), inserting an EMouseCaptureMode as a parameter, to cover all the possibilities?
Besides that, I couldn’t find a way, in c++, to process keyboard actions when I’m in FinputModeUIOnly… Do you know a workaround for this situation?
Thanks!
If using blueprints there is a function ‘Set Viewport Mouse Capture Mode’ that can be used to set the capture mode directly after the ‘Set Input Mode Game Only’ node. You can use this node to return the setting to whatever default you had.
Thanks so much for that Hixtra. Perfect