Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

GDScript 风格指南

该样式指南列出了编写优雅 GDScript 的约定。目标是促进编写干净、可读的代码,促进项目、讨论和教程之间的一致性。希望这也会促进开发自动格式化工具。

由于 GDScript 与 Python 非常接近,因此本指南的灵感来自 Python 的 PEP 8 编程风格指南。

风格指南并不是硬性的规则手册。有时,你可能无法应用下面的一些规范。当这种情况发生时,请使用你最好的判断,并询问其他开发人员的见解。

一般来说,在项目和团队中保持代码的一致性比一板一眼地遵循本指南更为重要。

备注

Godot的内置脚本编辑器默认使用了很多这些约定. 让它帮助你.

下面是基于这些规范的完整的类的示例:

class_name StateMachine
extends Node
## Hierarchical State machine for the player.
##
## Initializes states and delegates engine callbacks ([method Node._physics_process],
## [method Node._unhandled_input]) to the state.


signal state_changed(previous, new)

@export var initial_state: Node
var is_active = true:
    set = set_is_active

@onready var _state = initial_state:
    set = set_state
@onready var _state_name = _state.name


func _init():
    add_to_group("state_machine")


func _enter_tree():
    print("this happens before the ready method!")


func _ready():
    state_changed.connect(_on_state_changed)
    _state.enter()


func _unhandled_input(event):
    _state.unhandled_input(event)


func _physics_process(delta):
    _state.physics_process(delta)


func transition_to(target_state_path, msg={}):
    if not has_node(target_state_path):
        return

    var target_state = get_node(target_state_path)
    assert(target_state.is_composite == false)

    _state.exit()
    self._state = target_state
    _state.enter(msg)
    Events.player_state_changed.emit(_state.name)


func set_is_active(value):
    is_active = value
    set_physics_process(value)
    set_process_unhandled_input(value)
    set_block_signals(not value)


func set_state(value):
    _state = value
    _state_name = _state.name


func _on_state_changed(previous, new):
    print("state changed")
    state_changed.emit()


class State:
    var foo = 0

    func _init():
        print("Hello!")

格式

编码和特殊字符

  • 使用换行符(LF)换行,而不是 CRLF 或 CR。(编辑器默认)

  • 在每个文件的末尾使用一个换行符。(编辑器默认)

  • 使用不带字节顺序标记UTF-8 编码。(编辑器默认)

  • 使用制表符代替空格进行缩进。(编辑器默认)

缩进

每个缩进级别必须大于包含它的代码块.

良好的 :

for i in range(10):
    print("hello")

糟糕的 :

for i in range(10):
  print("hello")

for i in range(10):
        print("hello")

使用2个缩进级别来区分续行与常规代码块.

良好的 :

effect.interpolate_property(sprite, "transform/scale",
        sprite.get_scale(), Vector2(2.0, 2.0), 0.3,
        Tween.TRANS_QUAD, Tween.EASE_OUT)

糟糕的 :

effect.interpolate_property(sprite, "transform/scale",
    sprite.get_scale(), Vector2(2.0, 2.0), 0.3,
    Tween.TRANS_QUAD, Tween.EASE_OUT)

此规则的例外是数组, 字典和枚举. 使用单个缩进级别来区分连续行:

良好的 :

var party = [
    "Godot",
    "Godette",
    "Steve",
]

var character_dict = {
    "Name": "Bob",
    "Age": 27,
    "Job": "Mechanic",
}

enum Tiles {
    TILE_BRICK,
    TILE_FLOOR,
    TILE_SPIKE,
    TILE_TELEPORT,
}

糟糕的 :

var party = [
        "Godot",
        "Godette",
        "Steve",
]

var character_dict = {
        "Name": "Bob",
        "Age": 27,
        "Job": "Mechanic",
}

enum Tiles {
        TILE_BRICK,
        TILE_FLOOR,
        TILE_SPIKE,
        TILE_TELEPORT,
}

行尾逗号

请在数组、字典和枚举的最后一行使用逗号。这将使版本控制中的重构更容易,Diff 也更美观,因为添加新元素时不需要修改最后一行。

良好的 :

enum Tiles {
    TILE_BRICK,
    TILE_FLOOR,
    TILE_SPIKE,
    TILE_TELEPORT,
}

糟糕的 :

enum Tiles {
    TILE_BRICK,
    TILE_FLOOR,
    TILE_SPIKE,
    TILE_TELEPORT
}

单行列表中不需要行尾逗号,因此在这种情况下不要添加它们。

良好的 :

enum Tiles {TILE_BRICK, TILE_FLOOR, TILE_SPIKE, TILE_TELEPORT}

糟糕的 :

enum Tiles {TILE_BRICK, TILE_FLOOR, TILE_SPIKE, TILE_TELEPORT,}

空白行

用两个空行包围函数和类定义:

func heal(amount):
    health += amount
    health = min(health, max_health)
    health_changed.emit(health)


func take_damage(amount, effect=null):
    health -= amount
    health = max(0, health)
    health_changed.emit(health)

函数内部使用一个空行来分隔逻辑部分.

备注

在类参考和本文档的短代码片段中,我们会在类和函数定义之间使用单个空行。

行的长度

把每行代码控制在100个字符以内.

如果可以的话, 尽量把行控制在80个字符以下. 这有助于在小屏幕上阅读代码, 并在外部文本编辑器中并排打开两个脚本. 例如, 在查看差异修订时.

一条语句一行

不要在一行上合并多个语句. 不要像C语言那样, 不能使用单行条件语句(三元运算符除外).

良好的 :

if position.x > width:
    position.x = 0

if flag:
    print("flagged")

糟糕的 :

if position.x > width: position.x = 0

if flag: print(