Value types are normally allocated on the stack. Primitive data types such as bools, ints, and floats are examples of Value types, but only if they're standalone and not a member of a Reference type. As soon as a primitive data types is contained within a Reference type, such as a class or an array, then it is implied that it is either too large for the stack or will need to survive longer than the current scope and must be allocated on the heap instead.
All of this can be best explained through examples. The following code will create an integer as a Value type that exists on the stack only temporarily:
public class TestComponent : MonoBehaviour {
void Start() {
int data = 5; // allocated on the stack
DoSomething(data);
} // integer is deallocated from the stack here
}
As soon as the
Start()
method ends, then the integer is deallocated from the stack. This is essentially a free operation since, as mentioned previously, it doesn't bother doing any cleanup; it just moves the stack pointer back to the previous memory location in the call stack. Any future stack allocations simply overwrite the old data. Most importantly, no heap allocation took place to create the data, and so, the Garbage Collector would be completely unaware of its existence.
But, if we created an integer as a member variable of the
MonoBehaviour
class definition, then it is now contained within a Reference type (a class) and must be allocated on the heap along with its container:
public class TestComponent : MonoBehaviour {
private int _data = 5;
void Start() {
DoSomething(_data);
}
}
Similarly, if we put the integer into an independent class, then the rules for Reference types still apply, and the object is allocated on the heap:
public class TestData {
public int data = 5;
}
public class TestComponent : MonoBehaviour {
void Start() {
TestData dataObj = new TestData(); // allocated on the heap
DoSomething(dataObj.data);
} // 'dataObj' is not deallocated here, but it will become a candidate during the next garbage collection
}
So, there is a big difference between temporarily allocating memory within a class method and storing long-term data in a class' member data. In both cases, we're using a Reference type (a class) to store the data, which means it can be referenced elsewhere.