Vectors in Godot are value types, not reference types. Furthermore, they are not considered objects.
But since "object" might mean slightly different things depending on context, I'll be more specific... Vector2
is:
- A value type: a type such that the memory layout of the variables is the value, and not a reference to the value.
- A built-in type: a type that is provided as part of the language.
- A composite type: a type that can be decomposed into simpler values (withing the constraints of the language).
Furthermore, Vector2
is not an entity type. So when you compare instances of Vactor2
you are checking if they have the same value not if they are the same.
You might be wondering is Vector2
a class? And the answer is that it depends on what you mean. Vector2
is a C++ class (internally there is a Vector2
class in the source code of Godot), but it is not a script class (it is not a class as far as the type system exposed by Godot is concerned).
Now, as you know, in general an "object" is an instance of a class. So if instances of Vector2
are objects also depends on what you mean.
In fact, there is an Object
class, which is the root of the class hierarchy in Godot, so we will call "object" to any instance of a Object
or a class that extends Object
... And Vector2
is not a class (even if you consider it one, it does not extend Object
). Which is why I claim that vectors in Godot are not considered objects.
Can you make aliases of objects, or does it always make a brand new one?
There are reference types in Godot, Vector2
is not one. You cannot make a direct reference to a Vector2
. Yes, pointers are direct references. GDScript is a pointer free language.
Is it using pass-by-reference or pass-by-value when you call a function?
You pass by value. You cannot choose to pass by reference. And, again, Godot has both value types and reference types (so you can have a reference type passed by value).
You might work around this by passing the values inside of an Array
(Array
is a reference type, i.e. not a value type).
Do I need to worry about allocating tons of memory, whenever I set one object equal to another? Will this slow my game way down?
Depends on what you call "object"...
No, you don't have to worry about allocation when you are setting a variable to an instance of a reference type.
You might worry about some large composite value types, which would be the case of packed arrays (Packed*Array
are value types).
Or am I focusing on the wrong details, when I'm trying to optimize? I'm used to avoiding system calls and reusing old objects, but that may just be the wrong approach in Godot.
I suppose you remember what they say about premature optimization. With that out of the way...
Yes, using a built-in method (I mean, something from the standard library) will be more performant than doing it in a script. However, I believe it is useful to figuring out if you can save a few calls, for another reason: a common experience for Godot beginners is to implement something to later discover Godot already has it.
And yes, a lot of allocations can become a problem. However, you will find that you can iterate your design much faster if you don't worry about it. And once you have settled on your design, you can work on optimize it if it is necessary.
I want to note that you have a time budget, which is split between your scripts, rendering, physics, and a few other systems. As long as they complete in time, the user would not perceive a performance degradation. Thus, if you are not going over budget, it is harmless if the GDScript code is less than optimal. But don't forget that the hardware is also a factor.
So what's going on behind the scenes when I set one Vector2 equal to another?
This is a copy:
var vectorA := Vector2(1.0,0.0)
var vectorB := vectorA
Simple. Being these value types, there is no ref-counting, no pointer fiddling, no flagging... It is a true, honest, copy.
Furthermore, these are local variables, correct? In that case they will be freed when the method ends. You are not leaking anything. You are not adding pressure to a garbage collector. Nothing like that.
A few extra notes about Godot type system and memory management:
- All objects (instances of classes that are
Object
) are reference types.
- If they extend
RefCounted
they are... reference counted.
- Otherwise you free them manually.
- If they extend
Node
you can use queue_free
which will free them sometime in the future between frames.
- Otherwise you would free them deterministically with
free
.
- You could avoid a lot of
Node
allocations by working with server classes. But the code becomes more rigid. So, as I said above, iterate your design first, and afterwards see if you need this.
In fact, you will find that many game engines and frameworks - not only Godot - opt to have value type vectors (e.g. Vector2
), plus they will have ways to keep lists of vectors compact in memory (e.g. PackedVector2Array
). This makes it easier to move memory to the graphic back end, and this improvement in performance outweighs the losses caused by crating copies.
Finally, you could write C# or C++ for Godot which could potentially be more performant than GDScript (And I say potentially because bad code is bad regardless of language). Yet you can mix languages. So you can make your game in GDScript, and then port the parts that could use some extra performance.