Greetings !
A few friends from college and I are currently working on a game that involves matchmaking, meaning you enter the game, then you connect to some kind of “Master server” who takes care of pairing you with another player and starting a match of the game you against him. At least that is what we are going for, a very simple version without any kind of player rating or anything. And I am the one that has to work on that. I decided I’d go with the low level API, for learning reasons (I dislike using High level stuff) and also for practical reasons : our game will not use GameObjects or even Transforms for most of the entities in the game which means most of the HLAPI is useless anyway.
I need help and advice on the approach I took which, I guess, is a common approach : I have a Master-Server monobehaviour holding a list of “ClientInfo” objects (ID of the Connection, name of the client, and weither than client is currently in a match or not).
The Master Server “gains” new Client Info upon a client connecting to it and loses client info upon the said client disconnecting.
On every frame it tries to pair off clients that are not currently in a match. For optimisation purpose it only looks at clients that just joined the server, it doesn’t update the list every frame with all the client infos that claim they are not in a match.
Upon successfully finding two clients to pair off, it creates an instance of the “Match” class, which is where all in-game stuff happens (entity management, communication with the client on gameplay…) and gives it the client info objects corresponding to each player, that way it knows about the name of each player and what connection ID to use for message transportation.
Matches are updated by the Master Server on its Update() call and are passed the delta-time. Matches also have their own “Speed” attribute that multiplies the deltaTime passed to them, but that’s purely gameplay stuff (figured I could use it for end-game slow-motion or whatever).
When a match ends, the clients are sent a message telling them the match’s outcome, and a few seconds after receiving it, they disconnect from the Master-Server and go back to the main menu.
For message transportation, I have 3 classes : NetworkMessage, NetworkMessageSender and NetworkListener. NetworkMessage is a simple data structure that contains a message name (string), message content (object), and the ConnectionID from which it was sent (useful to determine who / what a reaction to a message should affect, for example, if the Match receives a “Player wants to move forward” message, it can check if it is meant for him by checking the source Connection ID and the Connection IDs of each player participating in the match.
NetworkListener is a static class where all message receiving is handled for servers and clients alike : when a message is received it is put inside a list of “ReceivedMessages”. Then anyone can use the “NetworkListener.CheckMessage(“MessageName”, out NetworkMessage something)”. It works just like the Raycast : if a message of said name is inside the “ReceivedMessages” list, then the method returns true and puts the message in the something variable, then it removes itself from the ReceivedMessages list.
This is where my doubts are the greatest : If a message gets “Checked”, it gets removed from the list, meaning whoever reads a message first and tries to make sense of it will be the only one that ever gets to read it, which might prove problematic. I’ve also thought about cleaning the entire list of messages on each frame but then isn’t this going to cause problems too ? I’m not sure frankly.
As for NetworkMessageSender, it is a class used to “wrap” messages into something that is then sent into the message’s connection ID. So basically in order to send a message to Connection ID X :
- You create a NetworkMessage object, give it a name and a content, as well as X for Connection ID
- You create a NetworkMessageSender object, give it your HostID and ChannelID, aswell as the NetworkMessage
- On construction the NetworkMessageSender sends itself through the network on Connection ID X.
Not sure it is the best system, but so far it works, kinda ![]()
I think that’s it. I know there are no specific questions but if you guys are interested in helping me make a better system using the LLAPI then I’d appreciate some criticism ![]()
Thanks !