Ice and Water is a real time multiplayer game where each player is dropped into the arena filled with various types of balls and powers and the goal is to get max score on each round. This game is my showcase for my first real time multiplayer game developed in Unity Game Engine. With the game rules being quite different from a standard Multiplayer FPS, there were several challenges with game mechanics and data sync through all clients.
This game is heavily inspired from one of my favorite childhood game “Freeze Tag”. The Ice players gets 2 point when they “freeze” a player and other WaterPlayers can score 1 point by “unfreezing” the player. However, since the old game on used agility as the primary mechanism for success, I changed the rules significantly to make this games primary skillset to be agility as well as aiming. For achieving this effect, I added Iceballs and Waterballs in the arena which has to be picked up and thrown at players successfully to get the effects going.
There is also an interesting story about the targeting system and various different types of targeting system tried out and eventually one was selected which suited best for maximizing fun and challenge for the pace of the game. Initially I loved the way grenade was thrown in Call of Duty mobile, which is aiming with a projectile which can change its height and range depending on the parameters you input ( through joystick). This however, is not so much fun for a fast paced multiplayer game where you first have to get a ball, find a vantage point, take the perfect shot and if you are slow the other player can escape quite easily. Then I tinkered around with automatic aiming, just push the button and ball will fly straight to your opponent. This however, made the IcePlayer too over powered. So, just like all of the solutions in life,I came to a compromise. The aiming would be automatic but the aim will change depending on who is closest ( distance and angle) to the IcePlayer. This opened up a new type of skill mechanic where you can entice the IcePlayer to be closer to one of the other WaterPlayers, get them frozen and then unfreeze them to gain a point. It also made it slight strategic for the IcePlayer on who to target first. As the most skilled player would be the most danger for unfreezing everyone off. In the end I was quite satisfied with the aiming though there is always scope for improvement and I would love to take suggestions.
Ball throwing mechanic had a lot of implementation challenges specially in a multiplayer server setting where every state, property and position and speed of objects have to synchronized with only limited data bandwidth. Before I explain the details of what problems I had to face, I will go over what is a standard way of coding a multiplayer FPS. All the other players in the game are actors, and each device which has the player Photon can record time of events when they happened, so when a player shoots another player, through their UI ( gun scope), they send an event to Photon telling them who they shot and at what spot. Another script which is available in each client receives that event and checks who was shot and kills that actor in the scene accordingly. This works because at time t, we can say that this player died and all the other clients can synchronize that info. This became quite difficult to solve when I had balls traveling for certain time after being shot and the other player has a chance to move and escape incoming ball. So syncing all of that meant syncing ball throw time, the dynamic velocity (3D) throughout its travel range, after ball hit the player or not hit the player.
Due to limited bandwidth, syncing all of this data would mean a slower performance of the entire system and in order to address that I had to go back to my friendly state machines. I creates states of the ball (onGround, InHand, InAir, Destroy) and would sync my state with the clients. Only one time velocity is sent on Photon event packets and rest is taken care by the in engine physics. For a good safe measure, after the ball is destroyed, it goes back to initial state and thus syncing all clients for seamless experience. This whole system works smoothly and reduces the load on photon server bandwidth by 66%. I am planning to make a video on this soon so check out the website soon or register for news and info when this drops.
The registration, server connection and data maintenance has been created by using Photon and Playfab libraries. Once you start the game, there are options to either play as guest or to register with email ID and Password (easier to login again). I also synchronized all the data after login for unlocked skin, scores etc. There are multiple ways to start a game and since this game is only possible with at least 3 players, a delayed matchmaking script was created to ensure at least 3 players are present before the game can start (when joining random rooms). But lets be realistic here, the biggest problem most of the multiplayer games have is no players to play with. Well for now, the only plausible and fair solution I implemented was to give an option to create custom rooms where you can even play as 1 player. Get a hang of the game practice some throws, and then you can invite friends to play the game with you. I will almost always be available to play a game or 2. You can reach me out on discord anytime. In the future, I have plans to add AI opponents which can be a good way for practicing as well enjoying the game if not many people are available.