-
-
Notifications
You must be signed in to change notification settings - Fork 97
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add static variables in GDScript #6156
Comments
For a preliminary implementation, we can also just let users manage memory themselves: if they want to free memory used up by static variables, they can just do |
I don't care much for unloading, as all my use cases need persistent data, and indeed I can clear the unused bits myself as needed. That said, out of those two options, the method one seems simpler to use situationally, and an extra annotation can always be added later. |
You forgot the most cumbersome of them all, which is still available in 4.0 btw. |
It's not only static variables, you may have other data that you cannot clear without unloading the script (mainly with static var forever = 0
func _ready():
var scene = preload("res://super_big_scene.tscn")
add_child(scene.instantiate()) In this case, while the static variable is negligible memory-wise, the preloaded scene will still be attached to the script and there is no way you can unload it unless we add special means for it. |
Maybe store the static variables of all scripts in a central repository independently from the script? Some kind of dictionary maybe? This implementation would bypass the whole baggage of having to keep the script loaded. You could unload the script at any time and after reloading it can use the still available data from the repository. This would also avoid the need for any kind of special treatment or clean up function. To remove the data from memory you could just assign null to the variable. |
I feel like this would be quite complex to implement and maintain. In particular keeping a valid connection between script and its static variables even when reloaded, especially considering there are built-in scripts (present in a scene file) and scripts created at runtime. |
Non-static variable initializers do not have to be constant expressions, you can call methods. If this applies to static variables as well, then this can be worked around like this: static var _class_loaded := _static_init()
static func _static_init() -> bool:
# Your code here.
return true In this case, it makes sense to add a standard "static constructor" with a name that reflects that this method is not called when the application starts, but when the script is loaded. |
What I meant is that there is no custom static constructor. But the implementation does require an internal static constructor in order to properly execute the initializers (since they're not constant). Given this, it would be easy to allow custom static constructors as well and just call it from the internal one. |
Maybe also add a static signal? |
@4d49 this is a different beast to tackle. If you need it you should open a proposal specifically about it. |
Unfortunately, this proposal is silent about the order of static initialization. The C++ standard has the same omission, leading to the Static Initialization Order Fiasco. If script B's |
@ttencate given GDScript has a single official implementation, it is not as dependent of a standard as C++. Also, it does not really have the concept of "translation unit" like C++ does, so the order is always consistent.
If The only issue is if there is a dependency cycle. If |
I'm curious what the real world use case of this ever was. I see a lot of hypotheticals. ( Maybe I missed something ) |
Describe the project you are working on
GDScript.
Describe the problem or limitation you are having in your project
There's no practical way to share data across the instances of the same class. The available solutions to this problem are cumbersome to use:
const
Dictionary and edit its values.Singleton.data
) instead of directly (data
).This makes autoloads the only way to store global data which can be cumbersome if you want them to be tied to a particular class. Given autoloads are always Nodes, it limits what you can do even if you are okay with using the same class as an autoload and as a base for other instances.
Many users in favor of static variables were against having to use autoloads for this.
Previous proposals for a feature like this:
Describe the feature / enhancement and how it helps to overcome the problem or limitation
Static variables provide a cleaner way to achieve global data, in particular when the data is pertinent to different instances of the same class.
Syntax:
They can be used by static functions as well.
That is also available for inner classes:
There is no static constructor, so to have a value initialized when the script is loaded, you have to assign on the declaration (e.g.
static var x = "here"
). Those will be set when the script is loaded.Static variables can also be typed:
Once you use a
static var
in your class, it will not be unloaded until the application exits. This guarantees that the values stored in static variables aren't lost by accident. It also means that you are preloading heavy resources in a script with static variables (even if the preload isn't on a static variable itself) it will occupy memory until the game is closed. If an inner class has a static variable, its outermost script (the file it's defined in) will be kept loaded. This will be done by a list inGDScriptCache
that will keep a reference to those scripts so they stay alive.To solve this I have two proposals (not mutually exclusive):
1) Have a method in GDScript to unload scripts with static variables. E.g.
This method will not immediately unload the class. It will simply remove the reference from
GDScriptCache
so it can be freed once nothing else references it. The name of this method can be different to better reflect what it does.Note that if the class is loaded again, it will need another call to
unload_static()
if you want it to be freed.2) Have an annotation that makes a script not stay in memory. This essentially makes the script behaves as if it doesn't have any static variable. E.g.
This can be used if you don't care about losing the data in static variables and don't want to manage the memory manually. Again, name is not final.
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
Static variables will use a similar code to what is used for constants in GDScript, with the difference that they will allow being assigned to.
A list of scripts to be kept alive will be added to
GDScriptCache
, along with methods to add/remove items from the list. The GDScript compiler will detect usage of static variables to decide whether the script should be in the list or not (as well as the annotation), and proceed to store it in the cache if necessary.The
unload_stack()
method will simply remove the reference to itself from theGDScriptCache
. If no other reference is alive, this will proceed to free the script object.If this enhancement will not be used often, can it be worked around with a few lines of script?
The only available work around is to use autoloads, which does limit how this can be used. It becomes cumbersome if needed often.
Is there a reason why this should be core and not an add-on in the asset library?
It must be implemented in the core given it's part of the GDScript syntax.
The text was updated successfully, but these errors were encountered: