April 2024 - September 2024
This is a Battle Royale game, I have developed from scratch with over 40,000 lines of code written in C++. I have implemented typical Battle Royale mechanics which includes joining lobby, dropping from aircraft, picking up loot, moving towards the safe zone, and surviving to be the last squad and winning the game. This project helped me get very thorough with Unreal Engine's Replication System. Optimization was given top priority, I have ensured to send minimum data across the network to reduce latency, ensuring a smooth gameplay without compromising on quality. I have also implemented Lag Compensation techniques such as Server Side Rewind and Client Side Prediction. It's a full game prototype with complete game loop.
Replicated Weapon Mechanics
Inventory System
Armour
Hitbox based Weighted Damage
Grenade, Smoke Grenade
Vaulting
Solo, Duo, Trio, Squad
Knock Player
Revive Player
Eliminate Enemy and Team
Win/Lose Match
Death Box
Server Side Rewind
Client Side Prediction
Blue Zone, Safe Zone
Randomly generated Zone and Flight Path
Zone Damage and Effects
Weighted Random based Loot Generation
Jump from Aircraft
Skydive, Falling
Parachute, Glide
MiniMap and FullMap Widgets
Steam SDK
Create, Join, Configure Sessions
I enjoy building large, complex projects because they offer more challenges, not only in programming mechanics but also in maintaining a large codebase.
I always prioritize careful planning before implementation, ensuring that adding new features in the future will be hassle-free. By taking the time to plan
properly and implement mechanics with thorough testing, I was able to deliver a final prototype with minimal issues and no game-breaking bugs.
Decoupling features into components was crucial for enabling rapid feature additions and making maintenance
and testing more efficient.
This project also made me realize the importance of testing. Spending time to create tools or mechanics for testing proved highly productive and saved a lot of time.
I developed a strong interest in testing as it requires innovative solutions to test unique mechanics quickly.
Optimization was a top priority throughout the project. I designed every system to be as efficient as possible, consuming minimal CPU cycles. I also focused on
memory optimization, using appropriate data structures and clearing objects from memory when no longer needed. I carefully selected data types to minimize the
amount of data sent over the network, and I found solutions to avoid transmitting unnecessary data.
Random loot generation is a crucial part in Battle Royale games. After looking through various approaches, I found Weight Random choosing to be suitable since it gave more control by taking individual weights and total weight into account.
Assigning weights was made easy by the use of DataTables, so weights can be updated easily by modifying the DataTable, experimenting the Loot Generation is made easy this way. Following are the weights that I use currently.
[Fig 1] Item Weights DataTables
LootSpawnActor is placed all around the map, when the game begins, the server gets all these LootSpawnActors placed in the world. Then based on choosing probability set in
the blueprint, it either uses that LootSpawnActor for spawning loot otherwise it just destroys the LootSpawnActor. After that, it determines the number of loot items that
need to be spawned in each of the chosen LootSpawnActors randomly ,and it can range upto 1 to 5 items.
Next is determining the items to spawn.
First, ItemType such as Ammo, Throwable, Armour, Weapon have weights, which is used to determine what kind of loot to spawn.
Once that has been chosen, the next would be to choose the item of the previously chosen type, for which again weights can be found in the DataTable. By doing this,
I have balanced the spawn rate of the item based on the necessity of the item in the game.
After choosing the items to spawn, logic is executed to spawn the chosen items. The LootSpawnActor is a plane, which is divided equally into 4 parts. Each chosen item
is randomly spawned in any of the divided part, and placed at random rotation. The reason I have chosen this method is to save the server's CPU time. Since there are 1000s of
LootSpawnActors in the world, doing complex calculations and trace testing will be costly. By profiling the LootGeneration and spawning
I found this method to be best, generating loot and spawning them in few hundred milliseconds.
There is also additional logic, that ensures that when a weapon is spawned, the ammo for the weapons is also spawned along with it.
[Fig 2] Random Loot Generation
Varying the flight path and the zone randomly every game which creates variability in the game. So every match doesn't feel the same. I came up with some solutions to do this effectively and they are highly customizable.
The flight need to spawn and move from any side of the map to another side which is on the opposite. To achieve this with maximum variability I have used a spline. Here is how the component responsible for generating the flight path works,
[Fig 3] Spline looped around the map
The zone can be completely configured using a DataTable. It is possible to change things like Init delay (generally only set for the first zone), Blue Zone shrink start time, Blue Zone shrink time, Safe Zone diameter, Blue Zone Damage per second.
For determining the zone location, we again use the spline. Since the spline is a closed loop around the map, it can be used as bounds and points can be generated inside the bounds. The way it is generated is as follows,
[Fig 4] Zone Generation
The problem with multiplayer games is that, due to network latency, the time of shooting a bullet and the time this reaches the server for authentication and processing will be different. In low latency scenario, this might not mean much. But even with moderate latency, this can cause some discrepancies such as player getting hit and dying after reaching a cover. To fix this, Server Side Rewind can be used, where the server records data regarding hit boxes of the player in some regular intervals or every frame. So when a player fires a weapon, time of firing the weapon can also be sent along, which can be used to look through the history of the recorded hit box data and test if the shot is a hit or not. Though this can be a good way of ensuring accurate hit based on time, but for very high latency it may not look as intended in the gameplay, so it's best to turn off Server Side Rewind for very high latency.
Below is how I have implemented Server Side Rewind in my project.
In the below image, a projectile weapon is fired. We can see the green sphere which is a projectile trace, tested against a record that was found based on the time sent from the client. The chosen record is debugged and player is hidden for understanding.
[Fig 5] Record at time of hit Debugged