Signaling from one GDScript to another?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Corruptinator

Now lets say that I have two scripts, the “Primary” one attached to a node and the other existing “Secondary” placed outside the node and that it extends to the original script…

Is there a way to send a signal to the other script?

Example:

(Primary)

extends Node

signal *update_to_external_script*

ready():
pass

(Secondary)

extends "res://path/to/*Primary.gd*"

connect("update_to_external_scrip",self,"on_state_changed")

on_state_changed()
print("update")

ready():
pass
:bust_in_silhouette: Reply From: Zylann

You should have a look at how signals work: GDScript — Godot Engine (3.0) documentation in English

Emitting a signal from Primary.gd and receiving it in Secondary.gd can be done in the following way: first, you would have your two scripts written like this:

Primary.gd

extends Node

signal the_signal

# Then whatever code...

Secondary.gd

extends Node
# Note: inheriting Primary is not necessary for the signal to be received,
# so for this example I will not inherit it

func on_state_changed():
    print("Update!")

Then you would have each of these scripts in two nodes, anywhere in your scene.
Now, for Secondary to receive the signal, it has to be connected with Primary.

You can do this from the scene tree editor: select the Primary node, then click on the Node dock. This dock should show all signals your node can emit, and you should see the_signal in them. Double-click on it, a dialog will open asking you which node should receive the signal. Select Secondary, and write the name of the function to call (“Method in Node”): on_state_changed, validate and they should be connected.

There is another way to do this connection, with code, using the _ready function. For example, in Secondary.gd, you can do this:

func _ready():
    var primary = get_node("relative/path/to/Primary")
    primary.connect("the_signal", self, "on_state_changed")

or, if you prefer doing it from Primary.gd:

func _ready():
    var secondary = get_node("relative/path/to/Secondary")
    connect("the_signal", secondary , "on_state_changed")

Finally, for this signal to do something, you have to emit it.
A simple way to test if it works is to emit the signal when you click a mouse button. To test this, you can use the _input function in Primary.gd:

func _input(event):
    if event is InputEventMouseButton and event.pressed:
        emit_signal("the_signal")

I seem to have an issue with the signal. The signal is always taken from the current file and this means that if I move the function I also have to move the signal. Is there a way to use it with a signal from another file?

takje | 2020-11-17 01:15

:bust_in_silhouette: Reply From: WolframR

the answer is no. unfortunately signals are a feature of nodes specifically and the scripts using them need to be connected to nodes in order to use them. this is because the communication is happening through the scene tree, so nothing outside of it, such as your secondary script, can communicate using it. While they don’t answer the question, Zylann provides a very good explanation of how signals work inside the scene tree as normal.

i may be wrong, ofc, i’m just one game dev with several months of experience. however, there may be a more advanced way to recreate the observer pattern (signals) to allow a similar way to communicate, but unless you plan on making it a major architectural decision it’s probably not worth the effort.

grain of salt here.

:bust_in_silhouette: Reply From: deaton64

Hi,

Maybe Groups would work for you?

Groups