signals.rst 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. .. meta::
  2. :keywords: Signal
  3. .. _doc_signals:
  4. Signals
  5. =======
  6. Introduction
  7. ------------
  8. Signals are Godot's version of the *observer* pattern. They allow a node to
  9. send out a message that other nodes can listen for and respond to. For example,
  10. rather than continuously checking a button to see if it's being pressed, the
  11. button can emit a signal when it's pressed.
  12. .. note:: You can read more about the observer pattern here: https://gameprogrammingpatterns.com/observer.html
  13. Signals are a way to *decouple* your game objects, which leads to better organized
  14. and more manageable code. Instead of forcing game objects to expect other objects
  15. to always be present, they can instead emit signals that all interested objects can
  16. subscribe to and respond to.
  17. Below you can see some examples of how you can use signals in your own projects.
  18. Timer example
  19. -------------
  20. To see how signals work, let's try using a :ref:`Timer <class_Timer>` node. Create
  21. a new scene with a Node2D and two children: a Timer and a :ref:`Sprite <class_Sprite>`.
  22. In the Scene dock, rename Node2D to TimerExample.
  23. For the Sprite's texture, you can use the Godot icon, or any other image you
  24. like. Do so by selecting ``Load`` in the Sprite's Texture attribute drop-down menu.
  25. Attach a script to the root node, but don't add any code to it yet.
  26. Your scene tree should look like this:
  27. .. image:: img/signals_node_setup.png
  28. In the Timer node's properties, check the "On" box next to *Autostart*. This will
  29. cause the timer to start automatically when you run the scene. You can leave the
  30. *Wait Time* at 1 second.
  31. Next to the "Inspector" tab is a tab labeled "Node". Click on this tab and you'll
  32. see all of the signals that the selected node can emit. In the case of the Timer
  33. node, the one we're concerned with is "timeout". This signal is emitted whenever
  34. the Timer reaches ``0``.
  35. .. image:: img/signals_node_tab_timer.png
  36. Click on the "timeout()" signal and click "Connect..." at the bottom of the signals
  37. panel. You'll see the following window, where you can define how you want to connect
  38. the signal:
  39. .. image:: img/signals_connect_dialog_timer.png
  40. On the left side, you'll see the nodes in your scene and can select the node that
  41. you want to "listen" for the signal. Note that the Timer node is blue, this is a
  42. visual indication that it's the node that is emitting the signal. Select the root
  43. node.
  44. .. warning:: The target node *must* have a script attached or you'll receive
  45. an error message.
  46. If you toggle the Advanced menu, you'll see on the right side that you can bind an arbitrary number of arguments of (possibly) different
  47. types. This can be useful when you have more than one signal connected to the same method,
  48. as each signal propagation will result in different values for those extra call arguments.
  49. On the bottom of the window is a field labeled "Receiver Method". This is the name
  50. of the function in the target node's script that you want to use. By default,
  51. Godot will create this function using the naming convention ``_on_<node_name>_<signal_name>``
  52. but you can change it if you wish.
  53. Click "Connect" and you'll see that the function has been created in the script:
  54. .. tabs::
  55. .. code-tab:: gdscript GDScript
  56. extends Node2D
  57. func _on_Timer_timeout():
  58. pass # Replace with function body.
  59. .. code-tab:: csharp
  60. public class TimerExample : Node2D
  61. {
  62. public void _on_Timer_timeout()
  63. {
  64. // Replace with function body.
  65. }
  66. }
  67. Now we can replace the placeholder code with whatever code we want to run when
  68. the signal is received. Let's make the Sprite blink:
  69. .. tabs::
  70. .. code-tab:: gdscript GDScript
  71. extends Node2D
  72. func _on_Timer_timeout():
  73. # Note: the `$` operator is a shorthand for `get_node()`,
  74. # so `$Sprite` is equivalent to `get_node("Sprite")`.
  75. $Sprite.visible = !$Sprite.visible
  76. .. code-tab:: csharp
  77. public class TimerExample : Node2D
  78. {
  79. public void _on_Timer_timeout()
  80. {
  81. var sprite = GetNode<Sprite>("Sprite");
  82. sprite.Visible = !sprite.Visible;
  83. }
  84. }
  85. Run the scene and you'll see the Sprite blinking on and off every second. You can
  86. change the Timer's *Wait Time* property to alter this.
  87. Connecting signals in code
  88. ~~~~~~~~~~~~~~~~~~~~~~~~~~
  89. You can also make the signal connection in code rather than with the editor. This
  90. is usually necessary when you're instancing nodes via code and so you can't use
  91. the editor to make the connection.
  92. First, disconnect the signal by selecting the connection in the Timer's "Node"
  93. tab and clicking disconnect.
  94. .. image:: img/signals_disconnect_timer.png
  95. To make the connection in code, we can use the ``connect`` function. We'll put it
  96. in ``_ready()`` so that the connection will be made on run. The syntax of the
  97. function is ``<source_node>.connect(<signal_name>, <target_node>, <target_function_name>)``.
  98. Here is the code for our Timer connection:
  99. .. tabs::
  100. .. code-tab:: gdscript GDScript
  101. extends Node2D
  102. func _ready():
  103. $Timer.connect("timeout", self, "_on_Timer_timeout")
  104. func _on_Timer_timeout():
  105. $Sprite.visible = !$Sprite.visible
  106. .. code-tab:: csharp
  107. public class TimerExample : Node2D
  108. {
  109. public override void _Ready()
  110. {
  111. GetNode("Timer").Connect("timeout", this, nameof(_on_Timer_timeout));
  112. }
  113. public void _on_Timer_timeout()
  114. {
  115. var sprite = GetNode<Sprite>("Sprite");
  116. sprite.Visible = !sprite.Visible;
  117. }
  118. }
  119. Custom signals
  120. --------------
  121. You can also declare your own custom signals in Godot:
  122. .. tabs::
  123. .. code-tab:: gdscript GDScript
  124. extends Node2D
  125. signal my_signal
  126. .. code-tab:: csharp
  127. public class Main : Node2D
  128. {
  129. [Signal]
  130. public delegate void MySignal();
  131. }
  132. Once declared, your custom signals will appear in the Inspector and can be connected
  133. in the same way as a node's built-in signals.
  134. To emit a signal via code, use the ``emit_signal`` function:
  135. .. tabs::
  136. .. code-tab:: gdscript GDScript
  137. extends Node2D
  138. signal my_signal
  139. func _ready():
  140. emit_signal("my_signal")
  141. .. code-tab:: csharp
  142. public class Main : Node2D
  143. {
  144. [Signal]
  145. public delegate void MySignal();
  146. public override void _Ready()
  147. {
  148. EmitSignal(nameof(MySignal));
  149. }
  150. }
  151. A signal can also optionally declare one or more arguments. Specify the
  152. argument names between parentheses:
  153. .. tabs::
  154. .. code-tab:: gdscript GDScript
  155. extends Node
  156. signal my_signal(value, other_value)
  157. .. code-tab:: csharp
  158. public class Main : Node
  159. {
  160. [Signal]
  161. public delegate void MySignal(bool value, int other_value);
  162. }
  163. .. note::
  164. The signal arguments show up in the editor's node dock, and Godot
  165. can use them to generate callback functions for you. However, you can still
  166. emit any number of arguments when you emit signals. So it's up to you to
  167. emit the correct values.
  168. To pass values, add them as the second argument to the ``emit_signal`` function:
  169. .. tabs::
  170. .. code-tab:: gdscript GDScript
  171. extends Node
  172. signal my_signal(value, other_value)
  173. func _ready():
  174. emit_signal("my_signal", true, 42)
  175. .. code-tab:: csharp
  176. public class Main : Node
  177. {
  178. [Signal]
  179. public delegate void MySignal(bool value, int other_value);
  180. public override void _Ready()
  181. {
  182. EmitSignal(nameof(MySignal), true, 42);
  183. }
  184. }
  185. Conclusion
  186. ----------
  187. Many of Godot's built-in node types provide signals you can use to detect
  188. events. For example, an :ref:`Area2D <class_Area2D>` representing a coin emits
  189. a ``body_entered`` signal whenever the player's physics body enters its collision
  190. shape, allowing you to know when the player collected it.
  191. In the next section, :ref:`doc_your_first_game`, you'll build a complete game
  192. including several uses of signals to connect different game components.