0 votes

Hello. In my project, I have an array of my custom class, SnakeInfo, shown here.

class SnakeInfo:

var x : float
var y : float

var dir : int
var type : int
var curve : int

func toVector2() -> Vector2 : return Vector2(x, y)

and the array

var bodyPositions : Array

Every element of the array is assigned with the type SnakeInfo, so, you can expect to access individual elements of my class snake info. bodyPositions[0] should return a value of type'SnakeInfo, which I can then edit the values of by using the . operator.
Like so: bodyPositions[0].curve = 15 or something like that.

The problem I'm having is this. In one of my functions, when I assign a variable of bodyPositions[0], I am also editing the value of bodyPositions[1] Tried and tested below:

bodyPositions[0].dir = direction
bodyPositions[0].type = TYPE.head
bodyPositions[0].curve = CURVE.noCurve

var beforeBug0 = bodyPositions[0].toVector2()
var beforeBug1 = bodyPositions[1].toVector2()

match direction:


            bodyPositions[0].y -= Global_Vars.sector


            bodyPositions[0].y += Global_Vars.sector


            bodyPositions[0].x += Global_Vars.sector


            bodyPositions[0].x -= Global_Vars.sector

if bodyPositions[0].toVector2() == beforeBug0:

    # This branch doesn't execute
    print("bodyPositions[0] didnt change?")

if bodyPositions[1].toVector2() != beforeBug1:

    # This branch executes
    print("bodyPositions[1] changed???")

Here I only change the values of bodyPositions[0], but the values of bodyPositions[1] and bodyPositions[0] change at the same time. This was a nightmare to figure out where in my code this went wrong, and the result doesn't make any sense to me.

I wish to know why this happens, and how I can prevent this kind of bug from happening. Thanks for your time and help in advance

in Engine by (25 points)

did you initialize array? like var bodyPositions : Array = []

I did. In my initialization function, i initialize it, and I call that function from _ready(): Here it is below:

func _ready():

func initialize() -> void:

# Reset the snake body
while bodyPositions.size() > 0:


direction = DIRECTION.stopped

bodyPositions.append(SnakeInfo(bodyPositions[0].x, bodyPositions[0].y + Global_Vars.sector))

bodyPositions.append(SnakeInfo(bodyPositions[1].x, bodyPositions[1].y + Global_Vars.sector, DIRECTION.up, TYPE.tail))

The setRandHeadPos() function returns a new object of type SnakeInfo and is listed below

func setRandHeadPos() -> SnakeInfo:

# Set the x and y pos to a point on the game grid
var randX : int = rand.randi_range(leftR, rightR) * Global_Vars.sector
var randY : int = rand.randi_range(topR, bottomR) * Global_Vars.sector

# Return the random position
return SnakeInfo(randX, randY, DIRECTION.stopped, TYPE.head, CURVE.noCurve)

And here is the constructor that returns an object of type SnakeInfo

func SnakeInfo(x : float = 0, y : float = 0, dir : int = DIRECTION.up, type : int = TYPE.body, curve : int = CURVE.noCurve) -> SnakeInfo:

var snake = SnakeInfo.new()

snake.x = x
snake.y = y
snake.dir = dir
snake.type = type
snake.curve = curve

return snake

Additionally, initializing the array like you said var bodyPositions : Array = [] did not change the incorrect behavior at all

1 Answer

+1 vote
Best answer

I figured out my issue, and why. I read up on the array documentation on how godot stores arrays, and realized how bodyPositions[0] returns a reference to the object at array position 0, not a value. I come from a c++ background, and usually assigning array[0] = array[1] is completely fine and viable. However, in godot that same statement assigns the reference at array[0]with a reference to the element at array[1]. Meaning every assignment was changing both values, haha.

I fixed it by creating a copy by value function for my class, and then using that when necessary instead of the default copy assignment. Thanks to those who were confused at my problem, but tried to find out the solution anyways~!

by (25 points)
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.