Though I’m a developper I’m quite new to UE4 and feel a bit lost about multiplayer concepts: I’m working on a game with mixed multiplayer distributed as this:
1-4 players on the same computer, sharing the same view (no split screen). I’ve read in the documentation that I only need to display player 1 viewport for that
1 more player using is own LAN device
I’m not including the LAN player for now, I focus on the local players
In my level blueprint, I have a loop to create 4 player controllers:
In the editor [multiplayer options], I’ve set the number of players to 1, since I don’t want to have multple viewports
my problem is that when I count the player controllers in the scene, the game always return 1
Another weird thing: when I set 2 players in the editor’s multiplayer options, I get this:
At this point, I guess I’m just misunderstanding how multiplayer is managed in UE4:
1)-can we create players on the fly without setting it in the editor?
2)-it looks like the player creation is not working. Am I missing a point?
3)-since I want the players to press start to join, how can I make the widget menu listen to every controller so I can detect who’s joining?
4)-is the level blueprint called for every player? Will I have to prevent the character creation loop to be executed by the other players?
5)-how complex will it be when I will need to add the LAN player to this? Do I have any chance to be able to run it with just 2 viewports as I’m expecting?
Thanks for your help, any suggestion is welcome!
ok I figured out some partial answer by myself:
-the level blueprint is called only once, no matter how many players are set in the editor preferences
-player creation was indeed not working. For some reason, it fails if executed from the level blueprint. I moved the “create player” nodes into the gamemode BP and it works now (carrefulll though, the loop must only be 3 iterations because the game already has one existing player controller on startup. Which, I guess, is a mandatory requirement)
I still have to figure out a way for the menu widget to listen to all inputs. I will try using the tick event to check every input controller one by one, but I wonder if it’s a good way of doing it. It feels a bit hacky and not optimal.
once again, if any of you guys have any suggestion, you’re welcome
as you already figured out, the LevelBlueprint is called once per NETWORKED Player.
To not have misunderstandings:
- Networked Player: Lan, Internet
- Local Player: Players on the same Computer / maybe Splitscreen
Each Player needs a valid PlayerController to be correctly represented. The initial Player, the one you get with simply starting the game with the PlayerNumber Setting at 1 already has a PlayerController.
The PlayerNumber Setting is for Networked Players. If you set it to 2+, it will create a LAN Connection. This has nothing to do with Local Players. Keep in mind, that the GameMode only exists on the Server. If you add a Networked Player to the setup, he will NOT call the GameMode functions (if he’s the client).
Split UI from Logic!
Always remember: UI is meant to display information and not to handle logic!
This means, you should not let your Widgets Listen for the Controller Input.
Spawn your Widget at a place where you can access it (not the LevelBlueprint). For example the GameMode or GameState. Now let the PlayerControllers listen for their own Input and if you notice an Input, just set a Variable in the PlayerController. Let the Widget only GET data from the each PlayerController and display it.
- Spawn Widget in a class you can easily access (GameMode/GameState) You never know, if you need it again!
- Let the PlayerControllers listen for Input and set a simple Boolean for “Joined” or something
- Let the Widget get each PlayerController and display information, based on the Boolean or what ever you want to use
Adding a Networked Player to the Local Game
To be honest, I’ve never done this. I actually also have never worked with LocalPlayers. I only work with the Networked stuff. But you need to adjust your logic based on the following information:
- Networked CLIENTS don’t have a GameMode.
- Networked CLIENTS only have their own PlayerController
- Networked CLIENTS use the replicated GameState (PlayerArray) and PlayerState to share information about the current State of the Game and Player (minus PlayerCharacter stuff, like Health. That’s managed in the replicated PlayerCharacter)
- You may need to manage Local Clients and Networked Clients differently, since I don’t know if each Local Client gets a Replicated PlayerState for the Network Session
All in all, as soon as you add Network to it, you need to follow the Networking rules of replication.
I hope that helps to get started!
Wow, now that’s an answer !
Thank you so much for this, this is exactly what I needed to know
I did not understand very well, can you show a print of the blueprints?
UMG is not currently designed to handle multiple players on one widget. Each widget is Owned by a speicific Player Controller (usually the one who created it).
However, I have made the other player controllers “follow” the focus to the most recently-focused widget using the On Added To Focus Chain Event. After getting this to work, I thought better of it and decided to only have player 0 control all the widgets except the player character setup menus.
Clarification: Each device has only the PlayerControllers of the players local to that device. For Clients this is anyone who has connected a controller to the machine AND who has had a Player Created for them on that machine.
For the server this includes the server machine’s local Players, and ALSO all the connected Client Players, HOWEVER on the server, the remote playercontrollers will all have an ID of -1 because they are not controlled by a player on the server. So that’s why you want to keep track of them using PlayerState → Player ID
To get mine to work that way I had to create the players first, assign the player setup widgets to their player controllers when i creat them, and then listen for input events in the widget (there is a node for that not the same as the inputaction event node but more like a delegate) this way each player setup card is controlled by the player who owns it that it was created for, including the “join” action fro pressing the Start button on the widget’s owner’s controller.
You have to modify a C++ class GameViewport or. ake a C++ child class of it and select that in project settings as default if you want to obtain input events without them coming through an already created Player.
So I just create all 4 players before that menu shows up.