Skip to content

Commit 648388e

Browse files
AdriaandeJonghAdriaan de Jongh
authored andcommitted
added section on common unsafe operations and their safe counterparts
1 parent 833e2c4 commit 648388e

File tree

1 file changed

+73
-0
lines changed

1 file changed

+73
-0
lines changed

tutorials/scripting/gdscript/static_typing.rst

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,79 @@ if you prefer a more readable and reliable, but more verbose syntax.
396396
``UNSAFE_*`` warnings make unsafe operations more noticeable, than unsafe lines.
397397
Currently, ``UNSAFE_*`` warnings do not cover all cases that unsafe lines cover.
398398

399+
Common unsafe operations and their safe counterparts
400+
----------------------------------------------------
401+
402+
``UNSAFE_PROPERTY_ACCESS`` and ``UNSAFE_METHOD_ACCESS`` warnings
403+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
404+
405+
In this example, we aim to set a property and call a method on an object
406+
that has a script attached with ``class_name MyScript`` and that ``extends
407+
Node2D``. If we have a reference to the object as a ``Node2D`` (for instance,
408+
as it was passed to us by the physics system), we can first check if the
409+
property and method exist and then set and call them if they do::
410+
411+
if "some_property" in node_2d:
412+
node_2d.some_property = 20 # Produces UNSAFE_PROPERTY_ACCESS warning.
413+
414+
if node_2d.has_method("some_function"):
415+
node_2d.some_function() # Produces UNSAFE_METHOD_ACCESS warning.
416+
417+
However, this code will produce ``UNSAFE_PROPERTY_ACCESS`` and
418+
``UNSAFE_METHOD_ACCESS`` warnings as the property and method are not present
419+
in the referenced type - in this case a ``Node2D``. To make these operations
420+
safe, you can first check if the object is of type ``MyScript`` using the
421+
``is`` keyword and then declare a variable with the type ``MyScript`` on
422+
which you can set its properties and call its methods::
423+
424+
if node_2d is MyScript:
425+
var my_script: MyScript = node_2d
426+
my_script.some_property = 20
427+
my_script.some_function()
428+
429+
Alternatively, you can declare a variable and use the ``as`` operator to try
430+
to cast the object. You'll then want to check whether the cast was successful
431+
by confirming that the variable was assigned::
432+
433+
var my_script := node_2d as MyScript
434+
if my_script != null:
435+
my_script.some_property = 20
436+
my_script.some_function()
437+
438+
``UNSAFE_CAST`` warning
439+
~~~~~~~~~~~~~~~~~~~~~~~
440+
441+
In this example, we would like the label connected to an object entering our
442+
collision area to show the area's name. Once the object enters the collision
443+
area, the physics system sends a signal with a ``Node2D`` object, and the most
444+
straightforward (but not statically typed) solution to do what we want could
445+
be achieved like this::
446+
447+
func _on_body_entered(body: Node2D) -> void:
448+
body.label.text = name # Produces UNSAFE_PROPERTY_ACCESS warning.
449+
450+
This piece of code produces an ``UNSAFE_PROPERTY_ACCESS`` warning because
451+
``label`` is not defined in ``Node2D``. To solve this, we could first check if the
452+
``label`` property exist and cast it to type ``Label`` before settings its text
453+
property like so::
454+
455+
func _on_body_entered(body: Node2D) -> void:
456+
if "label" in body:
457+
(body.label as Label).text = name # Produces UNSAFE_CAST warning.
458+
459+
However, this produces an ``UNSAFE_CAST`` warning because ``body.label`` is of a
460+
``Variant`` type. To safely get the property in the type you want, you can use the
461+
``Object.get()`` method which returns the object as a ``Variant`` value or returns
462+
``null`` if the property doesn't exist. You can then determine whether the
463+
property contains an object of the right type using the ``is`` keyword, and
464+
finally declare a statically typed variable with the object::
465+
466+
func _on_body_entered(body: Node2D) -> void:
467+
var label_variant: Variant = body.get("label")
468+
if label_variant is Label:
469+
var label: Label = label_variant
470+
label.text = name
471+
399472
Cases where you can't specify types
400473
-----------------------------------
401474

0 commit comments

Comments
 (0)