+3 votes

Hi,

I'm preloading some elements on the scene with preload() function. It should make creation of an instance of preloaded scene instantly available, but it doesn't seem to work entirely as intended. Each time a resource or scene, which was preloaded, is spawned for the first time, there is a small freeze of the game and some frames are skipped.

For example, first enemy I spawn cause little freeze, but each next of the same type is loaded instantly without freezes. If I want to spawn other type of enemy (different scene), again, first spawn causes mini freeze, and next is OK.

Am I missing something important here? I want to have all the required resources preloaded at the beginning of the level, so they are available instantly later on.

How can I do this?

in Engine by (137 points)

Could You provide code sample for preloading and spawning ?

Sure, it's simple:

const BadGuyTemplate = preload("res://BadGuy.tscn")

func spawnBadGuy():
    var new_BadGuy = BadGuyTemplate.instance()
    add_child(new_BadGuy)

I have the same problem, only it happens to me, when I spawn object that has emission set. Haven't found out why, though.

I've made a workaround for this by adding this code to the scene:

const BadGuyTemplate1 = preload("res://BadGuy1.tscn")
const BadGuyTemplate2 = preload("res://BadGuy2.tscn")
const BadGuyTemplate3 = preload("res://BadGuy3.tscn")

func _ready():
    var new_BadGuy = BadGuyTemplate1.instance()
    add_child(new_BadGuy)
    new_BadGuy.queue_free()
    new_BadGuy = BadGuyTemplate2.instance()
    add_child(new_BadGuy)
    new_BadGuy.queue_free()
    new_BadGuy = BadGuyTemplate3.instance()
    add_child(new_BadGuy)
    new_BadGuy.queue_free()

This way I load and dispose everything I need at the start and got a big freeze (about half a second) at the very beginning of the level, but then everything is smooth.

This is working for me OK now, but it's not an elegant solution.

Indeed its not :) I have the same code for preloading as You and it seems to work without any freezes.

const BulletScene = preload("res://demo/bullet.tscn")
...
func create_bullet() -> RigidBody2D:
    var bullet = BulletScene.instance() as RigidBody2D
    bullet.position = $ShootingPoint.global_position
    bullet.collision_layer = other_player.collision_layer
    bullet.collision_mask = other_player.collision_mask

    return bullet

You can try also another approach with allowing to provide bdGuy scene from editor

export(PackedScene) var BulletScene

And than inside editor drag and drop Your bad guy scene.

Could You also check how large is Your texture sprite or do You have any heavycomputing inside _ready on Your badGuy script

Oh, I see you are in 2D. I should mention, I'm in 3D.

In that case maybe it is an issue with engine itself. Ask big brains at https://github.com/godotengine/godot/issues or report an issue :)

Yeah I think it would be best to open the github ticket but it's best to localize the issue first, otherwise it's likely to get ignored, @skipperro do you have any special material settings in your bad guy scene? Try the scene without the materials, if it doesn't lag the problem is in materials.

It's not only in the characters. It's on everything I load this way. I've got the BadGuys, but also for example a scene containing a single arrow, that I spawn, when BadGuy shoots his crossbow. Also an explosion, that have no mesh at all, only particle effects, omni light, sound and area to detect who is affected by the explosion.

There are some textures on every scene, but it cannot be, that every texture I use for every item I spawn is somehow broken.

No texture is broken :) There is a bug in the engine, that causes the lag and it's triggered when specific object appears. In my case it's when units shoot, and I preload the muzzle, I think it's due to the emission setting on the material. There must be some common lag trigger for your scene, you just have to find out what is it. I would guess that it has to do with lighting, because that is also in my case.

Well... I do have many light sources with dynamic shadows everywhere, because light and shadow plays important role on my game. Also, I have the same lag when I enable shadows on Directional Light node, so... you might be onto something.

I am trying to find a solution to this as well. I found something, but it's extremely hacky and not sure if I'm going to use it yet, but figured I'd post it here.

In your main UI canvaslayer, add a Node2D called smooth_preloads. Then, create var smooth_preloads = [] and a func called smooth_preload. Now, append the paths of your scenes you want to be smoothly loaded.

func smooth_preload():
    for path in smooth_preloads:
        var t = load(path).instance()
        smooth_preloads_node.add_child(t)
        yield(get_tree(), "idle_frame")

    for node in smooth_preloads_node.get_children():
        #node.queue_free()
        pass

There are some caveats with this:
- The scene must be VISIBLE in your player's viewport.
- You cannot make it invisible or hide it.
- If you run queue_free after they are loaded, it won't work.

I initially was going to use this solution because I figured I could set the opacity to 0 and then maybe receive a signal once the preload is called, and queue_free it from smooth_preloads_node. However, it seems like even if the opacity of the node is set to 0, the hiccup still happens. I'm stumped.

My solution does work, but the preloaded scene has to be visible on the player's viewport first. Tested on exported builds as well.

Still not sure how to go about this... but it's essential. For example, if a player joins a game and uses a skill. There should be no hiccup at all if we are using preload

:( No idea what to do as there is no way I'm going to have all the skills/scenes visible on the screen lol.

I am seriously contemplating on switching game engines. However, it's been nearly half a decade there is no turning back. But good lord, it's been hell. So many bugs and issues, when does it stop! :X

edit: I am going to stay optimistic though and hope it can be fixed

~~Hmm. It seems like this is happening if you are calling duplicate() on a material (however, it only hiccups once then it's smooth as butter). I'm going to do some more testing.~~

edit: Nevermind. Nope it doesn't. I'm totally stumped lmao.

Please log in or register to answer this question.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.