Creating Players

Hey all,

So, I’m getting in a tangled mess and going round and round in circles here…

I wanted to set two different pawns for players 1 and 2.

I set the game mode to not use a default pawn. I was unable to set the default player controller to “none”, so left it pointing to my base class.

When the game starts I have a function which performs three steps. First, its removes the player with the player index 0 - I assumed this would be the default one created by the base class.

Next, it creates player 1 using the Create Player node. I spawn a pawn, possess it with the just created controller.

I then repeat that step for player 2.

Initially I was setting the “Player Index” values to 0, and 1 respectively.

I’ve just ran into some difficulties and whilst diagnosing them it seemed that current controller doesn’t have a pawn reference - yet I am clearly able to move it around on the screen.

After more digging it would seem that I have more player controllers than I expected. I changed the player indexes from 0 and 1 to both be -1 so that it would auto-increment the numbers. Whilst outputting via a print node, I get a controller 3!

I am calling the creation of my players in my GameMode, my understanding is that this is created each time a level loads. So, on my menu, these are created unnecessarily. Then, when the player clicks “Play”, the main menu level is scrubbed, the GameMode is destroyed, the playable level loads, with a new GameMode and thus the players are created again.

Assuming my assumption above is correct - how am ending up with more player controllers than two?

Does the CreatePlayer node create persistent players in the game?

I’m getting really tangled up on this and its so frustrating, all I’m trying to do is have two players in a game which take it in turns to play when the other dies, but I can’t seem to get anywhere near that part due to all these other problems :frowning:

Thanks in advance for any help. (I did try UE4 docs, but, well, you know… sparse)

In my game, I had somewhat of a similar situation: I wanted one player to have a different Pawn Class than the rest. After going through a lot of pain, I discovered the proper way Unreal wants you to do this is to simply Override the function GetDefaultPawnClassForController in your own custom GameMode class. This function gives you a reference to the PlayerController that will posses the Pawn, so you can decide on what Pawn Class to give to that PlayerController.

In answer to the other part of your question, I found that the survival of Pawns and PlayerControllers across level transitions seemed to depend on some factors. If you are using seamless travel and the new level has the same GameMode as the previous level, then yes, it seems all PlayerControllers survive the level transition. Things are different when you use Non-seamless travel, and the GameMode in the new level has a different default PlayerController class. The technique of overriding GetDefaultPawnClassForController shown above seems to cleanly handle all cases, though.

Hi,

Thanks so much for such a prompt response! I will check out the GetDefaultPawnClassForController function…

All I’m trying to do is have a blue space ship for one player and red for another - I cannot believe how much of my time this has consumed - the more I use Blueprint, the more I dislike it (so far).

One other area I seem to be having problems with is the player index / controller ids…

Despite having set it to zero for player one, when I move to the playable level from the main menu, I try to call a function on my controller and it suddenly has no knowledge of the references I’ve set. Yet, if I change it from zero to 1, it works fine?! It’s like they’ve got reversed…

Not entirely sure what you mean by “seamless travel” for the levels etc… I just called “Open Level” and (horribly) pass in the string reference of the level to load.

If the player controllers are going to survive through the level load, how can I avoid them trying to be recreated? e.g. my “Create Players” function is called in my GameMode, so, as that gets created again on the next level, it tries to create all the players again and then moans that players with that ID already exist (sometimes).

All I’ve managed to do so far is add a sequence node and have the very first item remove players for controllers 0 and 1. It feels really messy, overly cluttered and just, well, wrong.

Digging more into that player index issue…

Here’s something a bit weird that perhaps you could shed some light on for me?

If I use GetPlayerController, leave the index as zero, then cast the returned controller to my base class, SI_PlayerController, when I then call DisablePawn from it (my own function), I get an error that states there reference is “None”.

If however I use Switch On Integer node, and from the zero pin connect my existing PlayerOneReference variable (of type SI_PlayerController), then drag from that to the DisablePawn function - it works fine.

If I also run a Print node from this and use GetControllerID, passing in the PlayerOneReference variable, I get zero as the output.

I am somewhat confused by this.

Just want to make sure of something: Is your game 2 players on the same computer (like Local Split Screen with two xbox gamepads plugged into 1 computer) or does Player 2 connect across the network (Internet/LAN) from another computer?

Assuming this is a network game just a few notes:

  • Once players are connected you should use the console command “ServerTravel MyLevel?listen” instead of “open MyLevel”. If the server uses the “open” command, it will disconnect all the other players. ServerTravel should only be called on the Server (use “Has Authority” to check).
  • When you create your custom GameMode subclass under Class Defaults, there is a checkbox for Use Seamless Travel. This is supposed to keep your remote clients connected when you switch maps using ServerTravel.
  • You should normally never have to write any code to spawn Pawns, PlayerControllers, or call Possess/Unpossess. This is all done automatically for you by the Unreal GameMode class

In regards to your goal of having each player have their own colour: I did something similar in my multiplayer game. Rather than try to fight Unreal’s ID system, I added an integer to my PlayerController called “myID” and gave it the value of -1. Then, on the EventGraph you can override the OnPossess function of the PlayerController (I believe OnPossess is only ever called on the Server). At this point, I had the PlayerController check if "myID=-1). If so, it checks if it’s the server using the “Has Authority” Node and sets “MyID=0” (if it is the Server). If it is a remote PlayerController, it instead sets “MyID=1” or the next lowest number that isn’t already taken by another player. Then, the PlayerController sets a RepNotify variable called “MyColor” on my Pawn. In the Pawn class, the RepNotify for “MyColor” changes the Pawn Material to match the new colour.

There is a great official video tutorial series on Replication here:

Hi,

Thanks for the detailed reply.

It’s actually two players on the same device, in this case a PC. I am trying to create a pass-and-play style game. The game can be just one player (thats working fine), or two players, if the latter, then they will be taking it in turns after each player dies etc.