Hello all!

Like most people I find myself a recent refugee from the Unity fiasco. I’ve been trying to prototype a project in Godot and I’ve been running into an issue I would think would be pretty easy to find a solution to as it seems to be a pretty fundamental building block of any project in Godot. Perhaps I’m misunderstanding how to accomplish this in Godot, but essentially I’m instantiating a number of tiles to be used for a grid system in my game. I want these tiles to be able to emit their index and transform values and then have other scripts pick this information up as needed. From what I’ve read signals are the way to do this, however whenever I try to send a signal with or without parameters nothing seems to happen. I seem to be able to connect to the signal just fine but the method doesn’t seem to be called.

Here’s an example of me defining the signal and then emitting it:

signal index_transform()

index_transform.emit()

And here’s how I am connecting and attempting to call the method in a secondary script:

func _ready() -> void:
	var hexGrid = get_node("/root/Main/Map/HexGrid")
	hexGrid.index_transform.connect(Callable(self, "_get_hex_index_transform"))

func _get_hex_index_transform():
	print("I'm Connected")

And when I’m passing parameters from what I understand I should only have to include the parameters like so:

signal index_transform(index, transform)

index_transform.emit(tile_index, tile_coordinates)
func _ready() -> void:
	var hexGrid = get_node("/root/Main/Map/HexGrid")
	hexGrid.index_transform.connect(Callable(self, "_get_hex_index_transform"))

func _get_hex_index_transform(index, transform):
	print("I'm Connected")
	print("INDEX: ", index," POS: ", transform)

However neither of these seem to work. What am I doing wrong?

  • plixelOP
    link
    fedilink
    arrow-up
    1
    ·
    1 year ago

    Is this the intended purpose for signals? Moving info up and down the tree? If so how are we supposed to send information from one script to another if one is not directly a child of the other? Do we send it to a shared parent node then send the info back down to the secondary script?

    • Rodeo@lemmy.ca
      link
      fedilink
      arrow-up
      3
      ·
      1 year ago

      I don’t know if it the intended purpose, but it’s a very useful one.

      If so how are we supposed to send information from one script to another if one is not directly a child of the other?

      Signals are good for that. It’s just generally easier to maintain than many calls to get_node. Signals help to decouple a scene from other scenes, so when you instantiate it you just connect the signals to some callbacks that can be in any script anywhere. If you use get_node all the time you end up having one scene relying on a specific node hierarchy in another scene, which is just a big headache.

      • plixelOP
        link
        fedilink
        English
        arrow-up
        1
        ·
        edit-2
        1 year ago

        I see okay so I understand that the intent is to decouple scenes from each other, however from the tutorials I’ve seen they typically say that to establish the connection you need to run get_node() from the script you are establishing the connection to. So for example if you have:

        *Parent
            **Child 1
            **Child 2
        

        You would emit from Child1, then establish the connection from Child2 using:

        var script = get_node("root/Parent/Child1")
        script.some_signal.connect(some_function)
        

        Is that the correct interpretation? Or am I misunderstanding? Thanks in advance btw I appreciate all the help in understanding this!

        • @plixel @Rodeo if the parent is creating the children at runtime then that’s the time to connect signals in code.

          If the child already exists as part of the parent’s scene you could connect it’s signals in the editor (built-in signals or your own signals). Then in code just run singal_name.emit(args) when needed. You can still connect them in code if you want [e.g. iterate over get_children()].

        • crei0@mastodon.gamedev.place
          link
          fedilink
          arrow-up
          2
          arrow-down
          1
          ·
          1 year ago

          @plixel @Rodeo
          The way I’m doing in my game is by

          1. Using a Signals.gd script

          2. Add that script to Project settings > Autoload, this makes the script globally accessible (singleton)

          3. Then from the scene I want to send the signal, I do
            Signals.my_signal_was_triggered.emit()

          4. Then on the scene/node (can by multiple) I want to receive the signal emission, I do
            Signals.my_signal_was_triggered.connect(my_function)

          5. Create the function “my_function”

          • Rodeo@lemmy.ca
            link
            fedilink
            arrow-up
            2
            ·
            1 year ago

            This works but now your signals are not part of the class which they act for, and are also in global scope rather than scoped within the class they belong to.

            Generally it’s a good idea to keep everything in the smallest scope possible. But this can work for smaller projects where the total number of signals is manageable on its own.

    • leprasmurf@lemmy.geekforbes.com
      link
      fedilink
      arrow-up
      2
      ·
      1 year ago

      It’s a good rule of thumb, but Godot gives you enough rope to hang yourself with … at least until the next update 😀

      If you need to pass information around to different scripts and/or scenes then you may wish to employ Singletons.