Whats happens with my variable? Why it's changed?

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

Hi! I have big problem with my code, maybe it’s a bug?

I need to save position of my rays in child node to revert it back after some movement of my character. I have written simple save() function what should get data from variable and store it for later use. But for some reason when variable in character is changing values are also changed in my saved data. Of course save() function I’m using only once.

Generally it’s all what I have in scene for now, one object with rays variable and parent whit this save() function.

Why it happens? How to solve that?

CODE:

var history = []

func _process(delta):
	if Input.is_action_just_pressed("ui_accept"):
		save()
	if Input.is_action_just_pressed("ui_down"):
		for child in get_children():
			if child.get_class() == "StaticBody2D":
				print(child.rays_list)
		for hist in history:
			print(hist)

func save():
	history.clear()
	for child in get_children():
		if child.get_class() == "StaticBody2D":
			var data = child.rays_list
			history.append( data )

OUTPUT:

# just after save()
     # variable from child node
[[ray_0, (0, -128), (-1, -1), (-1, -1)], [ray_1, (128, -128), (1, -1), (1, -1)], [ray_2, (128, 0), (1, 1), (1, 1)], [ray_3, (0, 0), (-1, 1), (-1, 1)]]
     # variable from saved data (history), for now they are the same, so it's ok
[[ray_0, (0, -128), (-1, -1), (-1, -1)], [ray_1, (128, -128), (1, -1), (1, -1)], [ray_2, (128, 0), (1, 1), (1, 1)], [ray_3, (0, 0), (-1, 1), (-1, 1)]]



# after movement (without next save() )
     # variable from child node
[[ray_0, (-128, -128), (-1, -1), (-1, -1)], [ray_1, (0, -128), (1, -1), (1, -1)], [ray_2, (0, 0), (1, 1), (1, 1)], [ray_3, (-128, 0), (-1, 1), (-1, 1)]]
     # variable from saved data (history), why it's also changed?
[[ray_0, (-128, -128), (-1, -1), (-1, -1)], [ray_1, (0, -128), (1, -1), (1, -1)], [ray_2, (0, 0), (1, 1), (1, 1)], [ray_3, (-128, 0), (-1, 1), (-1, 1)]]
:bust_in_silhouette: Reply From: hilfazer

Arrays (and dictionaries) are shared. You’ve copied a reference into history variable. You need to duplicate() it:

history.append( data.duplicate() )

I have try it, bit it’s still not working :frowning:

Right now code looks like this:

var history = []


func _process(delta):
	if Input.is_action_just_pressed("ui_accept"):
		save()
	if Input.is_action_just_pressed("ui_down"):
		for child in get_children():
			if child.get_class() == "StaticBody2D":
				print(child.rays_list)
		for hist in history:
			print(hist)


func save():
	history.clear()
	for child in get_children():
		if child.get_class() == "StaticBody2D":
			var data = child.rays_list
			history.append( data.duplicate() )

websterek | 2018-08-31 18:07

Ok, i see what’s wrong - ray_list is an array of arrays and those arrays were not duplicated.
Try this:

var data = []
for ray in child.rays_list:
	data.append( ray.duplicate() )
	
history.append( data )

In Godot 3.1 there will be option to make deep copy via Array.duplicate( true ) - it will duplicate all nested arrays as well.

hilfazer | 2018-08-31 19:29

Thanks, it’s works :slight_smile:

websterek | 2018-09-01 17:54