|
|
|
|
Reply From: |
Zylann |
In GDScript, the main way to do optimization is to optimize the approaches themselves, the algorithms and data structures you choose to use (dictionary vs array is most common).
Knowing which engine functions to call also helps. For example, you mentioned accessing other nodes: if you use get_node("path")
or $path
everytime for a node that you know is always present, sure it will have a cost (small), the engine has to decompose the path and compare node names until it finds the correct one, which can however be easily avoided by storing the node in a variable with onready
, with the added advantage of failing earlier if the path is wrong.
Another point is memory: allocating memory often has a high cost. .new
and .instance()
may allocate memory and run construction logic. In Godot, custom allocation strategies are in place under the hood to optimize this already, but constructing and destruction objects still has a “setting-up” cost when they are many. So if you plan on having hundreds of VFX and bullets in your game, investigate how much do they take on frame time and pool them if needed.
Lazy-loading can also impact performance: a typical bottleneck in Godot 3 are shaders. They are very big internally and take a long time to compile, and that can only happen when first needed, so the first time an object is visible or an effect plays, it causes shader loading and short freeze (See https://github.com/godotengine/godot/issues/13954). It’s not necessarily related to scripts, but something to know about if you optimize your game.
The same applies to sounds: if you play a sound by load
ing it on the spot, it might be loaded on that spot, and cause a freeze. The solution is to either set it in advance on the sample player, or preload it.
Use signals and input callbacks when suited. It can be tempting to put everything in _process
, but not all things are frequent enough to need constant polling.
Optimizing script bottlenecks can be adressed in two ways:
- Old school method, you can wrap the region you want to profile between
OS.get_ticks_usec()
calls and calculate how many microseconds the function took to execute. Keeping everything under 16ms is usually the goal. Try on lower-end devices if you have margin.
- Use the profiler in the debugger tab. It has a listing of functions, but will only profile if you enable it while the game runs. I find it lacking in usability and features though, even the doc has almost no details on it Overview of debugging tools — Godot Engine (3.0) documentation in English, which is why I often fallback on the old school method.
Oh my lord, you have no idea how useful this is!
I’ve been using a lot of process functions to check for changes in booleans. For instance process(delta): if “var” == true: “do something” then “var” =false
What do I do to replace this code?
FYI the “var” is located in a singleton that “controls” the flow of the game
Any more help is appreciated
Icewheel12 | 2020-02-23 19:16
maybe try to use signal, its only check when the condition meet, not every frame like in the process(delta) function
ruruarchy | 2020-03-28 13:20