If you want to see the scene before, you can delay your calculation by 1 frame by using yield(get_tree(), "idle_frame")
. You'll be able to see the scene, but it's still going to hang until all calculations are done.
If that's just what you need, then you don't need to read what I wrote next (but do so if you're curious^^)
Just like any calculation which takes time in any kind of programming language, what you can do is to either optimize the calculations (make sure it's not doing anything silly), spread out the calculations using "time-slicing" or use a thread.
Godot cannot do these magically for you, so you have a bit of setup work to make this happen.
Time-slicing is a technique where you basically queue all tasks and execute them one after the other in a controlled way over time. If the time spent doing tasks gets bigger than some interval (say, 8ms), then you pause the process and wait for the next frame, allowing the game to run. Then you continue processing tasks until none are left.
_ready
is controlled by Godot, not you. So this technique requires you to not use _ready
for each task, and instead fetch all nodes you want to initialize in a single function which will do something like:
# initializer.gd
# Call this when you want stuff to initialize all nodes
func _initialize_stuff():
# You can put nodes to initialize in a group to easily get them all
var nodes_to_init = get_tree().get_nodes_in_group("heavy_initialize")
var time_before = OS.get_ticks_msec()
var max_interval = 8
# Go through all of them and initialize
for node in nodes_to_init:
# You would define an `initialize` function on those nodes
node.initialize()
var now = OS.get_ticks_msec()
if now - time_before > max_interval:
# Took too long to process, suspend loading and continue next frame
yield(get_tree(), "idle_frame")
time_before = OS.get_ticks_msec()
print("Done!")
# If needed you can emit a signal or use `call_group`
# to notify things finished to load
I used yield
here but other solutions exist using _process
and some member variables.
Note that you could also instance your nodes one by one if they are procedurally generated for example.
Another way is to use threads. It can be a little bit trickier, because you can't access the scene tree from within a thread (it's not "thread-safe") so be sure your heavy processing is just dealing with data and resources. See http://docs.godotengine.org/en/3.0/tutorials/io/background_loading.html