0 votes

Hi all. I'm an absolute beginner here with very basic knowledge in coding. I am creating my first game. It is like an endless runner with random spawns of obstacles moving at different speed from top (out of screen) to bottom (exit screen). There are different types of obstacles and each of them have their own speed. These same few obstacles are used in different scenes but they are positioned differently.

Everything was going well for me until I reached this weird problem... I managed to get the same few obstacle scenes to be randomly instanced but it doesn't seem to work every time. Some times it works endlessly, some things when I closed it and reopen, it doesn't work at all or it just works for a few spawn and then it just stops instancing.

Appreciate it if anyone could advise me on this? Is it because my codes aren't ideal or is it because of queue_free or the clash of the same instanced scene names, etc.? Thanks a bunch :)

Sample of my codes in my main scene's script:

const mobs_1 = preload("res://Mobs_1.tscn")
const mobs_2 = preload("res://Mobs_2.tscn")
const mobs_3 = preload("res://Mobs_3.tscn")     

 func spawn_mobs_1():
    var new_mobs_1 = mobs_1.instance()
    call_deferred("add_child", new_mobs_1)
    new_mobs_1.position.x = rand_range(25, 480)

func spawn_mobs_2():
    var new_mobs_2 = mobs_2.instance()
    call_deferred("add_child", new_mobs_2)
    new_mobs_2.position.x = rand_range(25, 260)

func spawn_mobs_3():
    var new_mobs_3 = mobs_3.instance()
    call_deferred("add_child", new_mobs_3)
    new_mobs_3.position.x = rand_range(25, 195)

func spawn_mobs():
    var randomNum = randi()%4 + 2

    if randomNum == 1:
        spawn_mobs_1()

    if randomNum == 2:
        spawn_mobs_2()

    if randomNum == 3:
        spawn_mobs_3()

func _on_Player_spawn_mobs_signal():
    spawn_mobs()
# When Player exits Area2D of obstacle scene, this signal is called. When obstacle scene's VisibleNotifier exits scene, queue_free().
Godot version 3.3.2
in Engine by (20 points)

1 Answer

+1 vote
Best answer

You can use an array for the, lets say, "spawnable mobs", here's my code for a very similar thing i did for my gf:

extends Node2D


var spawnpos = Vector2() #This is randomly assigned later

var biker = preload("res://Games/Dodger/Biker.tscn") #Mob1
var walker = preload("res://Games/Dodger/Walker.tscn") #Mob2

var spawnable = [biker, walker] #Array of spawnable mobs


func _ready():
    randomize() #This is very important because it creates a new "seed" for your randomness, your code doesnt seem to have it.


func _on_RandomSpawn_timeout(): #This timer autostarts with the game

    spawnpos = Vector2(rand_range(104,600), -200)

    var spawn = spawnable[randi()%spawnable.size()].instance() #This chooses a random mob from the list (the array)

    add_child(spawn) #Adds it into the world

    spawn.global_position = spawnpos #In the randomly chosen spot, in my game they spawn in a fixed offscreen Y coordinate, with a random X coordinate.

    $RandomSpawn.start() #Makes this spawn timer restart.
by (298 points)
selected by

Thanks for your reply!

I do have randomize() already but it's just somehow the mob scenes don't always spawn. Sometimes the spawns are called twice. Some times none at all or just once before it stops. I'll definitely try the array method.

Would the spawnpos work for me if each of my mob scene has different size? This is why I have specific spawning range on position.x for each of the mob scenes otherwise they'd spawn over the walls or other objects.

Update: I tried your codes. There were errors due to my own typos but I figured it out. It works!! But the whole game freezes a bit every time the respawn is called and the debugger keeps telling me to use set/call_deferred(). And the spawnpos can't work for me as my mobs have significantly different sizes which will spawn them on walls and off screen for some. Any way to fix these problems?

Update 2: I replaced addchild() with calldeferred(). It seems to have stopped the debugger from going off and the game stopped freezing too. The only thing I need to figure out is how to set a unique spawning range on position.x for each mob scene.

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.