Those of you who follow my Twitter may know that I’ve been on a personal quest to create the most optimized game on Roblox.
First, I got my game to run at 600 FPS. That was a great start, but it made me hungry for more.
After quite a bit more work, I got it to break into the quadruple digits at just over 1000 FPS.
Recently I had another breakthrough and got it running at over 2400 FPS!
Then, simply by making my game’s window not fullscreen in order to lower the render resolution, I got it to run at over 3500 FPS!!
I made the place public and added a global leaderboard so people can try it out- and some people have run it at over 6000 FPS!
You can try it out here:
I know you’re all wondering how on earth I accomplished this. Good question! Here’s my internal documentation of the process:
Removing 3D and Physics Work
This project is UI only. There is no physics, no 3D world, no characters to run around. That means it should run fast as hell. However, the Roblox engine has no concept of UI only games- so we have to do our best to minimize the impact of the pointless 3D work that is done in the background.
-
Hello darkness my old friend:
We set our lighting to the simplest possible- voxel tech, no shadows, all black color values, and brightness 0. This reduces some lighting work.
We add a Sky, with no celestial bodies or stars and all the textures set to a single pixel. This saves us from sending the big sky and moon textures to several drawcalls.
Adding a BloomEffect with Size 0, Intensity 0, and Threshold inf actually lets the engine skip the entire Glow step on the GPU. -
Floating Point:
We set gravity to 0, making it so that there are absolutely no forces in play for the physics engine. -
Empty inside:
We do not spawn in characters for the players, and the world has no geometry. There is nothing but our minimal sky. -
Narrow minded:
We set our 3D camera FoV to 1, the lowest it supports. This way, we’d render only a tiny sliver of the aforementioned sky. -
Blindfolded:
We set our camera CFrame matrix to all zeros, causing the camera to render pure black as it is distorted down to nothingness. -
No thank you:
Roblox injects default scripts, such as camera controls, character controls, chat, and more. We override these by replacing them with empty directories or (in cases where we can’t override) by destroying them on startup.
Although some of these may seem insignificantly small, our frame times are merely a couple hundred microseconds at thousands of FPS and therefore they really do matter.
Benchmarking
How much of an improvement do we see from these 3D/Physics changes? Let’s find out.
Running on a Zephrus G14 Laptop (Ryzen 9 5900HS, RTX 3060 Laptop, 16GB 3200MHz RAM) using RenderDoc for capture
Baseplate: 1357.24 μs GPU time
On max graphics
Baseplate: 382.59 μs GPU time
On lowest graphics
Optimized: 751.61 μs GPU time
On max graphics
Optimized: 87.04 μs GPU time
On lowest graphics
Result:
Max graphics:
GPU Time: 44.62% decrease
Lowest graphics:
GPU Time: 77.24% decrease
These are reasonable and predictable results, and extremely pleasing.
You may try the benchmark place yourself, as I’ve turned it into a friendly competition:
Result
Well, how does this all run in my actual game? Like a champ, that’s how!
1200+ FPS even while UI is being animated, 1800 FPS peak at idle.