Edited: Function called with for loop in give a different result than the same function called with If Input.is_...

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

Edit:
Completly changing my question because i discovered something.

In the code below, the way i’m trying to call my function several times with a for loop in the _ready function seems to be the problem.
When i do it like this, the 4 instances are taking the same position, they all have SlimePosition = 3
Printed this in the _process, the 4 first lines are the instances ID.
It seem that my SlimePosition is jumping directly to 3 after spawning the 4 instances.

But when i’m calling the function with this

if Input.is_action_just_pressed("ui_accept"):
		slime_spawning()

I can press my key 4 time and everything go as intended.

What is the for loop or the _ready function doing ?
And how can i call the function several time when launching the game ?

Here is the code of the Main scene

extends Node2D

onready var SlimeScene = load("res://Scènes/Slime.tscn")

signal SlimeNbr

var SlimeNbr = 0

func _ready():
	for _number in range(4):
		slime_spawning()

func slime_spawning():
	var SlimeInstance = SlimeScene.instance()
	add_child(SlimeInstance)
	emit_signal("SlimeNbr", SlimeNbr)
	SlimeNbr += 1

And here the code of the Slime scene

extends Sprite

onready var ListenMain = get_parent()

var SlimePosition = 0
var PositionSetted = false
var InstanceSpawned = 0
var PositionVectors = [Vector2(104, 64), Vector2(136, 96), Vector2(168, 64), Vector2(136, 32)]
func _ready():
	ListenMain.connect("SlimeNbr", self, "position_var_setter")
	PositionSetted = false
	
func _process(delta):
	if PositionSetted == false and SlimePosition == InstanceSpawned:
		position_setter()
		PositionSetted = true

func position_var_setter(SlimeNbr):#Cette fonction fonctionne
	SlimePosition = SlimeNbr
	InstanceSpawned = SlimeNbr

func position_setter():
	self.position = PositionVectors[SlimePosition]

Thanks

:bust_in_silhouette: Reply From: Inces

I am sorry but this is hard to understand :slight_smile:
I had problem getting earlier question too :slight_smile:

In ready function You call function spawning 4 times, once for 0,1,2 and 3, thats how range works. I guess this is what You wanted ? Your SLimenumber should be 4, is this what You were printing in debug ? Because relation of slimenumber and slimeposition in Your code seems off.
First of all You emit signal before rising the slimenumber, so first singnal carries argument 0, next ones being 1,2 and 3.
Second, You emit signal one line after adding child of slime, and expect this signal to already be connected, which should happen in fresh childs ready function. It might be mistimed.

I don’t know what do You want to ultimately achieve, but if You need slimes to be spawned one after the other, not at the same time, than You should fit all the code for spawning in for loop, or make a yield corroutine inside loop. Is that it ? If not describe what is intended result, and where did you call print for debug in example above.

Hey
Sorry if it is confusing, i’m trying to be clear but i’m new to programming, i don’t understand all the concepts and i’m not even sure that my english is good.

I’ll explain it like this
Initially in project my 4 Slimes were already in the scene before launching the game and the SlimePosition was an export var. For each Slime i was setting the value from 0 to 3 in the Editor before launching the game.
I was using that variable to say which slime was taking the damages.
If SlimPosition == Variable Grabbed from the player: call the function to deal damages

But now I want to spawn them instead of having them already present in the scene. I can no longer set the value from the Editor and they are spawning with the original value from the original Slime scene.
So my idea was to Start with SlimePosition = 0 and each time I spawn one Slime I increase that value by 1, so the first Slime would have 0, the second would have 1, until I reach 3.
My problem is that when I increase the value of SlimePosition, it is also updated for the instances that are already spawned and so earlier i was asking if it is possible to reproduce what export var do, unlink the value of the original scene and the value that was given to the instance.

Now, the for loop problem
The print was to show that the SlimePosition jumps directly to 3 instead of doing 0,1,2,3.
The problem was not occuring when I tried to spawn them manually.
I fixed it by attaching a Timer and using the timeout

func _on_Slime_spawning_timeout():
	slime_spawning()
	if SlimeNbr == 3:
		SlimeSpawningTimer.one_shot = true

I would say that the problem is linked to the speed at which they were spawned, because the same thing happens if I set the wait_time of my timer too low.
So yeah, yield might be a solution for this. Thank you !

Any clue for my Instance/variable problem ?

Ph_Pheo | 2021-03-22 17:20

Ah so You want every slime to spawn at different position !
You were close to finding sollution. It can be done much easier with just this starting loop.

For number in range(4)
var slime = slime.instance()
slime.set_position(number)

This is pseudocode, but notice how You can use number of currently iterated loop as a variable and use it. In other words this loop will give You 0,1,2,3 as arguments and You can do whatever You want with them, any calculations, before You transform it into something usefull. For example

For number in range(10)
if number%2 == 0:
slime modulate red
else:
slime modulate blue
add_child(slime)
This would spawn slimes alternately red and blue

Inces | 2021-03-22 18:59

Okay thanks for your help

Ph_Pheo | 2021-03-23 10:58