Spawn multiple player controllers in multiplayer game


I’m trying to use a custom controllers to control different players in a multiplayer game. Here is the part where I get the player and attach to this controller. It works fine when number of players is 1, but as soon as there are 2 or more players in the game, there are multiple instances of player character but there is only 1 instance of player controller. Hence theoretically there is only 1 character that is getting controlled. But all characters are still receiving control mechanics from this custom controller. Basically I want the game to spawn controllers where the amount is the same as the number of players in the game so that each controller is controlling one player character.

@anonymous_user_3cd4384c Thanks for your reply! I am aiming for multiplayer game over network, and I just checked that there are 2 player controllers on server and 1 on client, meaning they get spawned correctly. Those are some actions that I would like the character to do when certain inputs are received.

The problem is those inputs will be received and actions will be made by controllers to characters, but when I exit the game I will receive those errors, indicating me that Cast Player which is the character reference is None. Since all character actions are in controller blueprint, I will need character reference to apply actions to.

[This is the video][4] I followed on creating custom controller, it works fine for 1 player, but if there are more than 1 players, the error messages above will show up. I modified my “Getting player character reference” part a little bit which is the first image of this thread. How am I supposed to modify my controller so that it works with multiplayer games? Thanks a lot!

I have to say, that I don’t really understand what you are aiming for but I assume that you mix up what player controllers actually are.

Each character has to be controlled by a player controller so the game know which inputs to use. If you have character A and player controller Z, everything works fine as intended. If you add an additional character B which also uses a player controller Z then this is also fine. Why is this fine? Because a player controller can only possess one character at a time. If you want to test stuff on one machine but with 2 players, you will likely get two windows, one for each player and character. Both windows can use the same player controller without creating problems. The one window moves character A and the other window moves character B. This works because the player controllers have indexes as well.

Link: Get Player Controller | Unreal Engine Documentation

As you can see the player controller needs a number and in computer science stuff starts with 0, so this is the very first player. If have multiple player controllers in one window that you will have index 1 for the second player and so on. But if you want to create a multiplayer experience with multiple windows or on multiple machines, then things change a bit, because every local player is always player controller 0, which might be confusing at first. The number of possessed characters is always the number of player controllers, but you can have characters which are not possessed (like, maybe you want to switch to that one later).

So this is out of the way. What do you want to do? You want to control different characters with one player controller? Like I said each player controller can only possess one character at a time. But you can switch between the characters when you unpossess the first and then possess the next character which you would like to control. I can also think of a solution where you put multiple components in your character and according to the buttonpresses you can determine which component should do what as if you would have a group of something.

If you want to make a 4 player multiplayer game, then I assume that you want to do that over network with multiple pcs where everyone is playing his character he sees/focuses on. The only other way I can currently think of is some sort of local multiplayer where you fight with or against your buddies on a couch or something while everyone is holding a unique controller/gamepad to move and interact with his/her character on the screen.

If you want to do something over network, then you don’t have to worry about the number of controllers or alike. One player can serve as the listen server while playing. The server is locally controlled on the pc the game runs on. If you have an other computer connecting to this server, doesn’t matter if LAN or Internet/Steam, the engine itself will generate an additional player controller for the new player in the “PostLogin” Event. You can access this new player controller because in the event “PostLogin” the new player controller is an output pin.

Quote: “PostLogin - Called after a successful login. This is the first place it is safe to call replicated functions on the PlayerController. OnPostLogin can be implemented in Blueprint to add extra logic.”

So if you have only the server, there is only one player controller. If a client connects to the server, then there are two player controllers, the server and the client. And every new client will get their own player controller. So you will always have 1 player controller for the server and one player controller for each client who connected.

If you want to do a local multiplayer or so called “couch co-op”, you need to handle the indexes of player controllers inside of your game “somehow”. Why do I say somehow? Because I do not know everything and I didn’t do local multiplayer that much on one screen. But you should be able to create multiple player controllers, even of the same class, which get input from different peripherals, like keyboard, mouse or gamepads.

Thanks for your answer! So I’m making a 4 player multiplayer game. I have a CustomController that will control ThirdPersonCharacter_Experimental which is the character for players. When I start the game in 2 player mode, there are 2 ThirdPersonCharacter_Experimental instances in the game but there is only 1 CustomController instance. Since each player controller can only possess one character at a time and I want all characters to be controlled by player controllers all the time (since it’s multiplayer), I assume that I need multiple instances of CustomController. Is there a way I can achieve this? Thanks!

Thank you for your reply! I have updated the question with more images and descriptions, could you take a look and help me on it? Thanks a lot!

“isBeingControlled” is a variable in my character class. I never used it or changed its value anywhere besides “Get Player Character” block in controller blueprint and its default value is false because I want it only be set to true after a controller stores the character reference into Cast Player variable. After checking the number of elements in the array I found out that in the “Get Player Character” block the number of elements are 1 (Server) and 2 (Client 1). What does this mean in terms of networking? Thanks a lot!

Thank you very much for you recommendation on multiplayer tutorial, I will work through them. Thanks a lot!

I did take a look. According to the video you took the controls which were inside of the pawn and copy pasted them into the player controller. You told the engine that the player controller holds those input information now.

Your Mouse Input and Jump look fine, IF you have some information in the variable “Cast Player”. Let’s check if you do.

Let’s have a look at your “Get Player Character”-block:
At “Begin Play” you tell the game that it should fire the event “Cast Player” which is your custom event. “Cast Player” then gets all your actors of your desired class, which is your third-person character in this case. It returns an array of those characters and you want to give this array into a ForEachLoop. But what do you actually do? You want to branch and the branch depends on the boolean “is being controlled”.

You get the error that you try to access “none”. Where do you access “none”? Inside of your player controller “custom controller”, because you want to access “Cast Player”. So, where is “Cast Player” set, does it have an default value? It will have no default value, because it is “none”. You could argue, that you set the “Cast Player” inside of your ForEachLoop, but yeah, here comes the problem.

It appears you never set “Cast Player”, so it stays “none”. Every actor you check is controlled. By whom? By yourself I would assume. therefore it always returns true and you will never set the “cast player”, because there are no actors who are not controlled, otherwise it would have been set to “something”.

You should debug this and print something out(like the index value of your array element) if it branches into the “true” path, so you know for sure how many/which actors are actually “controlled” and how many are “not”. Do you have auto possess enabled? It sounds weird to me, that you move “every” character with your input, because that would mean that you do not control that pawn, but that class and therefore everyone.

Long story short… I would suggest this tutorial series to you:

This is Epic’s Multiplayer Tutorial and they lead you through the whole process of creating the menu, settings and controls to get a network game basicly working, including a lobby, several different characters (which are inherited from the same parent). In Multiplayer the topic replication is a beast, just like ownership and you have to wrap your head around that also and following those videos/steps it help me for example to understand those things better. I hope that you will also find them useful.

And if you worked your way through this tutorial you can expand it in every way you like it. And in the best cast you know what those things do, so you can adjust everything on your own for the first few changes :wink: The next barrier is always ahead xD

If “isBeingControlled” is always “false” then “Cast Player” would never be “none”, because it would be set. Maybe something about the actor is not right, so check “isValid (with the question mark)” of the actor you are checking. It may be that you access something which is not valid. And in that case the variable “Cast Player” can not be set despite branching into the “false” path, because the value is not valid.

The index numbers should start with 0, because that is how arrays work, so what happened to the 0? In terms of networking the player controller with the index 0 is always the local machine. So on the server player controller 0 is the server itself and on the client player controller 0 is also the client itself. If you get all actors of your characters and generate an array I guess there is no structure (maybe it takes the server’s character first? you have to test that to be certain), so you have to check which character has the authority (authority is also important in networking so you know if you execute stuff on the server or on the client side). The character/player controller who has the authority is the server in most cases, but there are also other cases where things switch around.

I’ll look into that. Thank you so much for your reply!

So i has the same issue, to fix it i simply did was go in the character i am spawning and set its ai controller to none.