Summary
MMOs are fun to work on, but also to play. I am a big fan of MMORTS games and RTS games in general. This game is a lite version of today's MMORTS we see. I mostly worked on the networking, server, and database side of this game as it is the challenging part for an MMO. And I love handling such tasks.
Specifications
- Developed in Unity
- A MMORTS game inspired by Evony
- Uses Mirror for networking,
- Hosted on Gamelift,
- Uses Lambda for database interactions,
- Uses dynamoDB for storing player data,
- Uses Cognito for user authentication
- Clickups for project management
Project goals
- Build a robust websocket server/map that can accomodate atleast 80k players,
- Implement player & alliance data management system
Gameplay
The game may seem huge but concept around which everything revolves is simple:
You'll be provided with a base on a vast map.
Gather resource => train/upgrade your troops/base using that resource.
Use that troop to attack other players on the map to gather even more resource.
And yeah the game does involve having aliances, npc's, server chat and other map based events.
Technical Overview
Map Synchronization
This is not a typical MMO, instead it's a lite version where the is no physics simulation/movement in the map. When player A dispatches troops to attack player B after scouting, the server code does the battle computation and sends back the result. Also makes an API call to the Lambda function to update the new player/map state into DynamoDB. Even if the EC2 instance die, automatically a new one will be booted which continues the simulation based on the last stored map state from dynamoDB. Everything else like farming on a public mine and attacking a NPC goes through same.
Battle Logic
The battle involve some math that does the job for us all the while keeping the battle result resonable and accurate.
Damage Factor = ((((Number of Troops * Total Attack Points)/Enemy Total Defence Points)/Enemy Total Health Points)*Damage multiplier)*(Number of Troops/Number of Troops)
The battle happens in turns. Each time the Damage factor decreases based on the previous lost troops. The damage factor can also be termed as troops killed.
Turn 1:
Player A makes attack, and Player B does its counter.
Player B makes attack, and Player A does its counter.
Turn 2:
Player A makes attack, and Player B does its counter.
Player B makes attack, and Player A does its counter.
Goes on....till either of those two player dies.
Yep as you guessed, what if both players are too powerful as they have millions of troops...will the battle will take some time to get computed?
That's the reason I have added Damage Multiplier to the above equation, by increasing and decreasing that value the computation time can be reduced. And the match will be over within 45 turns.
Player Management
I have great experience with Playfab player management service. But we wanted something more flexible but contains most of the things that Playfab offers. So I implemented the same architecture here. Using cognito I authenticated player(guest, email, facebook). Once authenticated the player's cognito id will be used as the unique identifier while creating a new player in dynamoDB.
No other services have access to write on DynamoDB and only can be done through Lambda functions, which first validate the requests before making changes.
One of the interesting things I learned here is that Microsoft-owned Playfab is using AWS services as its backend, not Azure.
Closing thoughts
For me it's a great start to understand how MMO server architecture works, if this were to involve simulations in the map then it would have gotten complex to handle. Also, players love swarming during major battles between alliance, which requires both robust net code with less latency. Something like unity DOTS to reduce the load on both server and client.