Hey, so I started coding a few days ago, and even thought I have no problems applying this in practice, I don’t understand a certain part of it. I ll explain my thoughts below, and I would appreciate if you could correct and answer my questions along with it.
So, to get the location of the object, or change it´s location, you need to use transform.position (is this a method ?). However, this “method” returns three values - x, y, z, so it cannot be stored in a single data type variable, but you need a vector (in this case Vector3) to store all three values. So far probably everything good, but now you can use “vectorname”.x,y or z to access one of the values. What is “vectorname”.x thought ? And where is it stored ? Because if your vector is public and you type:
position = transform.position;
position.x += 1f;
Debug.Log(position.x);
you can see when “playing the game” that the value of x does not change, which makes sense, because the object stays in a single place, but what confuses me, is that if I add transform.position = position; it starts changing the location, because now it assigns new value to the transform.position "method, which is capable of actually changing the objects position. The thing is, where was the position.x value stored before adding the last line ? Is stored somewhere in the background, waiting to be assigned to something ?
Not sure if I got your question fully but, see this page:
It says: Vector3, struct in UnityEngine.
So it’s a struct and it’s value type, not reference like class. So if you do:
position = transform.position;
now position variable/field contains copy of transform’s position. So if you change position’s x, it is the only thing that changes, as it’s not the same as transform’s. Then if you do:
transform.position = position;
Now you apply the position to transform’s position, so it will have the same values as position. And the transform’s position is property, of type Vector3, so you can use it to set/get the Vector3 struct value:
A “method” is a function/subroutine. Where a function returns a value, and a subroutine does not. So these are methods:
public void Foo() //subroutine
{
//do stuff
}
public int Bar(int x, int y) //function
{
return x + y;
}
Note that “subroutine” (also known as ‘procedure’) is not really a common term these days. People will often just say function interchangeable for the two methods, and assume that Foo is a function that returns void. This more or less has to do with the historical lineage of C… C-like languages are some of the most popular, and C originally only had functions that had to always return something, but then added ‘void’ to make it syntactically consistent for subroutines/procedures. So thusly function out of popularity is often used interchangeably.
This is opposed to “fields”, which are class level variables. If you declare a variable as being part of the class, that is a field.
public class FooClass
{
public int Value; //this is a field
}
A “property” (which is what the “transform.position” is) is in between a field and a method. It gives fields a method like nature, or a method a field like nature.
Basically it allows you to syntactically access data as if it were a field, but still have work done like a method.
public class FooClass
{
public float Credit;
public float Debit;
public float Balance { get { return Credit - Debit; } } //this is a property
}
When accessing the property it will look like a field:
var val = obj.Balance + 5f;
But work is being done (the subtraction).
You usually wouldn’t call a property a “method”. But it does have “method” like behaviours to it.
…
Now with that out of the way, lets move on to the bulk of your post’s question:
In memory.
It’s being stored in a spot in memory you’ve named “position”. To be cleaner and get rid of ambiguity of names, I’m going to rewrite your code like this:
Vector3 v = transform.position;
v.x += 1f;
Debug.Log(v.x);
In this case, the Vector3 is stored in memory with the label “v”. That location in memory is specifically on what is known as “the stack”. Since this variable in my example is inline in what would be a method, that means all memory needed for the method gets allocated on “the stack”. It’s just a continuous block of memory that the program runs on.
Basically every time you call a method, what is actually going on is that a chunk of memory large enough to hold everything needed by the method is allocated. The amount of memory is basically all of the variables that are used in the method. Then a jump command occurs that goes to the code where the method is defined, it operates on the memory at the top of the stack.
If it calls any methods, those get placed on top of this method’s memory. Hence the name “stack”, you’re stacking blocks of memory on one another.
Once a method returns/ends, the memory needed for it is “popped” off the top of the stack.
If too many methods are called filling up the entirity of allowed memory for the stack… this is called a “stack overflow”, I’ve bet you’ve heard this before. See when the program starts it allocates a large chunk of memory to act as its stack. If you go out of bounds of that memory, you’ve overflowed the stack… you started entering memory outside of the designated range.
It’s kind of like if you had a desk on which you did work, and you kept lining up paperwork on it until you reached the edge of the desk. You’ve overflowed your desk.
…
Now NOT ALL DATA ends up on the stack. Only value types do, like int, float, bool. Vector3 is a struct, so it also can be on the stack (though doesn’t have to be on the stack). Classes on the other hand are “reference types” and they get placed in what is called “the heap”. The heap is an even larger unordered block of memory that acts as a big scratch area for reference objects.
If in your method you say something like:
var obj = transform;
Well obj as a variable will take up only enough memory to “point” at the object “transform” on the heap. It’s basically just an address handle (though there’s a bit more to it because C# is a managed language and therefore the so called reference needs extra meta data along with it). What it’s pointing at on the heap is a small contiguous block of memory that holds all the “fields” of that object. If the field is a value type, it’s just the value sitting in memory. If the field is a reference type, then there’s the same sort of “ref pointer” sitting in memory over on the heap that points to somewhere else on the heap that is that object.
SO, if you say this:
public class Foo : MonoBehaviour
{
private Vector3 v;
void Update()
{
v = transform.position;
v.x += 1f;
Debug.Log(v.ToString());
}
}
In this case because “v” is a field of “Foo”, it’s not on the stack. It is instead sitting over on the heap in the contiguous block of memory that represents this instance of “Foo”. That’s “where” it is located.
If you then say:
transform.position = v;
What’s going on is that you’re copying the value that is “v” from the “Foo” object over to the “transform” object elsewhere in memory.
Where THAT is… well, that gets even more complicated.
See if “transform” was a regular old C# object it’d be somewhere else on the heap.
But unfortunately, it’s not a regular old C# object. Instead it’s a reference to a Unity object found in unmanaged code within the game engine.
See… Unity uses C# as a “scripting language” on top of its game engine which is actually written in C++ and compiled for each machine. It then spins up a mono runtime (though this gets even more complicated depending the platform you target), and allows you to communicate between the mono runtime and the Unity runtime via these special intermediate objects like Transform, GameObject, etc. It’s kind of like 2 programs running side by side.
The ‘transform.position’ property isn’t a field. Rather it’s a “property” which calls into the Unity runtime and copies out the value from the memory Unity has allocated for itself, which is outside of the so called “stack and heap” of .net/mono.
OF COURSE
This gets complicated further if you use something like AOT or IL2CPP since that technically steps around the .net/mono memory model. In the case of IL2CPP the C# you write is converted into C++ code and then compiled (it’s in the name IL to CPP… where IL is intermediate language, which is what C# is compiled into for .net/mono, and CPP is C++).
…
TLDR;
your variable is not “in the background”, it’s just in a different location in memory.