static_typing.rst 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. .. _doc_gdscript_static_typing:
  2. Static typing in GDScript
  3. =========================
  4. In this guide, you will learn:
  5. - **How to use types in GDScript**
  6. - That **static types can help you avoid bugs**
  7. Where and how you use this new language feature is entirely up to you:
  8. you can use it only in some sensitive GDScript files, use it everywhere,
  9. or write code like you always did!
  10. Static types can be used on variables, constants, functions, parameters,
  11. and return types.
  12. .. note::
  13. Typed GDScript is available since Godot 3.1.
  14. A brief look at static typing
  15. -----------------------------
  16. With typed GDScript, Godot can detect even more errors as you write
  17. code! It gives you and your teammates more information as you’re
  18. working, as the arguments’ types show up when you call a method.
  19. Imagine you’re programming an inventory system. You code an ``Item``
  20. node, then an ``Inventory``. To add items to the inventory, the people
  21. who work with your code should always pass an ``Item`` to the
  22. ``Inventory.add`` method. With types, you can enforce this:
  23. ::
  24. # In Item.gd
  25. class_name Item
  26. # In Inventory.gd
  27. class_name Inventory
  28. func add(reference: Item, amount: int = 1):
  29. var item = find_item(reference)
  30. if not item:
  31. item = _instance_item_from_db(reference)
  32. item.amount += amount
  33. Another significant advantage of typed GDScript is the new **warning
  34. system**. From version 3.1, Godot gives you warnings about your code as
  35. you write it: the engine identifies sections of your code that may lead
  36. to issues at runtime, but lets you decide whether or not you want to
  37. leave the code as it is. More on that in a moment.
  38. Static types also give you better code completion options. Below, you
  39. can see the difference between a dynamic and a static typed completion
  40. options for a class called ``PlayerController``.
  41. You’ve probably stored a node in a variable before, and typed a dot to
  42. be left with no autocomplete suggestions:
  43. .. figure:: ./img/typed_gdscript_code_completion_dynamic.png
  44. :alt: code completion options for dynamic
  45. This is due to dynamic code. Godot cannot know what node or value type
  46. you’re passing to the function. If you write the type explicitly
  47. however, you will get all public methods and variables from the node:
  48. .. figure:: ./img/typed_gdscript_code_completion_typed.png
  49. :alt: code completion options for typed
  50. In the future, typed GDScript will also increase code performance:
  51. Just-In-Time compilation and other compiler improvements are already
  52. on the roadmap!
  53. Overall, typed programming gives you a more structured experience. It
  54. helps prevent errors and improves the self-documenting aspect of your
  55. scripts. This is especially helpful when you’re working in a team or on
  56. a long-term project: studies have shown that developers spend most of
  57. their time reading other people’s code, or scripts they wrote in the
  58. past and forgot about. The clearer and the more structured the code, the
  59. faster it is to understand, the faster you can move forward.
  60. How to use static typing
  61. ------------------------
  62. To define the type of a variable or a constant, write a colon after the
  63. variable’s name, followed by its type. E.g. ``var health: int``. This
  64. forces the variable's type to always stay the same:
  65. ::
  66. var damage: float = 10.5
  67. const MOVE_SPEED: float = 50.0
  68. Godot will try to infer types if you write a colon, but you omit the
  69. type:
  70. ::
  71. var life_points := 4
  72. var damage := 10.5
  73. var motion := Vector2()
  74. Currently you can use three types of… types:
  75. 1. :ref:`Built-in <doc_gdscript_builtin_types>`
  76. 2. Core classes and nodes (``Object``, ``Node``, ``Area2D``,
  77. ``Camera2D``, etc.)
  78. 3. Your own, custom classes. Look at the new :ref:`class_name <doc_scripting_continued_class_name>`
  79. feature to register types in the editor.
  80. .. note::
  81. You don't need to write type hints for constants, as Godot sets it automatically from the assigned value. But you can still do so to make the intent of your code clearer.
  82. Custom variable types
  83. ~~~~~~~~~~~~~~~~~~~~~
  84. You can use any class, including your custom classes, as types. There
  85. are two ways to use them in scripts. The first method is to preload the
  86. script you want to use as a type in a constant:
  87. ::
  88. const Rifle = preload('res://player/weapons/Rifle.gd')
  89. var my_rifle: Rifle
  90. The second method is to use the ``class_name`` keyword when you create.
  91. For the example above, your Rifle.gd would look like this:
  92. ::
  93. extends Node2D
  94. class_name Rifle
  95. If you use ``class_name``, Godot registers the Rifle type globally in
  96. the editor, and you can use it anywhere, without having to preload it
  97. into a constant:
  98. ::
  99. var my_rifle: Rifle
  100. Variable casting
  101. ~~~~~~~~~~~~~~~~
  102. Type casting is a key concept in typed languages.
  103. Casting is the conversion of a value from one type to another.
  104. Imagine an Enemy in your game, that ``extends Area2D``. You want it to
  105. collide with the Player, a ``KinematicBody2D`` with a script called
  106. ``PlayerController`` attached to it. You use the ``on_body_entered``
  107. signal to detect the collision. With typed code, the body you detect is
  108. going to be a generic ``PhysicsBody2D``, and not your
  109. ``PlayerController`` on the ``_on_body_entered`` callback.
  110. You can check if this ``PhysicsBody2D`` is your Player with the ``as``
  111. casting keyword, and using the colon ``:`` again to force the variable
  112. to use this type. This forces the variable to stick to the
  113. ``PlayerController`` type:
  114. ::
  115. func _on_body_entered(body: PhysicsBody2D) -> void:
  116. var player := body as PlayerController
  117. if not player:
  118. return
  119. player.damage()
  120. As we’re dealing with a custom type, if the ``body`` doesn’t extend
  121. ``PlayerController``, the ``player``\ variable will be set to ``null``.
  122. We can use this to check if the body is the player or not. We will also
  123. get full autocompletion on the player variable thanks to that cast.
  124. .. note::
  125. If you try to cast with a built-in type and it fails, Godot will throw an error.
  126. Safe lines
  127. ^^^^^^^^^^
  128. You can also use casting to ensure safe lines. Safe lines are a new
  129. tool in Godot 3.1 to tell you when ambiguous lines of code are
  130. type-safe. As you can mix and match typed and dynamic code, at times,
  131. Godot doesn’t have enough information to know if an instruction will trigger
  132. an error or not at runtime.
  133. This happens when you get a child node. Let’s take a timer for example:
  134. with dynamic code, you can get the node with ``$Timer``. GDScript
  135. supports `duck-typing <https://stackoverflow.com/a/4205163/8125343>`__,
  136. so even if your timer is of type ``Timer``, it is also a ``Node`` and an
  137. ``Object``, two classes it extends. With dynamic GDScript, you also
  138. don’t care about the node’s type as long as it has the methods you need
  139. to call.
  140. You can use casting to tell Godot the type you expect when you get a
  141. node: ``($Timer as Timer)``, ``($Player as KinematicBody2D)``, etc.
  142. Godot will ensure the type works and if so, the line number will turn
  143. green at the left of the script editor.
  144. .. figure:: ./img/typed_gdscript_safe_unsafe_line.png
  145. :alt: Safe vs Unsafe Line
  146. Safe vs Unsafe Line
  147. .. note::
  148. You can turn off safe lines or change their color in the editor settings.
  149. Define the return type of a function with the arrow ->
  150. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  151. To define the return type of a function, write a dash and a right angle
  152. bracket ``->`` after its declaration, followed by the return type:
  153. ::
  154. func _process(delta: float) -> void:
  155. pass
  156. The type ``void`` means the function does not return anything. You can
  157. use any type, as with variables:
  158. ::
  159. func hit(damage: float) -> bool:
  160. health_points -= damage
  161. return health_points <= 0
  162. You can also use your own nodes as return types:
  163. ::
  164. # Inventory.gd
  165. # Adds an item to the inventory and returns it.
  166. func add(reference: Item, amount: int) -> Item:
  167. var item: Item = find_item(reference)
  168. if not item:
  169. item = ItemDatabase.get_instance(reference)
  170. item.amount += amount
  171. return item
  172. Typed or dynamic: stick to one style
  173. ------------------------------------
  174. Typed GDScript and dynamic GDScript can coexist in the same project. But
  175. I recommended to stick to either style for consistency in your codebase,
  176. and for your peers. It’s easier for everyone to work together if you
  177. follow the same guidelines, and faster to read and understand other
  178. people’s code.
  179. Typed code takes a little more writing, but you get the benefits we
  180. discussed above. Here’s an example of the same, empty script, in a
  181. dynamic style:
  182. ::
  183. extends Node
  184. func _ready():
  185. pass
  186. func _process(delta):
  187. pass
  188. And with static typing:
  189. ::
  190. extends Node
  191. func _ready() -> void:
  192. pass
  193. func _process(delta: float) -> void:
  194. pass
  195. As you can see, you can also use types with the engine’s virtual
  196. methods. Signal callbacks, like any methods, can also use types. Here’s
  197. a ``body_entered`` signal in a dynamic style:
  198. ::
  199. func _on_Area2D_body_entered(body):
  200. pass
  201. And the same callback, with type hints:
  202. ::
  203. func _on_area_entered(area: CollisionObject2D) -> void:
  204. pass
  205. You’re free to replace, e.g. the ``CollisionObject2D``, with your own type,
  206. to cast parameters automatically:
  207. ::
  208. func _on_area_entered(bullet: Bullet) -> void:
  209. if not bullet:
  210. return
  211. take_damage(bullet.damage)
  212. The ``bullet`` variable could hold any ``CollisionObject2D`` here, but
  213. we make sure it is our ``Bullet``, a node we created for our project. If
  214. it’s anything else, like an ``Area2D``, or any node that doesn’t extend
  215. ``Bullet``, the ``bullet`` variable will be ``null``.
  216. Warning system
  217. --------------
  218. The warning system complements typed GDScript. It’s here to help you
  219. avoid mistakes that are hard to spot during development, and that may
  220. lead to runtime errors.
  221. You can configure warnings in the Project Settings under a new section
  222. called ``GDScript``:
  223. .. figure:: ./img/typed_gdscript_warning_system_settings.png
  224. :alt: warning system project settings
  225. warning system project settings
  226. You can find a list of warnings for the active GDScript file in the
  227. script editor’s status bar. The example below has 3 warnings:
  228. .. figure:: ./img/typed_gdscript_warning_example.png
  229. :alt: warning system example
  230. warning system example
  231. To ignore specific warnings in one file, insert a special comment of the
  232. form ``#warning-ignore:warning-id``, or click on the ignore link to the
  233. right of the warning’s description. Godot will add a comment above the
  234. corresponding line and the code won’t trigger the corresponding warning
  235. anymore:
  236. .. figure:: ./img/typed_gdscript_warning_system_ignore.png
  237. :alt: warning system ignore example
  238. warning system ignore example
  239. Warnings won’t prevent the game from running, but you can turn them into
  240. errors if you’d like. This way your game won’t compile unless you fix
  241. all warnings. Head to the ``GDScript`` section of the Project Settings to
  242. turn on this option. Here’s the same file as the previous example with
  243. warnings as errors turned on:
  244. .. figure:: ./img/typed_gdscript_warning_system_errors.png
  245. :alt: warnings as errors
  246. warnings as errors
  247. Cases where you can’t specify types
  248. -----------------------------------
  249. To wrap up this introduction, let’s cover a few cases where you can’t
  250. use type hints. All the examples below **will trigger errors**.
  251. You can’t use Enums as types:
  252. ::
  253. enum MoveDirection {UP, DOWN, LEFT, RIGHT}
  254. var current_direction: MoveDirection
  255. You can’t specify the type of individual members in an array. This will
  256. give you an error:
  257. ::
  258. var enemies: Array = [$Goblin: Enemy, $Zombie: Enemy]
  259. You can’t force the assignment of types in a ``for`` loop, as each
  260. element the ``for`` keyword loops over already has a different type. So you
  261. **cannot** write:
  262. ::
  263. var names = ['John', 'Marta', 'Samantha', 'Jimmy']
  264. for name: String in names:
  265. pass
  266. Two scripts can’t depend on each other in a cyclic fashion:
  267. ::
  268. # Player.gd
  269. extends Area2D
  270. class_name Player
  271. var rifle: Rifle
  272. ::
  273. # Rifle.gd
  274. extends Area2D
  275. class_name Rifle
  276. var player: Player
  277. Summary
  278. -------
  279. Typed GDScript is a powerful tool. Available as of version 3.1 of Godot, it
  280. helps you write more structured code, avoid common errors, and
  281. create scalable systems. In the future, static types will also bring you
  282. a nice performance boost thanks to upcoming compiler optimizations.