what would someone need to do to optimize their game where it uses like the least resources possible… i mean like micro optimizations.
I can tell you the most important things about optimization:
-
cast shadow
roblox uses deferred render method, so the shadows are only rendered on the screen. they update everytime there is a motion on the screen, that causes lags when rotating your camera.
Solution: Get rid of shadow casting on tiny and unnecessary parts, that will not affect visual a lot, especially on future technology. -
future local light
they lag a lot with shadows on, use them as rarely as possible and let your players disable shadows if they want -
geometry
use streaming for terrain and small models, and you can also write your own LOD system to reduce geometry from bigger models/meshes with better results. -
transparency
transparent objects are very laggy, many trees/bushes from toolbox are using transparent leaves.
for bad leaves, add surface appearance, set it to transparent mode, and add leaves texture. don`t forget to set mesh transparency to 0 after that. -
terrain
complex terrain will eat more memory, remove caves and hollow spaces under terrain to optimize memory. grass decorations can be mixed with any other material so less grass will be rendered. -
parts
too much parts can lag the game, use streaming or your own LOD system to reduce part count
I think that`s all
I can tell you some optimizations that I have done before.
- Always defer updating things except for user input, for example the moving leaves of trees or motion blur. You should also have a tick queueing system for these updates.
- Avoid creating and destroying instances every frame. Creating instances is very expensive.
- Avoid very large particles. Overdraw wastes an insane amount of GPU power.
- Avoid division. The
/
operator is very slow. Try to cache division first if possible (for example 1/2, 1/8, etc), and use the*
operator. - Cache calculation results if it’ll be used later to lower CPU overhead.
- Avoid nested if statements. You should also cache if conditions in a variable first if you’ll need it later.
- Use timed
task.wait()
s usingtick()
in loops that are using very large tables to avoid stuttering and script timeouts. - Add
--!native
at the top of your server scripts to enable native code generation. It’s basically a free performance boost. - Use actors and multithreading for heavy calculations. This boosts performance for things like generated terrain.
- Finally, avoid printing things into the console multiple times each frame. This is really bad.
That’s all that I can remember.
so its faster to do 1 * 0.5
than 1 / 2
?
wait could you elaborate more? how would i make a tick queuing system
Plenty of resources already. Why reinvent the wheel?
Just keep looking. These are just the tip of the iceberg.
exactly… they are just the tip of the iceberg…
- optimize your light sources (especially for future. CastShadow doesn’t affect performance - it’s your lights with
.Shadows
on that do! Overlapping lights especially decimate performance) - do not use unions that much. Unions, while they seem useful, still have to load each part of the operation once. They are also suffering from recalculating hitboxes each time they load.
- Reduce your part counts, and use meshes instead (more on that). Meshes have one draw, which is really good considering the complex shapes.
- Build around the principle of low draw calls (and remember, each shadow casting light on future has to re-render the scene, meaning many drawcalls)
- Use meshes, and you should probably learn to model. Meshes get GPU acceleration (they can store their data in VRAM and they get processsed by the GPU)
- Optimize your meshes! And use GPU instancing, (reuse assets). If you reuse a meshpart, ROBLOX only has to load said mesh once and store it in memory, meaning if you have Mesh X, you can duplicate it 200 times and only have 1 draw call since ROBLOX stores it. This however does not apply to meshes who’s transparency, color, or other aspects have been modified (since that means it has to redraw).
- Collisions: they cost a lot (especially for complex shapes, so dont use parts). Use hull for most meshes, and try lower the use of needless CanTouch (since it means the parts aren’t checking for touches)
- Triangles are important, but modern GPUs (even iGPU or mobile) can crunch a lot. again, draw calls are quite more important
edit*
- StreamingEnabled is your best friend for large maps. While it is iffy, you can quite intuitively reduce pop-ins by just altering the settings. I don’t remember specifics, but there are specific modes that determine how it behaves and whether it consumes more client or server resources. Also, for scripting, you can force streamingenabled to not stream specific assets, to avoid known issues with :WaitForChild() or :FindFirstChild()
That was more about building, now scripting, I can’t really say since I don’t script games, but;
- Avoid
RunService.Heartbeat
, and humanoids. Per frame updates, it is good practice to use these ONLY when you have to. Loops, avoid them for the most part and look into event based stuff instead. - Optimize your code (while that goes without saying), follow good practices, disconnect your events, and watch your memory (memory leaks happen really easily if you don’t watch), also watch your tables, they wont be garbage collected so long as they hold a reference to an object (even one that has been destroyed) ((afaik))
- Use the client, server will build up (especially for games if you have NPCs, like TDS)
- task.desynchronize (while good) is not needed for EVERY operation (or paralell luau). In some cases, it might actually spawn more overhead than the task you’e doing. Heavy math, AI, pathfinding. All that = task.desynchronize/ConnectParallel()
- use ContentProvider to preload important assets (or the whole map). It helps with buffering if you have to load large models/assets from replicatedstorage, loading screens basically.
Hope this helps, and please note I’m not a pro scripter (or really that good…) so take all my notes with a grain of salt. Research, there are tons more optimiztaions. It is pivoal that you optimize your scripts, as roblox isnt really that heavy on the GPU (its easier to optimize your graphics).
16.67ms is the frametime you should aim for 60fps. lower, the nicer!
collision fidelity doesn’t seem to do any effect for me except using .Touched
event on high-polygonal colliders. also precise low-poly collider should do a better job than default, a 12-120 triangles against many complex voxels.
and CastShadow
will reduce lag when redrawing shadow map
For the trees, its the opposite for me. likely you did smth wrong, or as i mentioned, changing color will make it not apply.
CastShadow won’t reduce lag as it just changes whether shadows are drawn or not (which costs like nothing, hence even the docs say it doesn’t affect performance). the lights are still drawn, and shadows are costly because you have to redraw the whole scene from the lights pespective to generate a shadow buffer. regardless of castshadow being on this happens, hence why only Shadows
affects it.
i tested in one of my scenes,
- shadows on (castshadow)
- draw calls were at 280 (total scene calls! this includes shadows that means)
off:
- shadows off (castshadow)
- performance and everything stayed the same. using future btw
performance tips documents say that castShadow property should be turned off, and they`re right! game becomes smoother when there aren’t many shadowcasters. moving the camera forces the engine to redraw shadows, less shadow casters = less work. I tested it
What? castshadow only alters if they’re drawn. not if they’re considered. afaik
for me, in a dense shadow scene, it had no effect. disabling shadows did however