Hello distinguished users of the devforum! I am here to give you all what I call my “Hitchhiker’s Guide to Optimization” (those who know the reference, good on you for knowing it). This contains all of my research and knowledge that I have built up over the years on optimizing my games to 99.9% perfection!
NOTICES BEFORE BEGINNING
- This is mostly meant for newer users to the DevForum. It is not meant to be for professional, full stack developers. However, you are free to make your own guide for full stack developers in the replies to ensure this guide helps all areas of the developer ladder.
- I am not the best programmer, but I did my best with writing down stuff for scripting optimization.
-
DO NOT USE ANTI-LAG SCRIPTS. PLEASE.
- Any time you are unsure of something, please look it up yourself. This post is not meant to be a directory to everything. I am not including many links because I want to avoid overwhelming the average devforum newbie.
- I am not going to be active that muchin the replies of this post. I will see your posts, and maybe heart a few of them, but I will only be responding to make clarifications where I feel it is needed. I feel that the less I help, the more the person will learn.
- These are all things I have had experience with. I have ran countless tests with my community to see what works, and what doesn’t. What you are seeing here is both research that I combined together throughout the years, tied in with results from my Community. Devices that were used to test this range from a Kindle Fire (I don’t know if they are still supported) to an iPad 2, all the way up to a computer running some of the best hardware out there.
GENERAL OPTIMIZATION
- Set all your meshparts to Performance or Automatic. Run these two bits of code SEPARATELY put forth by 440obama in your command bar. I have modified it to make it be to performance and for unions.
for _, object in pairs(game.Workspace:GetDescendants()) do
if object:IsA(“MeshPart”) then
object.RenderFidelity = “Performance”
end
end
for _, object in pairs(gPreformatted textame.Workspace:GetDescendants()) do
if object:IsA(“UnionOperation”) then
object.RenderFidelity = “Automatic”
end
end
-
Set StreamingEnabled to be on. For bigger games, I have attached my preferred settings below.
-
To fix any issues that arise from Streaming, make the part be a model and make the ModelStreamingMode be Persistent. It will fix the issue.
-
To fix audio, I use this plugin. It allows me to find the ID and the sound info, and I then line it up with a screenshot I got from my game to find out what audio is bugging out. https://create.roblox.com/store/asset/9173750549/Bulk-Audio-Manager-10
-
To fix part count issues, use this plugin. Here is the key for it:
https://create.roblox.com/store/asset/208249680/Part-Counter- Voxels are Terrain. Keep this below 100 million for an ideal gameplay environment for all devices.
- Instances are everything in your game not terrain-related. This number doesn’t matter too much.
- Parts are all of the parts and meshparts. The best spot for this count to be at is around 75k, because it’s still able to be managed by mobile devices of all sorts.
-
HOLLOW OUT YOUR TERRAIN. This is very, VERY important for ensuring your game will not lag. Use Subtract to make the process faster, be sure you do not create any holes in the terrain the player is meant to see.
- From my experience, flat surfaces mean more voxels, meaning more memory taxed on the player, and a decrease in FPS. I ran a test with my development team, and the results sent back showcased an increase of 15 to sometimes 48 FPS. More voxels = more GB of RAM used/more memory used!
- Try to avoid the underside of the terrain making complicated shapes. This can cause some issues with performance.
-
Try to avoid using regular water in bulk. it is REALLY LAGGY.. If you are making an ocean-related game, use infinite water. If you know what you are doing, then you can make it be swimmable.
-
Convert your Unions into Meshparts. ROBLOX does not optimize Unions the same way they optimize Meshparts, so the best way to fix that is doing Export Selection to convert it into a meshpart. YOU WILL NEED TO RESIZE AND RE-POSITION IT THOUGH!
-
For all noncollidable meshparts, set the CollisionFidelity to “Box”. This saves ROBLOX the issue of rendering that stuff. Please do not use this if that part is being used for CanTouch-related things.
Thank you sandofamber for contributing this script to the effort (Run it in the command bar):
for i, v in next, game:GetDescendants() do
if v and (v:IsA(‘MeshPart’) or v:IsA(‘UnionOperation’)) and not v.CanCollide then
v.CollisionFidelity = Enum.CollisionFidelity.Box
end
end
- For all meshparts, try your best to avoid using DoubleSided. It is not optimized. Same goes for PreciseConvexDecomposition.
- Try to keep CanTouch and CanQuery off. These can cause a lot of lag once they build up. You will only see CanQuery if CanCollide is turned off. Turn them on if you are actually needing to use them though.
- This is optional, but convert all of your audio to ogg files. This will help a ton for mobile players. ROBLOX does NOT do this automatically.
- Another way to help mobile players is to not use Textures. Rather, use custom materials or SurfaceAppearances. I have never found textures to be a good thing for mobile devices.
- ROBLOX has to check each side of the part for a texture if a texture is on it, from what I have seen. Using the knowledge I gained from testing, SurfaceAppearances and Custom Materials are the best way to go because ROBLOX doesn’t need to check for all 6 sides. of the part. Decals are also a bit weird like this, but they aren’t as laggy from experience. This will help you with optimizing your decals and textures, it was linked in another devforum post but I forgot where it is. https://imagecompressor.com/
- Added on from wastbo’s reply: Try to re-use meshes and be careful regarding changing things like transparency and color on them.
SCRIPTING OPTIMIZATION
- Set every wait you can to task.wait(). wait() was deprecated by ROBLOX in favor of task.wait(), meaning it can lead to issues in the future, and can be unoptimized for ROBLOX’s newest code changes.
- Try to keep as few heartbeats going as possible.
- Set all RaycastFilterTypes to Include and Exclude, to keep up with ROBLOX’s changes.
- Try to store stuff in ServerStorage instead of ReplicatedStorage. This helps with the player being able to handle the game better from the clientside, which is arguably more important in order to keep performance going well.
- From AGoodGuyHere: “Dont use FindFirstChild if you know it will always be there”
- DO NOT USE ANTI-LAG SCRIPTS. THEY DO THE EXACT OPPOSITE OF WHAT THEY SAY THEY DO.
- !IN BETA AT THE TIME OF WRITING THIS! Use buffering in some scripts to help alleviate issues. Read more about it, here.
- Use Native Lua to help streamline the code for your game. Do not use it everywhere though! Read into it more, here.
Hope this helps everyone here. Feel free to add on anything you think would help.
All of this guide has helped me, and it has helped others. I am not expecting it to satisfy everyone, but this is the best I can do. And, before making your reply, I encourage you to do tests and research yourself, as this will help a lot with learning what works for everyone and what doesn’t.
For more context, you can read the replies below. I specifically recommend the posts by Abcreator and TimeFrenzied, along with the note I added onto Abcreator’s reply.