Memory usage issue

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Dava

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
– enemy_spawner
— enemy_one_timer
— enemy_two_timer
— enemy_three_timer
— enemy_four_timer
– inverted_enemy_spawner
— (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

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.

kidscancode | 2018-04-29 16:21

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

Dava | 2018-04-29 16:35

:bust_in_silhouette: Reply From: kidscancode
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.

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!

Dava | 2018-04-29 17:20

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!

Dava | 2018-04-29 18:40