• 3D
  • [SOLVED] Help me understand references and objects in GDScript

Hi there,

Considering this simple code in GDScript:


var basis = Basis(Vector3.ZERO)
var origin = Vector3(1, 2, 3)
	
var t1 = Transform(basis, origin)
	
var t2 = Transform(t1.basis, t1.origin)
t2.origin.z = -3
	
print("t1.origin = " + str(t1.origin))
print("t2.origin = " + str(t2.origin))

The result is :


t1.origin = (1, 2, 3)
t2.origin = (1, 2, -3)

In a programming language like Ruby, t2.origin should reference t1.origin because you pass the arguments as references in the constructor.

In Ruby it would be :

! class Vector3 ! attr_accessor :x, :y, :z ! def initialize(x, y, z) ! @x = x ! @y = y ! @z = z ! end !
! def to_s ! "(#{x},#{y},#{z})" ! end ! end !
! class Basis ! attr_accessor :vector ! def initialize(vector) ! @vector = vector ! end ! end !
! class Transform ! attr_accessor :basis, :origin ! def initialize(basis, origin) ! @basis = basis ! @origin = origin ! end ! end !
! basis = Basis.new(Vector3.new(0, 0, 0)) ! origin = Vector3.new(1, 2, 3) !
! t1 = Transform.new(basis, origin) !
! t2 = Transform.new(t1.basis, t1.origin) ! t2.origin.z = -3 !
! puts "t1.origin = #{t1.origin}" ! puts "t2.origin = #{t2.origin}"

But here, the output is as expected :

t1.origin = (1,2,-3)
t2.origin = (1,2,-3)

So what's the difference in GDScript in terms of implementation?

Actually, Vectors are base types in Godot and therefore copied instead of referenced. See here: https://docs.godotengine.org/en/3.2/getting_started/scripting/gdscript/gdscript_advanced.html#pointers-referencing

That said I don't think that everything else remains a reference when it is assigned to attributes/constructors of Godots built-in Classes. Also because some attributes are derived from others.

I just tested it to be sure.

This code moves some spatial called "MeshInstance" to x+1.

func _on_Button_pressed():
	var trans = Transform()
	trans.origin=$MeshInstance.transform.origin
	trans.origin.x+=1
	$MeshInstance.transform=trans

And this code might do the same, but it doesn't:

func _on_Button_pressed():
	var trans = Transform()
	trans.origin=$MeshInstance.transform.origin
	$MeshInstance.transform=trans
	trans.origin.x+=1

So I'd say that the transform is copied at the time it is assigned to the transform attribute of the Spatial because it doesn't change when the instance which was assigned to the attribute is changed later.

Ok I'll look at the documentation on the subject, thanks for your answer!