-
-
Notifications
You must be signed in to change notification settings - Fork 21.3k
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
'static var' to go with 'static func' #6840
Comments
This is not C, care to explain what they would have that a normal global scope var wouldn't have? |
I disagree -- thinking without global variables makes things much cleaner. |
Global vars are a tempting plague IMO, they always bite you back. Also, the documentation states it's because of thread-safety: http://docs.godotengine.org/en/latest/reference/gdscript.html?highlight=static#classes If you really need global variables, you can have a look at auto-load scripts: http://docs.godotengine.org/en/latest/tutorials/step_by_step/singletons_autoload.html |
i am confused by this thread. :-) i don't want globals. i want class-level-variables. (of course on the other hand i agree that objects are little computers and class level variables as well as instance members are all in a sense global from the perspective of the methods, so "global" as a pejorative is true depending on what level of scale one is talking about.) i might be utterly misunderstanding what static means in gdscript but it looks to me more like class-members instead of the c static keyword. oh wait i am misunderstanding... (i see the bit about thread safety but actually how that reads is "we'll take away something you would expect to have especially since there's static functions, because our internal workings are too mysterious and haven't been thought out well enough to let static variables exist.) so now that i see the example at http://docs.godotengine.org/en/latest/reference/gdscript.html#classes i am super confused. :-) well super surprised anyway. to quote the hhgtth: "this is obviously some new meaning of the word static i wasn't previously aware of..." it might work such that i can do what i wanted to do in the first place :-) |
Isn't this sufficient?
or
Those are "class-level" variables as far as I understand. Would you give an example of what you're looking for exactly? |
Class-level static variables are globals. More specifically, they store a global state independent of any object. Any reason why you can't use autoloads for this? |
With class levels mean those variables that belongs to a class (globals for the class), not to instances or any scope, these are used sometimes like for global behaviour change or static pool of things. Of course that tends to make a mess here and there, autoload scripts or nodes can be better organized and call groups for mass changes. Is kind of pointless for the way Godot works but could be nice to have them as option some day. |
What about just using |
First of all thank you for your report and sorry for the delay. We released Godot 3.0 in January 2018 after 18 months of work, fixing many old issues either directly, or by obsoleting/replacing the features they were referring to. We still have hundreds of issues whose relevance/reproducibility needs to be checked against the current stable version, and that's where you can help us. For bug reports, please also make sure that the issue contains detailed steps to reproduce the bug and, if possible, a zipped project that can be used to reproduce it right away. This greatly speeds up debugging and bugfixing tasks for our contributors. Our Bugsquad will review this issue more in-depth in 15 days, and potentially close it if its relevance could not be confirmed. Thanks in advance. Note: This message is being copy-pasted to many "stale" issues (90+ days without activity). It might happen that it is not meaningful for this specific issue or appears oblivious of the issue's context, if so please comment to notify the Bugsquad about it. |
I have the feeling @raould 's idea is not understood well, for example I have a function for calculating perlin noise here which starts with:
The problem here is whenever I call this function it has to create the variable p , then removes it from memory after finish, however I am calling this function very frequently, but this function is taking almost 1 seconds to finish, I am trying to optimize the function , first thing came to my mind is, remove the variable out side of the function, which does NOT make it global variable, it still will be static variable belongs to the class, the thing is, at least my IDE is not allowing me to define
So so far I don't see the point of implementing new script language with custom grammer, but it would be an improvement to allow static variables |
@bevinhex why not use a In any case, if you need local state, create a new object. I don't see it a problem to use objects when you need more persistent data. |
@vnen, seems to be working as you said, I thought I tried const already, anyway as long as const is "static", I sure can use it in my case, |
Something like that looks good for a custom resource more than a constant/static value, for a more godotish approach. |
@bevinhex |
That is whould be one way of "workaround" , we do have workarounds to share some variable between static functions, but to be honest, to most programmers, it feels natural to want to try to use static variables for sharing data between static functions, I can use const to represent data for the static functions in my case, but when it comes to variables, I cannot just define it similar way
I think we kind of can put 'static variable' feature to somewhere as proposition for gdscript, maybe low priority, since we have workarounds. |
Why is it a workaround? It's not |
So unless I put the static class in autoload , the class I use gets unloaded when I switch scene, so it does not make sense to have static variable? if that is the case, true, static variables messes thing up a bit, unless static variables made to stays in memory and does not get unload. |
If static vars are made part of the script, then yes: they'll be destroyed as soon as the script is unloaded (which is very easy to happen, if you don't have persistent references to it). Thread safety also gets in the way. There's no true concept of "Global" in Godot (in userland at least). Autoload is not truly global, it's just added to the scene tree. So adding persistent static variables would require a new setup just for that, which IMO is not worth it. If you need persistent state that is always available, just make an autoload. |
@vnen I don't think there's trouble with static vars about the life cycle of the script. If we want to access a static variable we have to get the script instance first (A variable that persistent references to it or a variable just preloaded). That will keep the script is not freed so the static variables should be OK. Maybe I forgot something or something mis-understand. But the static variable is really an important feature to make the language better for organizations. |
With named scripts, static vars may be finally useful. |
If that's the case then it's not so "static" anymore. The idea of having static variables is to not have to create any instance.
Well, only if you keep the instance forever. But that does not really solve the problem, because users will most likely be unaware of this requirement and will get unexpected behavior. If that's a valid solution you don't even need instances, just keep a reference to the script resource. Also, I think the most problematic issue is thread safety. IINM this is why static variables were never introduced.
I'm not sure about that. It feels to me that it's replacing the use of a singleton. In which case it's much simpler and safer to use an autoload. |
Static vars will allow to make real singletons, autoloaded scripts and scenes are not singletons and won't be replaced by one (because are used in the tree), it may also help to translate quickly structures from other engines/frameworks. |
In fact we don't need something so static like other programing languages. But we really need a way to share variables in same class. For now only constants can be shared. Here is an example of the static variable usecase: Time.gd const _iso_datetime_regex = null # private static variable
# Parse ISO datetime string to a datetime dictionary
# - - - - - - - - - -
# *Parameters*
# * [datetime: String] ISO formated datetime text
# - - - - - - - - - -
# *Returns* Dictionary
# * Return the datetime dictionary
# * Return `ERR_PARSE_ERROR` if parse failed
static func parse_iso_datetime(datetime):
if _iso_datetime_regex == null:
_iso_datetime_regex = RegEx.new()
_iso_datetime_regex.compile("^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(.[0-9]+)?(Z)?$")
var result = _iso_datetime_regex.search(datetime)
if result.strings.size() >= 7:
return {
'year': int(result.strings[1]),
'month': int(result.strings[2]),
'day': int(result.strings[3]),
'hour': int(result.strings[4]),
'minute': int(result.strings[5]),
'second': int(result.strings[6]),
}
return ERR_PARSE_ERROR I use this method in following way const Time = preload('time.gd')
func _ready():
var time = Time.parse_iso_datetime('2018-08-25T02:17:26Z')
I don't think there are too much differences between static variables and constants in GDScript. If they are both stored in the |
Because thread safety becomes a concern when a variable can change. Constants don't change. |
I talked to @reduz and he said static variables aren't available to encourage the use of singletons. He proposed to add a system similar to the autoload that doesn't require the script to be a Node (so they wouldn't need to be on the tree). That is my preference as well. |
@vnen: Really nice idea. |
Did a short test on 3.0.6 since you can change the value of constants there. It seems there's not a problem changing the value from multiple threads (apparently Object has a locking mechanism). However, losing the reference to the script makes the value reset as expected. This is really a problem if you expect static variables to "just work". A singleton in this case would be much more useful because the engine keeps the reference for you. |
I'm trying to create data types inside of GDScript, and the non-existence of static vars makes it impossible to create pre-set objects like
But I think that currently the closest equivalent is this:
|
@aaronfranke I think it should be doable this way: one.gd class_name MyVector3
const one = Vector3(1, 1, 1) |
Hi @Zylann, quick question: |
@ericdsw it's intended. If a variable is always the same there is no reason to copy it in every instance, so it happens to be available without an instance, which is actually useful too (same happens in C#). |
extends Resource
class_name MyDataClass
var _data
func _init(data) -> void: _data = data
func get_data(): return _data extends Node2D
class_name Main
const data = MyDataClass.new(1) Last line produces an error: And to the autoload - it is a very cumbersome "solution" for libraries, telling users they must add this things to autoload. It should be, in my opinion, possible to specify this from code. PS: From a user perspective, autoloaded singleton contains global variables anyway... |
@mnn the thing with |
Was wondering about other languages and it would seem #include <iostream>
using namespace std;
struct MyData {
int data;
};
const auto myData = MyData{1};
int main() {
cout << myData.data; // ok
// compilation error: assignment of member ‘MyData::data’ in read-only object
myData.data = 4;
return 0;
} I find it a bit strange that a dynamic language like GDScript has
Eh, I found it hard to believe this, but apparently it's correct: const data = {a = 1}
func _init() -> void:
data.a = 2
print("data.a = %s" % data.a) it successfully compiles (even though |
Further discussion about the behavior of |
@mnn Yes it works but this is not a perfect way. The member of the |
My use case is that I have a list of packet classes, and I want to assign IDs to them at runtime so that later I can insert classes between others without changing the IDs. With any kind of static vars, I could assign them in a loop to an "id" field in the classes. |
I have a few performance counters I want to update across all instances of my class. |
I'll close this issue as we've decided not to implement static variables. Quoting @reduz on IRC:
(Remember that Godot supports live script editing and reloading.) Moreover, there are also concerns about thread safety. As a result, implementing static variables in GDScript would likely prove more trouble than it's worth. A parent node or a singleton can provide similar functionality, but without the downsides of static variables (and without the added complexity of implementing them in Godot's codebase). |
@vnen Is this still in the plans? |
I do want to do it, just not sure when. |
I am working in a project that is getting large fast. Because godot doesn't really do namespaces, autoloads (and class_name for that matter) quickly bloat the global space and make autocomplete lame and globally seize identifiers so they can never be used safely again. Static variables are nice cuz they are scoped. const __converter := []
static func get_converter() -> Converter:
if len(__converter) > 0: return __converter[0]
var c = Converter.new()
__converter.append(c)
return c |
Is that because the class |
Yeah, my converters are sub-classes that I use for some homespun json conversion. I only really put the static hack in the big class at the top that has a global name, so, yeah, it's should behave just like a lazy-init static var (Though I'd prefer a static constructor like C#.) class_name Binding
class Converter:
extends ObjectJsonConverter
func _init():
.with_property( "name", StringJsonConverter.new().with_default("unnamed") )
.with_property( "device_names", ArrayJsonConverter.new( StringJsonConverter.new() ) )
.with_property( "device_name_contains", ArrayJsonConverter.new( StringJsonConverter.new() ) )
.with_property( "binding_contexts", DictionaryJsonConverter.new(
StringJsonConverter.new(),
BindingContext.Converter.new()
) ) |
Not sure why this is brought up again. I know you can find some uses for static variables, but it still have the same issue: a script may be unloaded and then the value is lost. So this cannot be implemented. It's a technical limitation. We could do this anyway. Then scripts would break (even if we document because people in general don't read docs) so we would get many complaints. We could cache all scripts with static values. Then you might be consuming a lot of memory if you abuse So we prefer to not do any of those and let users make some workaround, because at this point they'll have to be aware of limitation and consequences. I know it's not ideal but it's what we have. |
Yeah, I was mostly just sharing another workaround that wasn't too bad. |
Those are supposed to be constant. If you are relying on them to keep the state you changed it's up to you because there's no such guarantee. If we call them In any case, if anyone wants to ask for a feature or change of behavior they need to go the the proposals repository. |
Operating system or device - Godot version:
ubuntu 16.04 lts 64 bit
godot 2.1 stable
i would like to have static vars for use by my static func()s.
The text was updated successfully, but these errors were encountered: