Godot Function is Changing Input Variable?

Godot Version

Godot 4.5.1 Stable

Question

I wrote a function for detecting a player’s inputs in my game, and seeing if they match up with a particular string of inputs stored in an array. For some reason, when I work with the data inside of the function, it changes the values of the source array?

Here’s the function with unnecessary parts cut out:

#									This part of the function uses an array of strings
#									VVVVVVVVVVVVVV
func grab_input_chain(target_chain : Array[String], time_tolerance : float) -> bool: #if the player has inputed the correct chain in the correct span of time, then this returns TRUE and nulls the inputs.
	var index = 0
	
	#Here is where the function changes the strings, replacing "Forward" and "Backward" with "Left" or "Right" depending on which way you're facing.
	#VVVVVVVVVVVVVVVVVVVV
	for i in target_chain:
		if facing_right:
			i = i.replace("Forward", "Right")
			i = i.replace("Backward", "Left")
		else:
			i = i.replace("Forward", "Left")
			i = i.replace("Backward", "Right")
		target_chain[index] = i
		index += 1

	return true #here, we assume it always returns "true" for testing purposes

If I were to call this function:

var desired_input_chain := ["Forward", "Backward", "Forward"]
var facing_right := true
if grab_input_chain(desired_input_chain, 1.0):
	print(desired_input_chain)

…It would return:

Right Left Right

So apparently, it’s changing the array that I’m feeding into the function.

Any idea why this is happening?

Because in GDScript arrays are always passed by reference. This means your grab_input_chain() function receives a pointer to the already existing array (instead of a copy of its contents).
The same goes for dictionaries and Object references (Nodes, Resources etc.).

Every other type is passed by value (= copies the value to a new memory address).

2 Likes

I see! Is there any way to clone the contents of an array? I can’t seem to figure it out.

Array.duplicate()

Are you sure you need to?

Um, yes, because I need to change the inputs to “Left” and “Right” from “Forward” and “Backward” in order to make them work independent of which side the character is facing. In my code, all of the special inputs are stored in a separate script attached to a node which is a child of this node. (Allowing me to have a separate list for each character) This means that the inputs have to be translated on the fly based on which way the character is facing.

Thanks! That did the trick!

Use Array::map(). You won’t need to loop and It will also create a duplicate for you:

if facing_right:
	target_chain = target_chain.map( func(x): return {"Forward": "Right", "Back": "Left"}[x] )
else:
	target_chain = target_chain.map( func(x): return {"Forward": "Left", "Back": "Right"}[x] )
1 Like