2 levers 2 labels 1 signal ... help

Godot Version

4.3

Hi guys!

I am absolutely new to godot and returning to coding after a long time of stop after highschool.
At the moment i am tring to solve an issue:
I am learning the basics creating a simple 2d side scrolling platformer game.
I programmed a few scenes (from my player to some logic parts like a game manager and so on), after creating enemies, health, damage, etc etc i decided to start working on interactables.

I started watching a few tutorials, reading a bit of documentations and with these as a base i created a Lever scene which emits a custom signal alongside an @export var containing a ActivatorID.
I also created a TestLabel scene that also @export a variable called ReceiverID, i than instantiated (with the link button) both of them in my Level1, linked the signal of my lever to my label and made so that pulling the lever would toggle the label visibility only if the 2 IDs match… it works perfectly.

Than came the problem: i instantiated with the same button a second lever and a second label, changed the IDs but this new pair don’t work, because (i suppose) the second lever signal is not linked to anything, while the first lever signal is linked only to the first label… so both the 2nd lever and the second label (even swapping IDs) are doing anything

I would like to find a solution to implement multiple times in a level the same lever scene and link them to different interactables … (in this case just a label, but they might be doors, traps, spawners and so on)…

Any idea / guide? I can ofc post code, screen or whatever mgiht be helpful, ecause i understand that saying things this way might get confusing

Personally, for such a situation, I prefer to have an interface script, a dictionary export variable that keeps the IDs and nodes that receive them, and a signal that takes the ID, then in the script I check the ID and give it to the receiver, in this case, to send, it is enough to send its ID button inside the signal to the intermediary, and the interface on Its basis runs a function that specifies which node each ID should call.

For example, suppose we have two buttons 1 and 2, we connect their compression signal to a function that calls the on_action() signal with its own ID parameter. In the connector we add a dictionary (export) and specify the IDs and labels that should be called (don’t forget to define the on_action in the script), Connect the signal to a function that searches in the dictionary based on the input parameter and calls change_state in the desired child, the rest of the process needs no explanation…

1 Like

First of all thank you very much for the answare!
It sounds like a very smart way to handle this issue, but I am not sure i grasp the concept (and that’s almost certantly due to a lack of knowledge on my side), if i can abuse of a bit more of your time, kindness and knowledge:

For a more concrete example let’s say that in my world i have 2 instances of the same “Lever” scene with the exported var ActivatorID, plus 1 instance “Door” and 1 instance “Trap” each with their own exported var ReceiverID (each of these scenes are at the moment siblings in a “Interactables” 2Dnode that works as a folder).
I should than create an intermediary, let’s call it InteractionManager (which i might autoload i suppose) and create a dictionary in it. This dictionary should containt the list of [Receivers] and their relative IDs (#should i reference the single receivers scene from each level by ctrl + drag from the main scene to reference them?).
I should than connect the signal that each of my “lever” scenes emits when they are interacted with by the player to this manager passing inside it the ID of the [Activator] and it should trigger a function inside the manager that searches in this dictionary for such an ID.

IF, and i say IF, all i just said makes sense, how can i than toggle the state of my Receiver? (turning the trap off or opening my door in the given example)

To define nodes, we still don’t have typed dictionaries in Godot (I’m glad to say we will have them soon), so the editor does not support a suitable user interface for a dictionary structured as String: Node, which can be a bit confusing; doing it is possible. However, I prefer to create a dictionary and keep NodePaths in it to use get_node when needed, as it gives me a better feeling.

Regarding receivers, essentially a function will be called on them (I mentioned change_state above as an example); this function changes the state from what it is to what it isn’t each time it is called. If the initial state of the sender and receiver is the same (which is not difficult) and there are only two states (true, false) for both, no problems will arise. However, for more than two possible states, if they change in order, the receiver can proceed to the next state with each call, and when it reaches the end, it returns to the beginning. If the states are unordered or anything that the above method does not cater to, an additional parameter should be added to the intermediary signal, and the sender should send it alongside the ID through the intermediary. Then, the intermediary sends it to the existing function in the receiver, and the receiver adjusts its state based on the value of the parameter.

All your statements may seem possible (at least what you said), so I don’t think there will be any problems. If you run into issues while implementing it, please express it in the forum!

1 Like

Thank you for your help! I ended up simplifying my approach: since all I needed was for ‘button X’ to activate Door/Trap X without having to include the signal for each instance of these items, I created a new scene called ‘RemoteX’ (for RemoteDoor, RemoteTrap, etc.). Each of these scenes have the same on_activation function with their own logic, and the RemoteActivator (lever, button, etc.) accesses this child through the get_child(x) method. At the moment, I’m simply using the index to grab the first child that isn’t part of the activator itself (i will study an ID method for bug proofing) and then call its on_activation function, or print a Activator debug ID if no child is found.

So, now all I have to do is instance the remotely activated node as a child of the Activator, and it works as needed. This solution is sufficient for my current needs, and I will revisit your approach when I am a more experienced programmer. Still, thank you very much for your time and for suggesting such a helpful solution. The idea ultimately came from reading and studying your suggestion and this post will remain as a useful reference for me in the future!! (i saved this conversation for myself due to the automatic elimination after a solution has been marked)

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.