13. Making the multiplayer part 1
Hi, it’s Jammu from the frontier. I’m behind the more complex multiplayer side on the Cave Digger 2 – Dig Harder. In the first part of this series I will open up a small portion of my current development implementing the Steam friend invite system. This blogpost will be more on the technical/tutorial side and the topic is pretty intermediate, so don’t worry if you miss some of the things.
This will hopefully provide some insight on how to tackle these problems, since (by my googling) I didn’t come across any proper tutorials/examples of this topic. This isn’t a fully fledged tutorial with proper examples, but if you would like to see that or need help in this topic, send me a message on our Discord server https://discord.gg/WY8mgJza.
Firstly let’s start up with our networking SDK of choice. I did a couple of days worth of research on different approaches with different SDK’s. Already from the start we knew that we wanted smooth crossplay between Oculus/Steam players and that we have limited development time to use on the multiplayer part of the game, so we didn’t want anything too complex (even though they usually make the experience smoother and decrease the ping).
On my final comparison list I had 5 different networking SDK’s to choose from. MLAPI, PUN, Mirror, Forge and Normcore. All of these options were good, some better than others. MLAPI, Forge and Normcore were dismissed, since they are not mature enough yet, don’t have a massive documentation or an already big community that has already solved most of the usual problems. Mirror was a good option, but some of the community members said that it has some performance issues. Also with Mirror we would need to use some 3rd party relay server which would increase the development time. So we decided to use Photon Pun 2, documentation is pretty good, it’s easy to set up, price isn’t bad and most of the problems I have encountered have already been solved on the forums.
Next on to the Steam. If you are currently about to start this kind of Steam/Oculus multiplayer development and came across this by googling, I advise you to grab (at least) 2 computers, stock up your coffee/energy drink reservoirs and make sure that you have at least a couple of weeks to spend. I will be using Unity 2019.4 LTS, Facepunch 2.3.2 and PUN 2.22 and Steam test appID 480, which shows up as “Spacewar”.
First solution was ok-ish, use Facepunch’s SteamFriends.GetFriends() to get data from steam, show friends names and avatar on a generated list. Asking them to join the game was done with friend.InviteToGame() with the host’s user ID as a room code, since I didn’t have to worry about cross platform at this point. When a player joins the game, we send an RPC event to everyone else that new person has joined the game and send the joined player’s info along with the RPC. Then we just need to delete the joined player from the friend list and add him/her to the “party” list and spawn the user’s avatar. This wasn’t super hard to do, but had major UX flaws.
Since friend.InviteToGame() uses a basic Steam chat based invite system, we don’t have any proper way to show any ingame UI when an invite request has been getted. Player that is asked to join the game would need to go (in VR mode) to Steam dashboard, find correct chat with that particular friend and connect from there, or they would need to take off their headset and accept the invite from the flat screen. Both of these options are bad for user experience in VR, on flat screen games this would probably be enough.
Friend invite gotten from InviteToGame() function.
2 players connected to same room with awesome developer UI. Right side is player’s steam friends and on the left side current “party”.
I fixed this UX problem by sending custom chat messages along with the normal invite system. We can send a chat message to players that we want to ask to join the game by using the friend.SendMessage() function. This way we can send an custom Steam message to the player we want to invite to the game and grab the room code on the receiving end simply by checking every chat message the user gets with the SteamFriends.OnChatMessage event. When we receive a chat message in the correct format, we can trigger a dialog box to the player if he/she wants to join the game. I still left the normal InviteToGame() function in the game, in case a user is not currently playing the game.
Sent room code via chat message system.
Received a message and displaying the room invite.
I also added a functionality to allow host to kick the players.This was pretty simple since we only use the Steamworks API with Facepunch wrapper to get user’s data and send messages, I could utilize the normal Pun’s PhotonNetwork.CloseConnection() function to close the connection for that player.
On my next blog post I will discuss how to make the Oculus side of this same functionality.
Thanks for reading if you survived this far!
Random development quote: “Huoneet on tuolla <osoittaa>. Ja lootit on täällä <osoittaa>.”