2023-01-12 20:49:14 +01:00
|
|
|
|
2022-03-18 17:46:08 +01:00
|
|
|
|
|
|
|
Godot notifications
|
|
|
|
===================
|
|
|
|
|
|
|
|
Every Object in Godot implements a
|
2023-01-12 20:57:31 +01:00
|
|
|
`notification` method. Its purpose is to
|
2022-03-18 17:46:08 +01:00
|
|
|
allow the Object to respond to a variety of engine-level callbacks that may
|
|
|
|
relate to it. For example, if the engine tells a
|
2023-01-12 19:30:47 +01:00
|
|
|
`CanvasItem` to "draw", it will call
|
2023-01-12 20:57:31 +01:00
|
|
|
`notification(NOTIFICATION_DRAW)`.
|
2022-03-18 17:46:08 +01:00
|
|
|
|
|
|
|
Some of these notifications, like draw, are useful to override in scripts. So
|
|
|
|
much so that Godot exposes many of them with dedicated functions:
|
|
|
|
|
2023-01-12 20:57:31 +01:00
|
|
|
- `ready()` : NOTIFICATION_READY
|
2022-03-18 17:46:08 +01:00
|
|
|
|
2023-01-12 20:57:31 +01:00
|
|
|
- `enter_tree()` : NOTIFICATION_ENTER_TREE
|
2022-03-18 17:46:08 +01:00
|
|
|
|
2023-01-12 20:57:31 +01:00
|
|
|
- `exit_tree()` : NOTIFICATION_EXIT_TREE
|
2022-03-18 17:46:08 +01:00
|
|
|
|
2023-01-12 20:57:31 +01:00
|
|
|
- `process(delta)` : NOTIFICATION_PROCESS
|
2022-03-18 17:46:08 +01:00
|
|
|
|
2023-01-12 20:57:31 +01:00
|
|
|
- `physics_process(delta)` : NOTIFICATION_PHYSICS_PROCESS
|
2022-03-18 17:46:08 +01:00
|
|
|
|
2023-01-12 20:57:31 +01:00
|
|
|
- `draw()` : NOTIFICATION_DRAW
|
2022-03-18 17:46:08 +01:00
|
|
|
|
|
|
|
What users might *not* realize is that notifications exist for types other
|
|
|
|
than Node alone:
|
|
|
|
|
2023-01-12 19:30:47 +01:00
|
|
|
- `Object::NOTIFICATION_POSTINITIALIZE`:
|
2022-03-18 17:46:08 +01:00
|
|
|
a callback that triggers during object initialization. Not accessible to scripts.
|
|
|
|
|
2023-01-12 19:30:47 +01:00
|
|
|
- `Object::NOTIFICATION_PREDELETE`:
|
2022-03-18 17:46:08 +01:00
|
|
|
a callback that triggers before the engine deletes an Object, i.e. a
|
|
|
|
'destructor'.
|
|
|
|
|
2023-01-12 19:30:47 +01:00
|
|
|
- `MainLoop::NOTIFICATION_WM_MOUSE_ENTER`:
|
2022-03-18 17:46:08 +01:00
|
|
|
a callback that triggers when the mouse enters the window in the operating
|
|
|
|
system that displays the game content.
|
|
|
|
|
|
|
|
And many of the callbacks that *do* exist in Nodes don't have any dedicated
|
|
|
|
methods, but are still quite useful.
|
|
|
|
|
2023-01-12 19:30:47 +01:00
|
|
|
- `Node::NOTIFICATION_PARENTED`:
|
2022-03-18 17:46:08 +01:00
|
|
|
a callback that triggers anytime one adds a child node to another node.
|
|
|
|
|
2023-01-12 19:30:47 +01:00
|
|
|
- `Node::NOTIFICATION_UNPARENTED`:
|
2022-03-18 17:46:08 +01:00
|
|
|
a callback that triggers anytime one removes a child node from another
|
|
|
|
node.
|
|
|
|
|
2023-01-12 19:30:47 +01:00
|
|
|
- `Popup::NOTIFICATION_POST_POPUP`:
|
2023-01-12 19:43:03 +01:00
|
|
|
a callback that triggers after a Popup node completes any `popup*` method.
|
|
|
|
Note the difference from its `about_to_show` signal which triggers
|
2022-03-18 17:46:08 +01:00
|
|
|
*before* its appearance.
|
|
|
|
|
|
|
|
One can access all these custom notifications from the universal
|
2023-01-12 20:57:31 +01:00
|
|
|
`notification` method.
|
2022-03-18 17:46:08 +01:00
|
|
|
|
2023-01-12 20:55:57 +01:00
|
|
|
Note:
|
|
|
|
|
2022-03-18 17:46:08 +01:00
|
|
|
Methods in the documentation labeled as "virtual" are also intended to be
|
|
|
|
overridden by scripts.
|
|
|
|
|
|
|
|
A classic example is the
|
2023-01-12 20:57:31 +01:00
|
|
|
`init` method in Object. While it has no
|
2023-01-12 19:43:03 +01:00
|
|
|
`NOTIFICATION_*` equivalent, the engine still calls the method. Most languages
|
2022-03-18 17:46:08 +01:00
|
|
|
(except C#) rely on it as a constructor.
|
|
|
|
|
|
|
|
So, in which situation should one use each of these notifications or
|
|
|
|
virtual functions?
|
|
|
|
|
|
|
|
_process vs. _physics_process vs. \*_input
|
|
|
|
------------------------------------------
|
|
|
|
|
2023-01-12 20:57:31 +01:00
|
|
|
Use `process` when one needs a framerate-dependent deltatime between
|
2022-03-18 17:46:08 +01:00
|
|
|
frames. If code that updates object data needs to update as often as
|
|
|
|
possible, this is the right place. Recurring logic checks and data caching
|
|
|
|
often execute here, but it comes down to the frequency at which one needs
|
|
|
|
the evaluations to update. If they don't need to execute every frame, then
|
|
|
|
implementing a Timer-yield-timeout loop is another option.
|
|
|
|
|
2023-01-12 18:31:02 +01:00
|
|
|
gdscript GDScript
|
2022-03-18 17:46:08 +01:00
|
|
|
|
2023-01-12 18:31:02 +01:00
|
|
|
```
|
2022-03-18 17:46:08 +01:00
|
|
|
# Infinitely loop, but only execute whenever the Timer fires.
|
|
|
|
# Allows for recurring operations that don't trigger script logic
|
|
|
|
# every frame (or even every fixed frame).
|
|
|
|
while true:
|
|
|
|
my_method()
|
|
|
|
$Timer.start()
|
|
|
|
yield($Timer, "timeout")
|
2023-01-12 18:31:02 +01:00
|
|
|
```
|
2022-03-18 17:46:08 +01:00
|
|
|
|
2023-01-12 20:57:31 +01:00
|
|
|
Use `physics_process` when one needs a framerate-independent deltatime
|
2022-03-18 17:46:08 +01:00
|
|
|
between frames. If code needs consistent updates over time, regardless
|
|
|
|
of how fast or slow time advances, this is the right place.
|
|
|
|
Recurring kinematic and object transform operations should execute here.
|
|
|
|
|
|
|
|
While it is possible, to achieve the best performance, one should avoid
|
2023-01-12 20:57:31 +01:00
|
|
|
making input checks during these callbacks. `process` and
|
|
|
|
`physics_process` will trigger at every opportunity (they do not "rest" by
|
2023-01-12 19:43:03 +01:00
|
|
|
default). In contrast, `*_input` callbacks will trigger only on frames in
|
2022-03-18 17:46:08 +01:00
|
|
|
which the engine has actually detected the input.
|
|
|
|
|
|
|
|
One can check for input actions within the input callbacks just the same.
|
|
|
|
If one wants to use delta time, one can fetch it from the related
|
|
|
|
deltatime methods as needed.
|
|
|
|
|
2023-01-12 18:31:02 +01:00
|
|
|
gdscript GDScript
|
2022-03-18 17:46:08 +01:00
|
|
|
|
2023-01-12 18:31:02 +01:00
|
|
|
```
|
2022-03-18 17:46:08 +01:00
|
|
|
# Called every frame, even when the engine detects no input.
|
|
|
|
func _process(delta):
|
|
|
|
if Input.is_action_just_pressed("ui_select"):
|
|
|
|
print(delta)
|
|
|
|
|
|
|
|
# Called during every input event.
|
|
|
|
func _unhandled_input(event):
|
|
|
|
match event.get_class():
|
|
|
|
"InputEventKey":
|
|
|
|
if Input.is_action_just_pressed("ui_accept"):
|
|
|
|
print(get_process_delta_time())
|
2023-01-12 18:31:02 +01:00
|
|
|
```
|
2022-03-18 17:46:08 +01:00
|
|
|
|
|
|
|
|
|
|
|
_init vs. initialization vs. export
|
|
|
|
-----------------------------------
|
|
|
|
|
|
|
|
If the script initializes its own node subtree, without a scene,
|
|
|
|
that code should execute here. Other property or SceneTree-independent
|
2023-01-12 20:57:31 +01:00
|
|
|
initializations should also run here. This triggers before `ready` or
|
|
|
|
`enter_tree`, but after a script creates and initializes its properties.
|
2022-03-18 17:46:08 +01:00
|
|
|
|
|
|
|
Scripts have three types of property assignments that can occur during
|
|
|
|
instantiation:
|
|
|
|
|
2023-01-12 18:31:02 +01:00
|
|
|
gdscript GDScript
|
2022-03-18 17:46:08 +01:00
|
|
|
|
2023-01-12 18:31:02 +01:00
|
|
|
```
|
2022-03-18 17:46:08 +01:00
|
|
|
# "one" is an "initialized value". These DO NOT trigger the setter.
|
|
|
|
# If someone set the value as "two" from the Inspector, this would be an
|
|
|
|
# "exported value". These DO trigger the setter.
|
|
|
|
export(String) var test = "one" setget set_test
|
|
|
|
|
|
|
|
func _init():
|
|
|
|
# "three" is an "init assignment value".
|
|
|
|
# These DO NOT trigger the setter, but...
|
|
|
|
test = "three"
|
|
|
|
# These DO trigger the setter. Note the `self` prefix.
|
|
|
|
self.test = "three"
|
|
|
|
|
|
|
|
func set_test(value):
|
|
|
|
test = value
|
|
|
|
print("Setting: ", test)
|
2023-01-12 18:31:02 +01:00
|
|
|
```
|
2022-03-18 17:46:08 +01:00
|
|
|
|
|
|
|
|
|
|
|
When instantiating a scene, property values will set up according to the
|
|
|
|
following sequence:
|
|
|
|
|
|
|
|
1. **Initial value assignment:** instantiation will assign either the
|
|
|
|
initialization value or the init assignment value. Init assignments take
|
|
|
|
priority over initialization values.
|
|
|
|
|
|
|
|
2. **Exported value assignment:** If instancing from a scene rather than
|
|
|
|
a script, Godot will assign the exported value to replace the initial
|
|
|
|
value defined in the script.
|
|
|
|
|
|
|
|
As a result, instantiating a script versus a scene will affect both the
|
|
|
|
initialization *and* the number of times the engine calls the setter.
|
|
|
|
|
|
|
|
_ready vs. _enter_tree vs. NOTIFICATION_PARENTED
|
|
|
|
------------------------------------------------
|
|
|
|
|
|
|
|
When instantiating a scene connected to the first executed scene, Godot will
|
2023-01-12 20:57:31 +01:00
|
|
|
instantiate nodes down the tree (making `init` calls) and build the tree
|
|
|
|
going downwards from the root. This causes `enter_tree` calls to cascade
|
|
|
|
down the tree. Once the tree is complete, leaf nodes call `ready`. A node
|
2022-03-18 17:46:08 +01:00
|
|
|
will call this method once all child nodes have finished calling theirs. This
|
|
|
|
then causes a reverse cascade going up back to the tree's root.
|
|
|
|
|
|
|
|
When instantiating a script or a standalone scene, nodes are not
|
2023-01-12 20:57:31 +01:00
|
|
|
added to the SceneTree upon creation, so no `enter_tree` callbacks
|
|
|
|
trigger. Instead, only the `init` call occurs. When the scene is added
|
|
|
|
to the SceneTree, the `enter_tree` and `ready` calls occur.
|
2022-03-18 17:46:08 +01:00
|
|
|
|
|
|
|
If one needs to trigger behavior that occurs as nodes parent to another,
|
|
|
|
regardless of whether it occurs as part of the main/active scene or not, one
|
2023-01-12 19:30:47 +01:00
|
|
|
can use the `PARENTED` notification.
|
2022-03-18 17:46:08 +01:00
|
|
|
For example, here is a snippet that connects a node's method to
|
|
|
|
a custom signal on the parent node without failing. Useful on data-centric
|
|
|
|
nodes that one might create at runtime.
|
|
|
|
|
2023-01-12 18:31:02 +01:00
|
|
|
gdscript GDScript
|
2022-03-18 17:46:08 +01:00
|
|
|
|
2023-01-12 18:31:02 +01:00
|
|
|
```
|
2022-03-18 17:46:08 +01:00
|
|
|
extends Node
|
|
|
|
|
|
|
|
var parent_cache
|
|
|
|
|
|
|
|
func connection_check():
|
|
|
|
return parent.has_user_signal("interacted_with")
|
|
|
|
|
|
|
|
func _notification(what):
|
|
|
|
match what:
|
|
|
|
NOTIFICATION_PARENTED:
|
|
|
|
parent_cache = get_parent()
|
|
|
|
if connection_check():
|
|
|
|
parent_cache.connect("interacted_with", self, "_on_parent_interacted_with")
|
|
|
|
NOTIFICATION_UNPARENTED:
|
|
|
|
if connection_check():
|
|
|
|
parent_cache.disconnect("interacted_with", self, "_on_parent_interacted_with")
|
|
|
|
|
|
|
|
func _on_parent_interacted_with():
|
|
|
|
print("I'm reacting to my parent's interaction!")
|
2023-01-12 18:31:02 +01:00
|
|
|
```
|