How to prevent duplicate function calls/instancing when adding a single instance to the tree?

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

I have been using Godot for a little while and now want to recode a snake game I wrote before in Lua and java.

I am really struggling with instancing a scene and adding it to my tree.
Somehow a function which is called on one single instance by the node above (its parent node) seems to take place twice as soon as I added it to the tree.

The SegmentScene I instanced holds only a Sprite as the root node with SegmentSkritpt.gd attached to it.
instanced

When I add an instance of that scene to my tree and call a function of the script attached to that scenes’ sprite, it would always take place twice - and even worse - when printing the instance out upon calling its function, it prints two different numbers, meaning it is not only calling the function of one instance twice but instead the instance itself exists twice, although created and added only once.
When I call the function on the created scene instance, storing it in an array before adding it to the tree, it won’t print anything at all…

tree

  • map contains an unrelated script
  • snake contains SnakeSkript.gd with related parent parts

in the create method:

var head = SnakeSScene.new()
add_child(head)
snake.append(head). #adding it to own array for referencing

and in the process method:

if snake[0] !=null:     
    snake[0].updateSnakeLog(delta)

calling it only on one instance and even if I put get_parent().get_child(0).updateSnakelog(delta) here it gets called twice in SnakeSegmentSkript

SnakeSkript.gd:

extends Node

var SnakeSScene = preload("res://SegmentSkript.gd")

var snakeSpd = 32.0

var snakeCmds = []

var snake = []
func _ready():
var head = SnakeSScene.new()
add_child(head)
snake.append(head)


func _process(delta):
	
if Input.is_action_just_pressed("ui_left"):
	if snakeCmds.size() ==0 or snakeCmds.back() != 0 and snakeCmds.back() != 1:
		snakeCmds.append(0)
elif Input.is_action_just_pressed("ui_right"):
	if snakeCmds.size() ==0 or snakeCmds.back() != 1 and snakeCmds.back() != 0:
		snakeCmds.append(1)
elif Input.is_action_just_pressed("ui_up"):
	if snakeCmds.size() ==0 or snakeCmds.back() != 2 and snakeCmds.back() != 3:
		snakeCmds.append(2)
elif Input.is_action_just_pressed("ui_down"):
	if snakeCmds.size() ==0 or snakeCmds.back() != 3 and snakeCmds.back() != 2:
		snakeCmds.append(3)

if snake[0] !=null:		
	 snake[0].updateSnakeLog(delta)


func addSnakeSegment():
pass

SnakeSegmentSkript.gd:

extends Sprite

var direction 
var snakeLogTimer = 0 
var walked = 0
var cmdIndex = 0


func _ready():
#snakeLogTimer=get_parent().get_child(0).snakeLogTimer
self.position.x = (SnakeSkript.snakeSpd/2)
self.position.y = (SnakeSkript.snakeSpd/2)
texture = load("res://assets/snake.png")
scale.x = SnakeSkript.snakeSpd/16
scale.y = SnakeSkript.snakeSpd/16
setDirection(globals.dirRight)

func setDirection(d):
direction = d
self.rotation_degrees = globals.directionRotations[d]


func movePosition(x,y):
self.walked += 1
position.x += x
position.y += y



func _process(delta):
pass

func updateSnakeLog(delta):
	
snakeLogTimer += delta
while snakeLogTimer >= 1/SnakeSkript.snakeSpd:
	snakeLogTimer -= 1/SnakeSkript.snakeSpd
	if direction == globals.dirLeft:
		movePosition(-1,0)
	if direction == globals.dirRight:
		movePosition(1,0)
	if direction == globals.dirUp:
		movePosition(0,-1)
	if direction == globals.dirDown:
		movePosition(0,1)
	
	if walked >= SnakeSkript.snakeSpd:
		walked = 0
		initNewSteps()

func initNewSteps():
    print("head"+ str(self))
    if cmdIndex >= SnakeSkript.snakeCmds.size():
            SnakeSkript.snakeCmds.append(direction)
    setDirection(SnakeSkript.snakeCmds[cmdIndex])
    cmdIndex +=1

So the snake node should add one instance of that snake segment scene and call update log… there a timer fills and triggers walked+1 once in a while. As soon as walked is >= 16 it gets reset and calls initnewStep() where “head” and the object is printed.
with this code every second initnewStep will be trigged by the updated instance and “head”+str(self) will be printed, but in Godot somehow two instances exist?!

This is the output:

head[Sprite:1180]
head[Sprite:1412]

:bust_in_silhouette: Reply From: yesyoor

I solved it. The mistake I made was to import the class on autoload and attaching it to a node in my tree, which lead to a double instance of the script inside the tree.