0 votes

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
in Engine by (203 points)

3 Answers

+2 votes

You should have a look at how signals work: http://docs.godotengine.org/en/3.0/getting_started/scripting/gdscript/gdscript_basics.html#signals

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")
by (28,738 points)

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?

0 votes

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.

by (41 points)
0 votes

Hi,

Maybe Groups would work for you?

Groups

by (1,963 points)
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.