The AHK scripting language has this really cool feature that allows to point to a variable or function by using a string variable - it's done very easily and simply by just encapsulating it in % signs.
This creates many different possibilities to cut down the number of lines needed to do different scenarios.
here is a case example:
if( PLAYERSTATE == "ground"):
ground_state()
elif( PLAYERSTATE == "air"):
air_state()
elif( PLAYERSTATE == "wall"):
wall_state()
elif( PLAYERSTATE == "jump"):
jump_state()
elif( PLAYERSTATE == "die"):
die_state()
elif( PLAYERSTATE == "respawn"):
respawn_state()
elif( PLAYERSTATE == "jump_pad"):
jump_pad_state()
With the feature the same code could instead be done with only one line:
##We are using the PLAYERSTATE variable in order to decide what function to execute
%PLAYERSTATE%_state()
Alternatively the same can be used for dynamically altering variables!
in gdscript without the feature:
func addAmmo(ammoAmmount,ammoType):
if ammoType == "bombs":
bombs += ammoAmmount
elif ammoType == "gunBullets":
gunBullets+= ammoAmmount
elif ammoType == "rockets":
rockets+= ammoAmmount
elif ammoType == "knives":
knives+= ammoAmmount
elif ammoType == "ninjaStars":
ninjaStars+= ammoAmmount
elif ammoType == "andSoOn":
andSoOn+= ammoAmmount
elif ammoType == "youGetTheIdea":
youGetTheIdea+= ammoAmmount
Same thing in just one line of code:
func addAmmo(ammoAmmount,ammoType):
%ammoType% += ammoAmmount
If Gdscript has this killer feature, just think of how much faster we can write games with it on gamejams! :D
You could use a dictionary for that
func addAmmo(ammoAmount,ammoType):
ammo[ammoType] += ammoAmount
@BeayemX That is true, and you can do it that way in AHK too if you want to.
However that would imply that you are using dictionaries to begin with - which is not something everyone would do in all scenarios. Having the ability to do that with any variable can be very powerful and lets you code in a simpler style - it adds some extra flexibility. The ammo example is not the best, because you are right - it would be good to keep that stuff in a dictionary for the load/save system.
The feature I am actually more interested in is the first case scenario - using it to trigger a function. It is going to save quite a lot of these if-else lines - resulting in much cleaner code
Not even gml script has this. Game maker tries to do this via a somewhat limited custom method, which again forces the programmer to structure their code in a very specific way:
https://docs.yoyogames.com/source/dadiospice/002_reference/miscellaneous/script_execute.html
I think you can do it by call(PLAYERSTATE + "_state")
Same for member variables:
set(PLAYERSTATE + "_active", true)
for the variable...
var aa = 1
var bb = 2
var cc = 3
func _ready():
add_to("aa", 1)
add_to("bb", 1)
add_to("cc", 1)
printt(aa,bb,cc)
func add_to(var_name, p_value):
set(var_name, get(var_name) + p_value)
@volzhs @Zylann Thank you guys, I didn't know about these functions.
I guess my request then can only be for some syntax sugar in order to make theam easier to use and understand. Godot technicaly already has the functionality
In order to do these things in AHK, you only need to know about the %string% concept.
To do them in gdscript, you need to know about call and set.
func add_to(var_name, p_value):
%var_name% = p_value
is much simpler and takes less typing than
func add_to(var_name, p_value):
set(var_name, get(var_name) + p_value)
If you see it as something that doesn't really fit within gdscript's design, I guess I will close this request. These functions are going to be really handy - I wonder why none of the popular examples and demo games in gdscript use them and people still write loads of repetitive if else code
reminds me what @akien-mga said...
Too much sugar causes health issues..
Well, this is not exactly a good practice because it can lead to runtime errors if you change/remove functions and fail to update the strings. Calling the functions directly would cause parse/compile errors which are easier to catch.
If you're going this route I would advise to at least have some has_method
call that triggers an error so it doesn't bite you in the back.
@vnen yeah that is true.
I guess either way (with or without sugar) - we will always have to be careful not call a non-existent function or set a non-defined variable - but that is a pretty easy to debug problem
The goal of having the sugar is to make it more intuitive and easier to discover by people learning gdscript.
Even ndee, who is quite experienced in gdscript didn't use call() when making the popular gbot tutorial.
https://github.com/ndee85/gBot/blob/master/projectfolder/scripts/gbot.gd
I would argue that it also leads to easier to read code. The set() and get() method is certainly not as straightforward as just %setVar% += n
if that stuff sounds messy to actual godot contributors though - I guess it's not the best idea ever. It certainly works great for AHK scripters
The idea is not new, there's the concept of "variable variables" on many languages. I just think that the sugar syntax is out-of-place for GDScript.
The goal of having the sugar is to make it more intuitive and easier to discover by people learning gdscript.
I would say it leads to the opposite. People who didn't find call()
or set()
might not find this syntax either. When you're reading, if you see %PLAYERSTATE%_state()
you have too look at the docs to know what's this %
syntax, while reading call(PLAYERSTATE + "_state")
is clear on its own.
putting aside the sugar part of it, do you think there is anything to be gained from having variable variables in gdscript?
I personally like them a lot, but it's a matter of personal preference
I never used variable variables (in all languages I know). I use dictionaries and objects, it's much clearer, faster, maintainable and often structurally closer to the actual concept to implement.
I don't want this kind of syntax in GDScript, because:
1) You can use set()
and call()
already (for class members only, but variable variables are less useful in the local scope where you can simply use a dictionary).
2) They can lead to "dangerous" code, especially if you are dereferencing many levels, or using it for array variables.
3) It's a complication for the GDScript VM, which will need to do multiple hops to get the final value (not to mention the trouble of actually implementing it).
Hi Everyone,
Thank you for showing me these very useful methods. Knowing about them now solves what I initially wanted- even if not in the way I am used to.
Seeing as to how unfavorable variable variables are, I think it would be better to close this issue now.
Much thanks to everyone who took the time to contribute to the discussion
Most helpful comment
I think you can do it by
call(PLAYERSTATE + "_state")