I'm not sure if there is a word for this, so I may be asking this question in a terrible way. Is there a way to specify what function you want to call using a variable? Like making a variable read as code? What I want is, IE, if you had a function named bake_muffins():

var funcname = "bake_muffins"
get_parent.funcname()

I know that this sounds kinda niche, and could be done in other ways such as a large if-then tree like:

var funcname = "bake_muffins"
if funcname == "bake_cookies":
  get_parent.bake_cookies()
if funcname == "bake_cake":
 get_parent.bake_cake()
if funcname == "bake_muffins":
    get_parent.bake_muffins()

But I'm not just baking cookies, cake, or muffins, I'm baking so many things it would put Duff Goldman to shame and require thousands of lines of the above to check them all, and I want to decide what I want to bake in a dynamic way either through complex situations dependent on the specific alignment of dozens of other variables, or would also like to be able to do so through a variable exported to the editor.

Yes, but you have to set the specific function as a variable:

var funcname_variable = get_parent().funcname()

After that, if you call funcname_variable it will call the assigned function instead. Sorry for not quoting the code, but anyhow the forum does not let me. :-(

You can use a FuncRef (documentation, GDScript function) to assign a function to a variable, which I think is what you are trying to achieve?

Then from there you could bind different functions to the FuncRef so that it would call the function you need at the time. Using the example above, you could do something like this:

# Assuming this is a base class or something
var bake_function = funcref(self, "bake");
var is_cake = true;

func _ready():
	if (is_cake == true):
		bake_function = funcref(self, "bake_cake");
	bake_function.call_func()

func bake():
	print ("Baked something!");
func bake_cake():
	print ("Baked a cake!");

The nice part about using a FuncRef like this is that you don't have to know what function the FuncRef is pointing to.

Hopefully this helps!


@kryzmak said: Yes, but you have to set the specific function as a variable:

var funcname_variable = get_parent().funcname()

After that, if you call funcname_variable it will call the assigned function instead. Sorry for not quoting the code, but anyhow the forum does not let me. :-(

You should be able to quote code. There shouldn't be anything blocking it, or at least nothing that I am aware of. What happened that was not letting you quote the code?

Were you trying to format code in your post? If you were trying to format code in your post, did you indent the code with a single tab character? Or if it is a single line of code, you can add ` around it and then it will be formatted as a line of code.

@TwistedTwigleg Something is not working properly. I cannot preview neither I am able to edit my postings. As far as I remember there were always those nice buttons for quoting etc. in the past. But anyways this is going to be offtopic.

Edit: As always the problem is in front of the screen. Through the move to the new domain, I did not changed my script blocker settings. After unblocking Google Ajax API for this site, everything is working as expected. Stupid me. ;-)

Edit2: As I now read the documentation regarding FuncRef where it says that it is impossible to store functions as variables, I wonder why it then does work in my testings?

var test_var = test_func()

func _ready():
	test_var

func test_func():
	print("Why does this work?")
9 days later

@kryzmak said: Edit2: As I now read the documentation regarding FuncRef where it says that it is impossible to store functions as variables, I wonder why it then does work in my testings?

var test_var = test_func()

func _ready():
	test_var

func test_func():
	print("Why does this work?")

In tests that I did trying to make this all work, I had a similar thing happen. However, upon closer examination, it appears that test_func() is not being called during ready(), but actually being called up top at var test_var = test_func() . If you remove the test_var from ready(), it'll still result in test_func() being called and the print taking place.

@TwistedTwigleg said: You can use a FuncRef (documentation, GDScript function) to assign a function to a variable, which I think is what you are trying to achieve?

Then from there you could bind different functions to the FuncRef so that it would call the function you need at the time. Using the example above, you could do something like this:

# Assuming this is a base class or something
var bake_function = funcref(self, "bake");
var is_cake = true;

func _ready():
	if (is_cake == true):
		bake_function = funcref(self, "bake_cake");
	bake_function.call_func()

func bake():
	print ("Baked something!");
func bake_cake():
	print ("Baked a cake!");

The nice part about using a FuncRef like this is that you don't have to know what function the FuncRef is pointing to.

Hopefully this helps!

This helps. I'm building an engine for my game, not a game, right now. My goal in particular is to be able to call a function on IE parent Object A from child Object B, with Object B deciding which function that is without resorting to if-then statements. I now have this working, as follows, and would like to know if there is a way to do the following with only code on Object B:

On Object A we have:

#These variables must be declared or we get errors.
var dynamicfunctionname = ""
var dynamicfunction = funcref(self, dynamicfunctionname)
func updatedynamicfunctionname():
	dynamicfunction = funcref(self, dynamicfunctionname)
#The below three functions represent functions we may want to call.
func cookie():
	print("Cookies!")
func cake():
	print("Cake!")
func muffin():
	print("Muffins!")

On Object B (which happens to be a child of Object A just for the sake of this test, eventually I want to be able to reference other things than just parents but assume I can do it similarly to how I've done function names here):

export var dynamicfunctionname = ""
func _ready():
	get_parent().dynamicfunctionname = dynamicfunctionname
    get_parent().updatedynamicfunctionname()
func _process(delta):
	get_parent().dynamicfunction.call_func()

The result is if "cake", "cookie", or "muffin" is put into the exported string variable on Object B through the editor, the output is correctly flooded with the print for that function.

This does work, but makes it so that any object whose functions I want to be able to access remotely through Strings must have

var dynamicfunctionname = ""
var dynamicfunction = funcref(self, dynamicfunctionname)

and some sort of function I could call to update the dynamicfunction with the new name , like:

func updatedynamicfunctionname():
	dynamicfunction = funcref(self, dynamicfunctionname)

This is a moderately light-weight as a solution, I'm just wanting to know if I am missing anything simple that would allow me to avoid this. If I am understanding the requirements of funcref correctly, it would require adding the necessary variables remotely (both the funcref declaration, and the var String being used to point to the desired function.) Can variables be created on an object through pathing? Is there a way to modify the funcref for dynamicfunction on Object A from Object B? (This does not appear possible like a standard variable, IE get_parent().dynamicfunction = funcref(self, dynamicfunctionname), thus why I am having to pass it through a function on Object A, which may be better practice anyway but I'm trying to minimize.)

Meanwhile though, this all works fantastic of course if I am only concerned with accessing functions on Object B through variables defined on Object B, which alone is going to be extremely helpful, so thank you for the assistance!

@Zadck said: This helps. I'm building an engine for my game, not a game, right now. My goal in particular is to be able to call a function on IE parent Object A from child Object B, with Object B deciding which function that is without resorting to if-then statements. I now have this working, as follows, and would like to know if there is a way to do the following with only code on Object B: ... This is a moderately light-weight as a solution, I'm just wanting to know if I am missing anything simple that would allow me to avoid this. If I am understanding the requirements of funcref correctly, it would require adding the necessary variables remotely (both the funcref declaration, and the var String being used to point to the desired function.) Can variables be created on an object through pathing?

I'm a little confused on what you mean by "can variables be created on an object through pathing". Do you mind giving a pseudo code example? I'm just struggling to wrap my mind around it. I do not think it is any issue on your end, I'm just tired and my mind isn't working :lol:

That said, you might be able to simplify things a bit. If you know the function you want to call, you could try something like this:

Object A:

func cookie():
	print ("Cookies!");
func cake():
	print ("Cake!");
func muffin():
	print ("Muffins!");

Object B:

export var dynamicFunctionName = "";
var dynamicFuncRef = null;
func _ready():
	# Not required, but it is a good idea to make sure the function exists
	if (get_parent.has_method(dynamicFunctionName) == true):
		dynamicFuncRef = funcref(get_parent(), dynamicFunctionName);
	else:
		print ("Error: A function assigned to a node with Object B does not exist in Object A!");
func _process():
	if (dynamicFuncRef != null):
		dynamicFuncRef.call_func();

(I have not tested any of the code I have posted! I think it should work though)


Also, kinda on the side, but if you want to not use get_parent to attach the function, you can do something like this instead for Object B:

export var dynamicFunctionName = "";
export (NodePath) var target_nodepath;
var target_node = null;
var dynamicFuncRef = null;
func _ready():
	if (target_nodepath != null):
		target_node = get_node(target_nodepath);
	else:
		print ("Error: A Nodepath for a node with the Object B script has not been set!");

	if (target_node != null):
		if (target_node.has_method(dynamicFunctionName) == true):
			dynamicFuncRef = funcref(target_node, dynamicFunctionName);
		else:
			print ("Error: A function assigned to a node with Object B does not exist in Target node!");
func _process():
	if (dynamicFuncRef != null):
		dynamicFuncRef.call_func();

Then you can set the NodePath through the editor. :smile:


Is there a way to modify the funcref for dynamicfunction on Object A from Object B? (This does not appear possible like a standard variable, IE get_parent().dynamicfunction = funcref(self, dynamicfunctionname), thus why I am having to pass it through a function on Object A, which may be better practice anyway but I'm trying to minimize.)

Good question, and honestly I do not know, sorry!

Using get_parent().dynamicfunction = funcref(self, dynamicfunctionname) was in object B, correct? If so, and you are wanting to call a function in Object A, then you'd need to make sure the first argument in funcref is the object that you want to call the function on. So in theory, using get_parent().dynamicfunction = funcref(get_parent(), dynamicfunctionname) should work.

That said, I haven't tested and I've only used FuncRef a few times, so I'm mainly guessing.


Meanwhile though, this all works fantastic of course if I am only concerned with accessing functions on Object B through variables defined on Object B, which alone is going to be extremely helpful, so thank you for the assistance!

My pleasure! I'm glad I was able to be of some help. :smile:

4 years later