0 votes

HI, I finished making a game, it had no problem (decent framerate, objects behaved as expected, etc) but it turned out i was wrong....
On my crappy 1GB Ram tablet, the game crashes after playing for approximately 5 minutes, at first i thought it was just the custom rom I installed because it seems to not handle android apps too well. But when i ran the game on my PC and checked the task manager, the game kept increasing in memory usage again...and again..... especially when i was in the game scene which is arranged like this:

-game
-- player
-- enemyspawner
--- enemy
onetimer
--- enemy
twotimer
--- enemy
threetimer
--- enemy
fourtimer
-- inverted
enemyspawner
--- (same child as enemy
spawner only inverted now)
-- powerup_spawner
--- (some child scenes)
-- (more child scenes but don't have effect)

When i removed the spawner nodes, the memory usage issue was gone and when i changed scene to the main menu, some memory even got freed.
But when I had the spawners (especially the enemy ones) the memory usage just kept increasing and even when i changed scene to the main menu, the memory doesn't get freed

The enemy_spawner instanciates the enemy scenes and when the timer for the specific enemy runs out, it gets spawned and moves continueously to the right (inverted is to the left) I took a look at my enemy scenes (all are area2d, some have kinematicbody2d) and had them get queue_free() when it reaches certain cordinates but that did not make a difference, the memory usage still increases

I read this issue with the scene memory, indicating that i should free the previously used scene but i don't know how to implement that on my stage manager script (from angegastudio flappy bird)

 extends CanvasLayer

const GAME = "res://src/main/game.tscn"
const MENU = "res://src/main/menu.tscn"

var is_changing = false

signal stage_changed

func _ready():
pass

func change_stage(stage_path):
if is_changing: return

is_changing = true
get_tree().get_root().set_disable_input(true)

# fade to black
get_node("anim").play("fade_in")
audio_player.play("sfx_swooshing")
yield(get_node("anim"), "finished")

# change stage
get_tree().change_scene(stage_path)
emit_signal("stage_changed")

# fade from black
get_node("anim").play("fade_out")
yield(get_node("anim"), "finished")

is_changing = false
get_tree().get_root().set_disable_input(false)
pass
asked Apr 29, 2018 in Engine by Dava (115 points)
edited Apr 29, 2018 by Dava

There's nothing that jumps out at me as wrong from your description. Are you sure the enemies are getting freed? Can you share some of your code - especially the spawner and enemy scripts? Maybe then someone can spot what might be going wrong.

This is the script for one of the enemies

extends Area2D

var inverted = false
const SPEED = 4

func _ready():
  set_fixed_process(true)
    connect("body_enter", self, "_player_enter")
        pass

func _fixed_process(delta):
        if !inverted:
            move_local_x(SPEED)
        if inverted:
            move_local_x(-SPEED)

       if !inverted:
          if get_pos().x >= 780:
           queue_free()
       if inverted:
         if get_pos().x <= -50:
           queue_free()
        pass

    func _player_enter(body):
       if body.get_name() == "player":
            if invincibility.invincibility:
               sfx.play("hit")
               particle.set_pos(Vector2(get_pos().x,get_pos().y))
               particle.set_emitting(true)
               get_node("/root/game/scorescn").points += 10
               queue_free()
         else:
           get_node("/root/game/player").health -= 1
           sfx.play("hit")
     pass

This is the script for the enemy_spawner showing how it spawns the same enemy

extends Node2D

onready var onepck = preload("res://src/enemy/enemy_one.tscn")
onready var one = get_node("enemy_one_spawner")

var onescn

func _ready:
     one.connect("timeout",self,"_spawn_one")
     one.set_wait_time(3)
     one.start()
     set_process(true)

func _process(delta):
     onescn = onepck.instance() # I might have moved this code to the _spawn_one function
     if score.points >= 1000:
        one.set_wait_time(2)
     if score.points >= 2000:
        one.set_wait_time(1)

func _spawn_one():
   randomize()
   var randpos = randi() % 1280
 #onescn = onepck.instance()
 add_child(onescn) 
  onescn.set_pos(Vector2(-10, randpos))

  # every other enemy have the same code of function in this script

1 Answer

+1 vote
onescn = onepck.instance() # I might have moved this code to the _spawn_one function

This line definitely shouldn't be in _process() or you'll be instancing another enemy every single frame. If the timer function is doing the add_child() then they'll only occasionally be added to the tree, but you're still instancing one every 1/60 sec.

If you have moved it to _spawn_one() make sure you did on any other spawner or instancing code you're using.

answered Apr 29, 2018 by kidscancode (12,138 points)

I had a feeling that might have been a problem, when I get back to my PC and fix this, i'll send you a feedback (if i can) thanks!

It works! Thanks a lot! But the memory doesn't get freed up when the menu scene is loaded, but memory usage seems to not exceed a certain limit!

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.