Hello there, I’m BullfrogBait and this is my first community tutorial that focuses on MeshPart usage, performance and optimizations as well as mini-tutorials along the way like how to import and export objects and what all the different RenderFidelities/CollisionFidelities mean.
MeshPart optimization is becoming a very important skill as MeshParts are being used more and more frequently as Roblox slowly climbs out of the stone age, with this tutorial you can really cut down on unnecessary collisions and triangles to help reduce lag for all devices. We’ll get more into that in a bit however.
First and foremost, you need to make sure that you’re using MeshParts when they’re actually supposed to be used.
You should only be importing MeshParts when the object itself can’t be created efficiently in Studio with the basic building blocks Roblox provides. When I say efficiently, I mean as low amount of triangles as possible.
Triangle Count, What Is It?
High-poly, high-tris, high triangle count, all relatively mean the same thing in Roblox. When you look at a basic part, your computer is calculating the triangles needed to make up the shape on your screen. When your device is unable to calculate tons of triangles, it starts to slow down in terms of frames per second, making your game look all choppy and laggy.
The leftmost image is an object I made using Roblox’s primitives, also known as the basic building blocks Roblox allows all developers to use. The object is made up of one basic part and two WedgeParts.
Using Wireframe Rendering, which you can see how to toggle in Studio by following the GIF shown above, you can see that the middle image with the red highlighted triangles has triangles that are being calculated that won’t ever be visible.
On the rightmost image of our object, with the triangles highlighted in green, you can see it’s the same shape but it has less triangles. This is because when it was created in Blender, it wouldn’t create excess triangles.
A good rule of thumb is that the less triangles the better. Even if you have a really strong device, you’ll be helping anyone with a low end device play your game with a high framerate.
What Is Framerate/FPS?
Framerate/FPS/Frames per second all generally mean the same thing. It means how fast your computer can calculate the stuff that’s on your devices screen. As a developer your goal should be to always have your game as close to 60 FPS as possible.
The leftmost GIF is low FPS while the one on the right is high FPS. Your game can look like the left GIF to some players with bad devices if you don’t take optimizations like reducing triangles and following the rest of this topics advice.
How you’ll go about increasing framerate and reducing lag will come up shortly, as for now we have to go over UnionOperations and why they should rarely ever be used.
Avoiding UnionOperations And Why
When new developers are trying to create similar objects quickly or hoping to reduce framerate lag they might choose to use the Union tool in Studio instead of trying to learn the basics of a 3D modelling program like Blender. This can be disastrous for performance.
UnionOperations for 99% of cases are unnecessary, laggy and overall a pain to work with. You’ll find yourself creating lag, excess triangles and weird resizing problems when using UnionOperations.
On the left is a very simple object I created with two Part instances and then I used the Union tool in Studio to union them together. On the right you’ll see the amount of triangles it’s creating. In all honestly, I don’t even know how some of those triangles are being rendered.
A simple object like this can be created in Blender and it’ll have even less triangles than it being made up of parts in Roblox Studio, let alone a lot less tris than when you union them together using Studio.
Another problem with UnionOperations is their missing Performance RenderFidelity option. This is intentional on Roblox’s side and we’ll probably never see the Performance option when using UnionOperations.
We’ll get more into it later as to why these options are important to have and what they mean in terms of game performance.
In the GIF above, the red object is the UnionOperation and the grey object is what the collision decomposition looks like. In other words, it’s the barrier that makes up collision. When flipping between these two, you’ll notice that the collision is weird and creates wedges that shouldn’t be there.
We haven’t gone over CollisionFidelity yet, but when we do, the CollisionFidelity of this UnionOperation is Default. To explain it briefly, if this same object was created in Blender and had its CollisionFidelity set to Default, it wouldn’t create those unnecessary wedges you see in the grey object image.
The reason it’s creating weird collision boundaries is because of how the triangles are layed out, or in other words the topology, in/of the UnionOperation. Since unioning parts creates bad topology, it’ll also have a domino effect and create bad collisions.
UnionOperations also have a downside when it comes to instancing. When you have a handful of UnionOperations and you update one of their properties, like material or color, with a script that’s running in your game, it’ll prevent part instancing and retrigger the calculation of the entire object. This can be really bad on performance and it’s one of the reasons why so many people opt to using MeshParts over UnionOperations.
There is one decent use case when you’re using UnionOperations over MeshParts. Reminder that this is practically never the case and should only even be considered if the rest of this tutorial doesn’t help your game.
You can choose to use UnionOperations when you’re making a one of a kind, low detail object that’ll never be updated. To be more specific, this object should never be touched by scripts and should only be in the game as a detail.
For example, if your game has somewhat high loading times even after reading this tutorial and optimizing it, you can use a couple UnionOperations over MeshParts when you’re never going to use that object again. By never using it again I mean you won’t be copying and pasting the UnionOperation to use it multiple times in your game. If you need to copy and paste a UnionOperation a few times, consider converting it to a MeshPart. You can easily do this by selecting the UnionOperation, clicking Export Selection and then import it as a filetype
Also, you can read more about Part Instancing here, it explains what it is and the technical specifics of what works with it and what doesn’t. For now however, we’re going to get into recycling MeshIds and how it can help performance and loading times when joining your game.
When creating tons of MeshParts for your game, you might run into the issue of longer loading times. When a player joins your game, they have to download all the games assets to their device. This includes MeshPart MeshIds and TextureIDs.
Above is an image explaining what I mean when I say similar MeshIds versus unique MeshIds. Keep this in mind when reading the parts below.
Everyone has different internet speeds, so it’s really important to use as little unique IDs as possible. Every unique AssetId takes time to load in depending on its size. The more unique MeshIds the longer your loading times to join the game will be depending on your internet.
There are actually a lot of scenarios where you can reuse your MeshIds and give off the same effect as you would when using unique ones.
In the left image above is a low poly tree and on the right is the same tree except every unique MeshId has its own color. As you can see, the leaves are all similar MeshIds because I reused them. When the engine sees that there are three leaves with the same MeshId, it will calculate the geometry of one of them and reuse it for the others.
The engine will only download the MeshId once and reuse the same data for the rest of the objects with the same MeshId. You can essentially cut down on loading times and lag by recycling your MeshIds.
There are a few tricks when recycling to make them not appear the same. For example in the image above some of the leaf objects are smaller or lighter than the rest and they’re all randomly rotated. You can create different looking objects with the same MeshId like so to cut down on loading times while also having your game look good.
On the left is a forest scene I created and on the right is the same scene except I marked unique MeshIds by color. The engine will only see two MeshIds and load them and then reuse their geometry. Since I recycled my MeshIds and used the same MeshId for the leaves and the rocks and just altered their properties to make them appear different, this whole forest will take no time at all to load and render in.
While recycling MeshIds and choosing MeshParts over UnionOperations does benefit your game in terms of performance and loading speeds, we’ve barely scratched the surface on how to actually boost performance while using MeshParts. Let’s get into it.
Finally with UnionOperations and recycling MeshIds out of the way we can focus on good performance techniques and strategies when it comes to using MeshParts. Following these simple rules can really help a majority of Roblox’s playerbase with low end devices play your game smoothly.
Choosing The Right RenderFidelity
RenderFidelity is a MeshPart property that allows you to determine the importance of a MeshPart and how it’s rendered. By default, MeshParts will have the Precise RenderFidelity and this can be a performace drainer especially when you’re using tons of MeshParts.
In the image above you’ll see that the RenderFidelity has three different options. From top to bottom we have Automatic, Performance and Precise. We’ll get more into what these actually look like in a second, but to be brief here’s what they mean:
The Precise RenderFidelity option is where the MeshPart will always look the same and have the same number of triangles from any distance. If you import a MeshPart with 3,000 triangles, it’ll always have 3,000 triangles being rendered whenever you look at it even from far distances.
The Automatic RenderFidelity choice is just like Precise except the farther you get away from the MeshPart the more it’ll degrade and lose triangles.
This is a chart from the RenderFidelity API Document. Let’s imagine you’ve imported a 3,000 triangle MeshPart. When your camera is less than 250 studs away from the MeshPart, it’ll remain at 3,000 triangles. When your camera is 250-500 studs away from the MeshPart, it’ll cut the 3,000 triangles in half.
In the image above, you’ll see how the MeshParts will gradually degrade. This image above correlates to the RenderFidelity Chart seen above.
Finally, the Performance RenderFidelity option performs exactly like Automatic. It’ll remove triangles from MeshParts the farther you get away from it but it’ll also remove as many triangles as needed in order to preserve performance and to keep the players FPS or framerate high.
This means if a device is struggling to compute an object and it’s lowering the frames per second, it’ll send MeshParts to the needed resolution to make sure their FPS stays as high as possible.
With the definitions of these options out of the way, we can now discuss how to easily find out which RenderFidelity choice is right for your MeshPart. Below I’ll be listing random objects, their best choice for RenderFidelity and why.
Object: Clouds that are in the sky.
Best RenderFidelity Choice: Performance
Why: Because since the clouds probably aren’t a main focus of your game, the player doesn’t need to see them in high detail. If the player is lagging it’ll reduce the detail in the clouds to help raise performance and make the game playable and enjoyable.
Object: An enemy’s sword,
Best RenderFidelity Choice: Automatic
Why: Let’s say your game has a handful of different swords that do different things. If you were to set this to Performance, low end devices might not be able to tell what sword it is and what it does, giving them a disadvantage in your game, leading them to leaving and/or having a bad time in your game.
Object: A statue in the middle of a fountain.
Best RenderFidelity Choice: Performance
Why: Remember that Performance works like Automatic. Let’s pretend the statue is in the middle of a plaza, you’d want it to be visible in high detail to anyone near it that’s looking at it. With Performance, any player who is far away will have its triangles reduced. You can choose Automatic, but if it’s a high poly MeshPart, you can cause unnecessary lag when low end devices are looking at it.
Object: A gigantic main gameplay castle that’s visible at all times.
Best RenderFidelity Choice: Precise
Why: Any object that needs to be visible at all times, like a landmark (castle, gigantic tree, huge volcano), should have the Precise RenderFidelity chosen. If you have a giant castle in the distance but it’s just for decoration and not apart of the game, then set it to Performance.
With these examples stated, you should be able to get a grasp at how the default RenderFidelity, Precise, should almost never be used. Even in realistic games you atleast should be using Automatic for highpoly vegetation or objects.
Not only does the engine render what an object visually looks like, it also has to render the collisions to know where your character is allowed to stand or go through. This property that determines collision rendering is known as CollisionFidelity.
Selecting The Best CollisionFidelity
As I just stated, CollisionFidelity is a property for MeshParts that allows you to pick the collision that best suits the purpose of the MeshPart.
CollisionFidelity has four different choices. These are Box, Hull, Default and PreciseConvexDecomposition. We’ll get right into what their differences are and how they should be used.
The image above is a tree model made up of MeshParts copied and pasted four times with different CollisionFidelity choices selected.
The ones of the left are the least laggy while the ones on the right cause the most performance issues if used uncarefully. Let’s go over how each of their collisions are generated and why some of them are more performant costly than others.
Before that though, just a small note that I used Mesh Optimization Tools to view the collision boxes of the different types of CollisionFidelity. The plugin, which can be found here, is by CloneTrooper1019 and is 100% safe. It isn’t mandatory to have, but can help you find collisions that are being rendered that shouldn’t be.
The tree in the GIF above has the Box CollisionFidelity option chosen. If you go back to the image above this GIF you will see that it’s the least laggy of the options. The reason it’s performant is because it creates one basic box as a collision and doesn’t do anything further than that.
You might be wondering, well how big is the collision box when using this option? The size of the collision box is the side of the blue lines when you select your MeshPart. These lines are known as the bounding box lines.
Next up we have the Hull CollisionFidelity option. This is the second best option in terms of performance when you’re trying to reduce framerate lag in your game.
This CollisionFidelity option creates a convex shape by taking the MeshParts visuals into account. It really isn’t documented but by doing some testing it seems that it takes a few positions of the MeshParts visual render and then fills it in with collision boundaries.
Almost finished but first we have the Default CollisionFidelity option next. The Default option tries its best to create collisions based on its visual appearance. Default is somewhat like PreciseConvexDecomposition except it has a harder time generating collision for holes in MeshParts.
Last but not least we have PreciseConvexDecomposition. This CollisionFidelity is definitely the most resource using and performance destroying option.
This should rarely ever be used. It’s like Default except it creates a better collision boundary based on the MeshParts visual appearance and also creates better collision for holes in MeshParts.
Now that we have all the CollisionFidelity types covered, we can go over some examples on which ones are the best options for your game.
I’d like to stress though that just because of the amount of triangles in your MeshPart, these examples won’t 100% help you make the decision. The best way to pick the least laggy and most efficient option is to test all four of them out in game starting with the least laggy then working your way up if it doesn’t work.
Object: A bush that players can walk through.
Best CollisionFidelity Choice: Box
Why: Any object that you can walk through, you’re gonna want to set it to Box Collision. If you have it set to other CollisionFidelity options, it can cause unnecessary lag. You’ll also want to disable the CanCollide and CanTouch properties, but we’ll get more into that later.
Object: A tree with branches that reach far out.
Best CollisionFidelity Choice: Hull or Default
Why: Since Hull creates a convex shape, it can create an efficient collision boundary that’ll get the job done. However sometimes it isn’t good enough and that’s when you’d want to switch to Default.
Object: Triangle terrain that you created in Blender.
Best CollisionFidelity Choice: Default or PreciseConvexDecomposition
Why: With rare usually one of a kind situations like this, you might need to use PreciseConvexDecomposition. If you were to use Box or Hull there might be points where the characters walking on the triangle terrain are floating in mid air.
Object: A traffic cone.
Best CollisionFidelity Choice: Box or Hull
Why: Depending on the size of the traffic cone, you might even consider using the Box CollisionFidelity type. However if it’s a bit large and you want it to have a decent collision box, I suggest using Hull as it’ll be able to easily create the convex shape.
I briefly stated in one of the examples about the two properties called CanTouch and CanCollide. These two properties should always be disabled when players should be able to walk through them and they’ll never be interacted with. It was even verified by an admin here. Let’s get into what these mean and how to get a performance gain in your game practically instantly.
Knowing When To Disable CanCollide And CanTouch
CanCollide and CanTouch can be found in any BaseParts properties under Behavior. CanCollide means that it doesn’t or does have collision. If it’s disabled, anything including players are able to walk through it. An example of this could be bushes or grass on the ground.
The CanTouch property means that the server won’t create a TouchTransmitter on the object unless it’s enabled. If you have a bush that you can walk through, but when you touch it, it kills you, then you’d need to have CanTouch enabled so you can script that and be able to detect when players touch it.
As I briefly stated before, when both of these properties are disabled the engine will completely ignore it and it won’t render in any sort of collision. If you find yourself disabling CanTouch and CanCollide on a MeshPart, make sure to also set the CollisionFidelity of the MeshPart to Box Collision.
Let’s go over some examples of when it’s appropriate to use CanCollide and CanTouch and also when you can get a small performance gain from disabling them.
Object: A very tiny object on the ground, like a bottle or stick.
CanCollide and CanTouch: Disabled
Why: Because it’s so tiny, you don’t need to calculate collision. Objects that are small and aren’t a main aspect in your game shouldn’t have any collision at all as it isn’t important. Also because they’re both disabled, give them box collision.
Object: A sword gear.
CanCollide and CanTouch: Disabled and Enabled
Why: Let’s imagine that your sword has multiple MeshParts. You’re going to want to make sure that the Handle of the gear has CanTouch enabled so it can create a TouchTransmitter, however all the other MeshParts in the gear should have them both disabled. Also because they’re both disabled, give them box collision.
Object: A door.
CanCollide and CanTouch: Enabled
CollisionFidelity: Whatever best suits it. Probably Box.
Why: Since you don’t want players to just walk through doors, you’re going to want to set CanCollide to enabled. You should note that you will only get a small performance gain if CanCollide and CanTouch are disabled, so it doesn’t matter if CanTouch is enabled or not if CanCollide is.
Object: A high-poly eagle flying in the sky.
CanCollide and CanTouch: Disabled
Why: In this example, this eagle is just for decoration. It doesn’t do anything except fly around. Since it’s high poly you will benefit from having the CanCollide and CanTouch property disabled as well as having the CollisionFidelity set to Box.
Stop Using SpecialMeshes
This little section will be quite short, but in theory just stop using SpecialMeshes. The only usecase of SpecialMeshes I can think of would be when you want to change its VertexColor (the color of the texture) in a looped manner during run-time. If what I said doesn’t make any sense what so ever, then odds are you’re better off using MeshParts.
SpecialMeshes take up two instances (the SpecialMesh instance and the part it’s parented to) and also offers no CollisionFidelity or RenderFidelity, meaning it always is the same number of triangles. This can be countered with StreamingEnabled for the most part, but you’ll have better performance when using MeshParts.
Parts can also be scaled further down past 0.05 now, so do not use SpecialMeshes to make really small MeshParts.
Anyways, let’s continue on about MeshPart optimizations and learn on when to actually use CastShadow.
When To Actually Use CastShadow
CastShadow is a property for all BaseParts that allows the part to simply cast a dark shadow if theres a light source like the sun or a point light casting onto it.
This property can be found in any BasePart under the Appearance section. The CastShadow property uses resources to actually cast where the shadow should be. You can reduce performance lag and increase framerate by disabling CastShadow on a ton of objects that don’t need it.
In the image above is an example of when to not have the CastShadow property enabled. The plant MeshPart is already inside of a shadow and having the CastShadow property enabled will not create any extra details as it’s already engulfed by a shadow.
A good rule of thumb is to never have an object that’s in the dark have the CastShadow property enabled. Doing this will ensure that the engine isn’t wasting time on calculating shadows that can’t be seen.
In the GIF above you’ll also find another example of when to disable the CastShadow property. When you have very tiny objects, especially mid or high poly MeshParts that are tiny and minor details in your game, you’re gonna want to disable the CastShadow property as people won’t be constantly inspecting the ground looking for their shadows.
- Mesh TextureID Compression
Hello again! I’m currently writing this before I even finished the entire tutorial. This tutorial took a lot of time to create and I’m proud that it’s finally complete. If you have questions, concerns or feel that I missed anything please either message me privately or reply with it below, I’ll respond to everything.
Finally, thank you to anyone who read or even skimmed this tutorial. It took a lot of time to write and a resource like this can put new developers on the fast track to learning about optimizations for their games when building. Have a good day or night!
This topic is somewhat outdated (I believe only for missing info like StreamingEnabled, etc, current info is still all reliable), and I had a huge overhaul for this topic underway but my drafts didnt save and removed all progress. Apologies for the poorly formatted/possible grammatical errors.