About preload() function and the way it works

joan_fase

There's one thing i'd like to confirm concerning the preload() function and that's when it is called (english isn't my first language so forgive me for any mispellings / grammatical errors).

If i understood correctly, in the Scoreboard script, preload() is called inside the add_row() function, return a resource (precisely a PackedScene) which is then turned into a node through the instance() function, node that we nest inside ScoresColumn through the add_child() function.

func add_row(player_name: String, player_points: String) -> void:
var row := preload("ScoreRow.tscn").instance()
scores_column.add_child(row)


So the way we learned it through the GDQuest learn-to-code app (by the way, thanks for this great teaching tool!), the preload() function should be called when the first instruction of the add_row() function is executed except the Godot documentation seems to indicate that preload() is actually called when the script is loaded (which makes more sense to me) so i'd like some precisions on the matter. Is preload() something like a special function that Godot automatically search for when loading a script? I feel this is the case because of the following lines written in the course:

"It’s a special function that tells Godot to load the scene once upon launching the game and later keep it in memory."

If that is the case, does it work like a web cache? Keeping the resource in memory so that every other files can later access it without Godot having to load it twice?


I just feel i should ask because the preload() function seems to be in quite a lot of Godot projects' scripts and understanding how it works seems relevant to me (I apologize if it is explained later in the course, i didn't check  because i wanted to understand that part before going into practice projects ).

On a separate note but still related to preload(), i want to point out to beginners like me that right clicking on a scene in the FileSystem dock then choosing "Copy Path" instantly gives its resource path which is a very nice shortcut.

  • Xananax replied

    You're completely correct on every point, yes. Good deductions!

    The preload function is indeed analyzed by Godot before running a script, and all the resources specified are loaded in advance, then kept in memory.

    That means that if you use preload("a.tscn") many times through your project, "a.tscn" will only ever be loaded once.

    The code

    func add_row(player_name: String, player_points: String) -> void:
        var row := preload("ScoreRow.tscn").instance()
        scores_column.add_child(row)

    is exactly equivalent to the code

    const ScoreRow := preload("ScoreRow.tscn")

    func add_row(player_name: String, player_points: String) -> void:
        var row := ScoreRow.instance()
        scores_column.add_child(row)

    In both cases:

    • ScoreRow.tscn will only be loaded once.
    • ScoreRow.tscn will be loaded when the script loads (before the function add_row() is called).
    • The editor will be able to determine before running the script if the path is correct, and will throw an error and refuse to run the script if the file isn't found.
    • the path needs to be static (it cannot be generated or contain a variable).

    So, if you want to be pedantic about it, the sentence

     preload() is called inside the add_row() function, return a resource

    is not exactly correct. The more correct way of phrasing it is

    preload() is called on script load, then its cached result is used in the add_row() function.

    I know this is what you meant, no worries, just clarifying.

    A Note About Load()

    This is in contrast with load(). load() is like preload():

    • It also only loads a file once.


    But:

    • It loads a file only when the load() function is called.
    • It cannot know if a path is correct in advance, and the editor can't help you
    • the path can be dynamic/generated


    In the code

    func add_row(player_name: String, player_points: String) -> void:
        var row := load("ScoreRow.tscn").instance()

    If your path is wrong, you will not know before the game tries to run add_row(). For that reason, it's preferable to use preload() by default, and only use load() if you have no choice.

    1 love
  • joan_fase replied

    Thanks a lot for the quick and detailed answer, i now have a clear idea of how it works. This course's content is really great but more than that the follow up on every question deserves respect. Keep up the good work sir and thanks again!

    1 love