signals.rst 6.4 KB

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