I have a local splitscreen multipayer game. When there is more than one player at the start of the level, only player 1 receives input from the gamepad and keyboard; none of the other players will receive input. The only fix I have for this at the moment is to left click with the mouse; once I left click everything functions normally.
Anyone have an idea as to why players 2, 3, and 4 aren’t getting input from their gamepad until I left click with my mouse?
I’m creating my game’s main menu; in it, I start with one player, but create players at a certain point along the UI’s flow.
If I launch the game, and just use the player 1 gamepad to control the UI, when I get to the point of other players being created, only player 1 receives input from their gamepad. No other players receive input. This is just like before.
However, if I click the mouse, even before any additional players are created, when the other players are created they do receive input from their gamepads.
And, if I then load another map, players on the newly loaded map (which in the interim the players have been destroyed in the previous map, and then created again in the new map) are still receiving input from their gamepads.
In light of this, I have a workaround; I’m going to force players to left-click their mouse in order to get past the first screen in the menu UI. That way players should correctly receive input from their gamepads.
Looks like the problem is that the game viewport is only setting keyboard focus when the window is focused (the keyboard == controller 1). So even after left-clicking, if you alt+tab away from your PIE viewport and alt+tab back to it, once again only controller 1 will be working. This is certainly something we’ll have to check out further and fix in the future.
In the meantime, there’s thankfully a much more preferable workaround to forcing a click. The blueprint library function from UWidgetBlueprintLibrary called SetFocusToGameViewport. Since it’s provided by a blueprint library, it can be accessed by any blueprint. If you’re using C++, it’s equivalent to calling FSlateApplication::Get().SetAllUserFocusToGameViewport().
The only caveat here is that the game viewport needs to have been registered already, which hasn’t happened when the level blueprint’s BeginPlay event fires (that’s also something we’ll try to fix). So, the quick and dirty way to fix this is to register a one second timer that triggers a call to SetFocusToGameViewport. Of course, if you have a better spot to put it after BeginPlay fires, by all means :).
Thanks for the explanation. It was really helpful. I had tried SetFocusToGameViewport, but had always tried to use it in EventBeginPlay with no results; now I know why it wasn’t working. It may be a good idea to add a comment to that function saying it requires a registered viewport.
I’ve added SetFocusToGameViewport to a few places in my code where I know it’ll get called after Event Begin Play; I actually kept the same “click” gate up, but it’s now responding to a gamepad and calling SetFocusToGameViewport. So, generally I shouldn’t have an issue any more.
Quesiton though:
Is there a way in code to know when a user has Alt-Tabbed away, and back, from an active viewport or window? If I could know that, then I could just call SetFocusToGameViewport when they Alt-Tab back.
There is technically a way, but unfortunately it isn’t quite that simple. Slate deals with focus on a per-widget basis, and the viewport is a type of widget. So for example, say you have a menu open with some option selected, then alt-tab away. When you return, you probably wouldn’t want to have your controller’s focus hijacked and set to the viewport instead of the menu.
I agree about the comment too, but timeline-wise hopefully we’ll have this fixed by the time a build with the comment would be released anyway. So hopefully by 4.8 these concerns will be a thing of the past.