0 votes

So, I'm making a coin generator that only generates coins inside a CollisionShape2D, I'm using preload() to load the coins and then add them in the scene and a Timer so it will generate coins every 10 seconds. I have a problem with the code, cause each 10 seconds when the node generates coins it causes FPS drops.

This is how the code looks:

extends Area2D


func _ready():
    $Timer.connect("timeout", self, "_checkGenerate")

func _checkGenerate():
    _generateCandy(1)

func _generateCandy(amount):
    for i in amount:
        var cnd = preload("res://objects/candy.tscn")#I tried to put this line and the one below in _ready so it will do use the preload just one time, but stills causing FPS drops
        var cn = cnd.instance()
        var dk = $CollisionShape2D.shape.extents
        cn.position = Vector2(randi()%(int(dk.x)*2)-int(dk.x), randi()%(int(dk.y)*2)-int(dk.y))
        self.add_child(cn)

There's a better method that doesn't cause FPS drops?

Godot version 3.2.3
in Engine by (60 points)

Why are you repeatedly preloading the resource...?

I tried to preload one time by just using preload in the ready function, but that didn't work either.

Can you share the code with the loading in _ready()?

2 Answers

+2 votes

First, when you are loading a resource inside function running in your script you use load(), not preload()

Second, loading resources is an expensive task, which is why you normally do it before the game runs. Have something like this

extends Area2D

var cnd = preload("pathtoresource")

func _ready():
    #rest of your code
by (251 points)

The code still causing FPS drops, tried replacing preload with load, and didn't work.

You are trying to load a resource every 10 seconds, don't do that. Load the resource at the start of the code and use it with the variable you assign it.

Like using one-time cnd.instance() and in the function running the rest of the code to generate the coin?

I would need to see your code with the loading under _ready() to have a better idea what the issue was.

Actually I have the code like this. Is the entire code.

extends Area2D
onready var cnd = preload("res://objects/candy.tscn")
onready var cn = cnd.instance()
func _ready():
    $Timer.connect("timeout", self, "_checkGenerate")
func _checkGenerate():
    _generateCandy(10)
    print("test")

func _generateCandy(amount):
    for i in amount:
        var dk = $CollisionShape2D.shape.extents
        cn.position = Vector2(randi()%(int(dk.x)*2)-int(dk.x), randi()%(int(dk.y)*2)-int(dk.y))
        self.add_child(cn)

instance() and duplicate() also seems to be expensive calls when used this way
so try using self.call_deferred("add_child", cnd.instance()) in your loop

Ok, but still having a problem with the FPS drop :/

0 votes

Ok, but still having a problem with the FPS drop :/

Hmm i noticed that in your example you're not freeing those generated coins
No judgement, its just that 10x10x6 = 600 coins per minute added to your scene, Yikes!!!

so i'd recommend to generate the maximum amount of coins you'll ever need displayed in your _ready() function add them to a list and when you need to show them use the_generateCandy() function to add them to the scene and after you've finished using them remove them from the scene using removeCandy(amount)

extends Area2D
onready var cnd = preload("res://objects/candy.tscn")
var generated_coins = Array()

func _ready():
    addCandy(10)
    $Timer.connect("timeout", self, "_checkGenerate")

func addCandy(amount):
    for i in amount:
        generated_coins.append(cnd.instance())

func _generateCandy(amount):
    if amount <= generated_coins.size():
        for i in amount:
            if not generated_coins[i].is_inside_tree():
                self.call_deferred("add_child", generated_coins[i])

func removeCandy(amount):
    if amount <= generated_coins.size():
        for i in amount:
            if generated_coins[i].is_inside_tree():
                self.call_deferred("remove_child", generated_coins[i])
by (4,304 points)
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.