In these programming languages, a class (which in Godot is is usually defined by a script) is a kind of template that tells the computer how to instantiate objects that belong to that class. The class itself doesn’t represent actual data, its just a description of what kind of data objects of that class will hold – in fact, the Godot documentation makes it clear that a class itself can’t hold any data members (while in C++, Python etc, there are class member variables - these don’t exist for Godot).
In practice, this means that you must instantiate a class, e.g. create an object based on the description the class provides, if you want to hold data. It’s the object that will hold the data, e.g. that holds actual values for all the properties/member variables you defined. Every object you instantiate has the same properties/member variables, but none of them are shared.
When you write
var lives_left := 5
outside of a function in a script, you don’t tell Godot to create a global variable
lives_left and set it to 5; you’re telling Godot that when an object of this class / a node that uses this script gets instantiated, it will hold a property named
lives_left that is initialized with the value 5. If you create two instances, there will be two such properties, both initialized to 5, both independent from each other.
When you extend a class, you’re basically just saying that “my new class will hold these new member variables / properties IN ADDITION to those of the base class”. But just because two classes A and B extend the same base class C, that doesn’t mean that objects of A and objects of B will magically share the actual data in the properties/member variables you defined in C. How could they? All you do with that is say that these objects will have properties that are named the same. Objects (instances) of A and B are fully independent; every instance (object) of class A you create has its own full set of member variables/properties.
If you want to share data between different objects, what deaton64 suggests works, but it leads to strong coupling between your objects - they need to know about each others names in the scene tree, and they need to know about their internal makeup. That might not be such a good idea if your project starts growing; because one important idea of object-oriented programming is to reduce the amount of knowledge any object has about other objects.
A better solution to share data between two objects a & b instantiated from classes/scripts A and B might be to create a third class/script C, create an instance c and pass this instance to objects a and b in the _ready-function of a Node that contains both a and b. This way, a and b don’t need any knowledge about each other’s names; in fact they don’t need any knowledge about each other’s existence at all - they just need to know that there is an object c, instantiated from class C, which they receive when their parent object enters the scene tree ; and that this object c holds shared data that they have access to. That seems like a cleaner design to me. You might also want to look up singletons, which are a somewhat easier but less flexible way to share data between different parts of your application. But watch out; singletons are basically “global variables” and as such should be used reluctantly and with care. They seem to be an easy solution to many problems, but again, they tend to lead to tighter coupling of different parts of your code if you don’t watch out, and that’s really something you want to avoid as much as possible.