r/godot • • 7h ago

help me How can I call a method and dynamically add its required arguments?

Post image

Context: I created a Resource with a goal to be able to seek and call methods from other nodes (like on x thing happen, call this y method), in order to not have to manually add the code for each time I want it to happen. I was also able to make an array of the required arguments that the caller has, but I came to a roadblock when I try to pass arguments to the method. If one method has one required argument, but another has like three.

I was thinking of somehow making the code a string, which has the method's arguments placed inside (like in the screencap), but I dont know how to make it run. Anyone knows how to solve this?

11 Upvotes

18 comments sorted by

14

u/GieMou Godot Regular 7h ago

I'm not sure what you mean but I think you need a callable. A callable is a type that points to a function or method and you can do .call() to call it.

2

u/GieMou Godot Regular 7h ago

https://docs.godotengine.org/en/stable/classes/class_callable.html

Read through this page to see if it helps you. I'm happy to answer any questions if you need something

6

u/WilkerS1 Godot Regular 6h ago

Callable.bind(...) might also be what you're looking for if you need anything to do with queueing an argument. also works with signals.

2

u/SplatFelix 5h ago

I already am able to call a function that way. It works with a function without any arguments. My issue is that I need to be able to add the arguments depending on how many the function requires.

6

u/GieMou Godot Regular 5h ago

Callables have a .get_argument_count()

But I'll be honest I think your design is pretty bad and you should probably reconsider how your code should be structured

5

u/powertomato 7h ago

node.function.callv(your_array)

2

u/SplatFelix 5h ago

This could be it. I'll try this later

4

u/Silrar 6h ago

I'm not quite sure what you're trying to accomplish here. Calling methods by their stringname is not a good idea. It tells me that your coupling might be a bit too loose.

Have some clearly defined API between your systems that are allowed to be called to communicate across boundaries. Put your parameters into an argument object. That should be all you'll need, unless you're setting up a very fringe case I can't think of at the moment.

2

u/Craptastic19 4h ago

If you don’t know how many arguments to pass, how do you know what arguments to pass?

2

u/Comfortable-Book2477 3h ago

Something to do with Callables sounds like the right way to go.

https://docs.godotengine.org/en/stable/classes/class_callable.html

There is also the Expression class which I messed with once and soon realized I was doing something disgusting that tripled the amount of work I had to do compared to a different solution. I'm sure it has a use case but you would have to be doing something really weird.

https://docs.godotengine.org/en/stable/classes/class_expression.html

2

u/Rythim 6h ago

Sorry. I don't know how. I'm curious why you need this though. (Not criticizing, I really want to know under what scenario something like this would be needed)

1

u/badguygames Godot Regular 6h ago

One common scenario is so that data can hold the needed function name, instead of switching on names or types or whatever. You can also do calls in a single line using string concatenation based on different types instead of a switch or if elses.

2

u/Odd_Cow7028 3h ago

That doesn't really answer the question. If reusability is the concern, there are better mechanisms for handling that, including composition (create a node that does the thing you're tired of repeating), inheritance (create a base class that defines common behavior, then subclass different implementations), and interfaces (not explicit in Godot, but the pattern still works). Mix-and-match those, and you've got a pretty powerful toolkit for reusing code without resorting to janky data structures and string parsing to control program flow.

1

u/scintillatinator 3h ago

"On x thing happen, call this y method" sounds like a signal. You can connect many methods to one signal and emit it from other objects. Since they use Callables you can bind arguments to them too. This page on the docs has examples on how to do it.

1

u/JimBobTheGymGoer Godot Regular 48m ago

You're looking for .bind(), it fills in the arguments of the function, and gives you a callable that you can .call

1

u/Fragrant-Hunt-3955 46m ago

I would reconsider how you're proposing to solve the initial problem:
"to be able to seek and call methods from other nodes (like on x thing happen, call this y method".
Perhaps take a step back and consider providing more detail on the first problem.
then you will likely get a more reliable answer.

1

u/Much_Inspector_9447 33m ago

don't build it as a code string. i went down that path with Expression once and it tripled the work. if the resource already holds the arg array, Callable.callv(that_array) is the whole call. the annoying case was a method that always wants the node plus a varying tail, so i bind() the node when i create the callable and callv only the extra args. get_argument_count() is just a check before you fire it, it won't fill the list for you.

0

u/jazzFromMars 6h ago

I think you want something like this:

var func_num = 1

var func_name = "MyFunc_" + str(func_num)

# Construct a Callable tied to this instance (self)

var my_callable = Callable(self, func_name)

if my_callable.is_valid():

my_callable.call() # Can also pass arguments here: my_callable.call(arg1, arg2)