GDScript style guide

Description

This styleguide lists conventions to write elegant GDScript. The goal is to encourage writing clean, readable code and promote consistency across projects, discussions, and tutorials. Hopefully, this will also encourage development of auto-formatting tools.

Since GDScript is close to Python, this guide is inspired by Python’s PEP 8 programming styleguide.

Note

Godot’s built-in script editor uses a lot of these conventions by default. Let it help you.

Code structure

Indentation

Indent type: Tabs (editor default)

Indent size: 4 (editor default)

Each indent level should be one greater than the block containing it.

Good:

  1. for i in range(10):
  2. print("hello")

Bad:

  1. for i in range(10):
  2. print("hello")
  3. for i in range(10):
  4. print("hello")

Use 2 indent levels to distinguish continuation lines from regular code blocks.

Good:

  1. effect.interpolate_property(sprite, 'transform/scale',
  2. sprite.get_scale(), Vector2(2.0, 2.0), 0.3,
  3. Tween.TRANS_QUAD, Tween.EASE_OUT)

Bad:

  1. effect.interpolate_property(sprite, 'transform/scale',
  2. sprite.get_scale(), Vector2(2.0, 2.0), 0.3,
  3. Tween.TRANS_QUAD, Tween.EASE_OUT)

Blank lines

Surround functions and class definitions with two blank lines:

  1. func heal(amount):
  2. health += amount
  3. health = min(health, max_health)
  4. emit_signal("health_changed", health)
  5. func take_damage(amount, effect=null):
  6. health -= amount
  7. health = max(0, health)
  8. emit_signal("health_changed", health)

Use one blank line inside functions to separate logical sections.

One statement per line

Never combine multiple statements on a single line. No, C programmers, not with a single line conditional statement (except with the ternary operator)!

Good:

  1. if position.x > width:
  2. position.x = 0
  3. if flag:
  4. print("flagged")

Bad:

  1. if position.x > width: position.x = 0
  2. if flag: print("flagged")

Avoid unnecessary parentheses

Avoid parentheses in expressions and conditional statements. Unless necessary for order of operations, they only reduce readability.

Good:

  1. if is_colliding():
  2. queue_free()

Bad:

  1. if (is_colliding()):
  2. queue_free()

Whitespace

Always use one space around operators and after commas. Avoid extra spaces in dictionary references and function calls, or to create “columns.”

Good:

  1. position.x = 5
  2. position.y = mpos.y + 10
  3. dict['key'] = 5
  4. myarray = [4, 5, 6]
  5. print('foo')

Bad:

  1. position.x=5
  2. position.y = mpos.y+10
  3. dict ['key'] = 5
  4. myarray = [4,5,6]
  5. print ('foo')

NEVER:

  1. x = 100
  2. y = 100
  3. velocity = 500

Naming conventions

These naming conventions follow the Godot Engine style. Breaking these will make your code clash with the built-in naming conventions, which is ugly.

Classes and nodes

Use PascalCase: extends KinematicBody

Also when loading a class into a constant or variable:

  1. const MyCoolNode = preload('res://my_cool_node.gd')

Functions and variables

Use snake_case: get_node()

Prepend a single underscore (_) to virtual methods (functions the user must override), private functions, and private variables: func _ready()

Signals

Use past tense:

  1. signal door_opened
  2. signal score_changed

Constants

Use CONSTANT_CASE, all caps, with an underscore (_) to separate words: const MAX_SPEED = 200

Static typing

Since Godot 3.1, GDScript supports optional static typing.

Type hints

Place the colon right after the variable’s name, without a space, and let the GDScript compiler infer the variable’s type when possible.

Good:

  1. onready var health_bar: ProgressBar = get_node("UI/LifeBar")
  2. var health := 0 # The compiler will use the int type

Bad:

  1. # The compiler can't infer the exact type and will use Node
  2. # instead of ProgressBar
  3. onready var health_bar := get_node("UI/LifeBar")

When you let the compiler infer the type hint, write the colon and equal signs together: :=.

  1. var health := 0 # The compiler will use the int type

Add a space on either sides of the return type arrow when defining functions.

  1. func heal(amount: int) -> void: