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!")

書式設定

エンコードと特殊文字

  • CRLFやCRではなく、改行(LF)文字を使用して改行します。(エディタのデフォルト)

  • 各ファイルの最後に1つの改行文字を使用します。(エディタのデフォルト)

  • バイトオーダーマークなしでUTF-8エンコーディングを使用します。(エディタのデフォルト)

  • インデントにはスペースの代わりにタブを使用します。(エディタのデフォルト)

インデント

各インデントレベルは、それを含むブロックより1つ大きくなければなりません。

良い例:

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,
}

末尾のコンマ

配列、辞書、および列挙型の最後の行に末尾のコンマを使用します。これにより、新しい要素を追加するときに最後の行を変更する必要がないため、リファクタリングが容易になり、バージョン管理の差分が改善されます。

良い例:

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,}

空白行

関数とクラスの定義は2つの空白行で囲んで下さい:

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)

論理セクションを区切るには、関数内で1行の空白行を使用します。

注釈

We use a single line between classes and function definitions in the class reference and in short code snippets in this documentation.

行の長さ

コードの個々の行を100文字以内に保ちます。

可能であれば、行を80文字未満に保つようにしてください。これにより、小さなディスプレイでコードを読む場合や、2つのスクリプトを外部テキスト エディタで並べて開くときに役立ちます。たとえば、差分リビジョンを見る場合などです。

1行につき1つのステートメント

複数のステートメントを1行にまとめないでください。Cプログラミングで可能な、1行での条件付きステートメントもありません。

良い例:

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

if flag:
    print("flagged")

悪い例:

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

if flag: print("flagged")

その規則の唯一の例外は三項演算子です:

next_state = "idle" if is_on_floor() else "fall"

Format multiline statements for readability

When you have particularly long if statements or nested ternary expressions, wrapping them over multiple lines improves readability. Since continuation lines are still part of the same expression, 2 indent levels should be used instead of one.

GDScript allows wrapping statements using multiple lines using parentheses or backslashes. Parentheses are favored in this style guide since they make for easier refactoring. With backslashes, you have to ensure that the last line never contains a backslash at the end. With parentheses, you don't have to worry about the last line having a backslash at the end.

When wrapping a conditional expression over multiple lines, the and/or keywords should be placed at the beginning of the line continuation, not at the end of the previous line.

良い例:

var angle_degrees = 135
var quadrant = (
        "northeast" if angle_degrees <= 90
        else "southeast" if angle_degrees <= 180
        else "southwest" if angle_degrees <= 270
        else "northwest"
)

var position = Vector2(250, 350)
if (
        position.x > 200 and position.x < 400
        and position.y > 300 and position.y < 400
):
    pass

悪い例:

var angle_degrees = 135
var quadrant = "northeast" if angle_degrees <= 90 else "southeast" if angle_degrees <= 180 else "southwest" if angle_degrees <= 270 else "northwest"

var position = Vector2(250, 350)
if position.x > 200 and position.x < 400 and position.y > 300 and position.y < 400:
    pass

不要なかっこ()を入れない

Avoid parentheses in expressions and conditional statements. Unless necessary for order of operations or wrapping over multiple lines, they only reduce readability.

良い例:

if is_colliding():
    queue_free()

悪い例:

if (is_colliding()):
    queue_free()

ブール演算子

最もアクセスしやすいように、ブール演算子のプレーンな英語バージョンを優先します:

  • && の代わりに and を使用します。

  • || の代わりに or を使用します。

  • Use not instead of !.

また、ブール演算子をかっこで囲んであいまいさを解消することもできます。これにより、長い式が読みやすくなります。

良い例:

if (foo and bar) or not baz:
    print("condition is true")

悪い例:

if foo && bar || !baz:
    print("condition is true")

コメントスペース

Regular comments (#) and documentation comments (##) should start with a space, but not code that you comment out. Additionally, code region comments (#region/#endregion) must follow that precise syntax, so they should not start with a space.

Using a space for regular and documentation comments helps differentiate text comments from disabled code.

良い例:

# This is a comment.
#print("This is disabled code")

悪い例:

#This is a comment.
# print("This is disabled code")

注釈

In the script editor, to toggle the selected code commented, press Ctrl + K. This feature adds a single # sign at the start of the selected lines.

空白

演算子の前後およびコンマの後には常に1つのスペースを使用します。また、辞書参照や関数呼び出しに余分なスペースを入れないでください。

良い例:

position.x = 5
position.y = target_position.y + 10
dict["key"] = 5
my_array = [4, 5, 6]
print("foo")

悪い例:

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

式を垂直方向に揃えるためにスペースを使用しないでください:

x        = 100
y        = 100
velocity = 500

引用符

シングルクォートを使えばエスケープする文字数を減らせる場合以外は、なるべくダブルクォートを使用するようにします。下記の例を見てください。

# Normal string.
print("hello world")

# Use double quotes as usual to avoid escapes.
print("hello 'world'")

# Use single quotes as an exception to the rule to avoid escapes.
print('hello "world"')

# Both quote styles would require 2 escapes; prefer double quotes if it's a tie.
print("'hello' \"world\"")

Numbers

Don't omit the leading or trailing zero in floating-point numbers. Otherwise, this makes them less readable and harder to distinguish from integers at a glance.

良い例:

var float_number = 0.234
var other_float_number = 13.0

悪い例:

var float_number = .234
var other_float_number = 13.

Use lowercase for letters in hexadecimal numbers, as their lower height makes the number easier to read.

良い例:

var hex_number = 0xfb8c0b

悪い例:

var hex_number = 0xFB8C0B

Take advantage of GDScript's underscores in literals to make large numbers more readable.

良い例:

var large_number = 1_234_567_890
var large_hex_number = 0xffff_f8f8_0000
var large_bin_number = 0b1101_0010_1010
# Numbers lower than 1000000 generally don't need separators.
var small_number = 12345

悪い例:

var large_number = 1234567890
var large_hex_number = 0xfffff8f80000
var large_bin_number = 0b110100101010
# Numbers lower than 1000000 generally don't need separators.
var small_number = 12_345

命名規則

これらの命名規則は、Godot Engineスタイルに従います。これらを壊すと、コードが組み込みの命名規則と衝突し、コードの一貫性が失われます。

File names

Use snake_case for file names. For named classes, convert the PascalCase class name to snake_case:

# This file should be saved as `weapon.gd`.
class_name Weapon
extends Node
# This file should be saved as `yaml_parser.gd`.
class_name YAMLParser
extends Object

This is consistent with how C++ files are named in Godot's source code. This also avoids case sensitivity issues that can crop up when exporting a project from Windows to other platforms.

クラスとノード

クラス名とノード名には PascalCase を使用します:

extends CharacterBody3D

クラスを定数または変数にロードするときにもPascalCaseを使用します:

const Weapon = preload("res://weapon.gd")

関数と変数

関数と変数に名前を付けるには、snake_caseを使用します:

var particle_effect
func load_level():

ユーザーがオーバーライドする必要がある仮想メソッド関数、プライベート関数、およびプライベート変数の前に単一のアンダースコア(_)を追加します:

var _counter = 0
func _recalculate_path():

シグナル

過去形を使用してシグナルに名前を付けます:

signal door_opened
signal score_changed

定数と列挙型

CONSTANT_CASEで定数を記述します。つまり、すべて大文字でアンダースコア(_)を使用して単語を区切ります:

const MAX_SPEED = 200

列挙型の名前にはPascalCaseを、そのメンバーには定数なのでCONSTANT_CASEを使用します:

enum Element {
    EARTH,
    WATER,
    AIR,
    FIRE,
}

コードの順序

この最初のセクションでは、コードの順序に焦点を当てます。書式設定については、書式設定 を参照してください。命名規則については、命名規則 を参照してください。

次のようにGDScriptコードを整理することをお勧めします:

01. @tool
02. class_name
03. extends
04. # docstring

05. signals
06. enums
07. constants
08. @export variables
09. public variables
10. private variables
11. @onready variables

12. optional built-in virtual _init method
13. optional built-in virtual _enter_tree() method
14. built-in virtual _ready method
15. remaining built-in virtual methods
16. public methods
17. private methods
18. subclasses

順序を最適化して、コードを上から下に読みやすくし、コードを初めて読む開発者がどのように機能するかを理解しやすくし、変数宣言の順序に関連するエラーを回避します。

このコードの順序は、次の4つの経験則に従います:

  1. プロパティとシグナルが最初に来て、メソッドがそれに続きます。

  2. パブリックはプライベートの前に来ます。

  3. 仮想コールバックは、クラスのインターフェースの前に来ます。

  4. オブジェクトの構築関数と初期化関数、_init_ready は実行時にオブジェクトを変更する関数の前に来ます。

クラス宣言

If the code is meant to run in the editor, place the @tool annotation on the first line of the script.

Follow with the class_name if necessary. You can turn a GDScript file into a global type in your project using this feature. For more information, see GDScript reference.

Then, add the extends keyword if the class extends a built-in type.

Following that, you should have the class's optional documentation comments. You can use that to explain the role of your class to your teammates, how it works, and how other developers should use it, for example.

class_name MyNode
extends Node
## A brief description of the class's role and functionality.
##
## The description of the script, what it can do,
## and any further detail.

シグナルとプロパティ

追加ドキュメントの後に、シグナル宣言、続いてプロパティ、つまりメンバー変数を記述します。

列挙型は、他のプロパティのエクスポートヒントとして使用できるため、シグナルの後に来る必要があります。

次に、定数、エクスポートされた変数、public、private、およびonready変数をこの順序で記述します。

signal player_spawned(position)

enum Jobs {KNIGHT, WIZARD, ROGUE, HEALER, SHAMAN}

const MAX_LIVES = 3

@export var job: Jobs = Jobs.KNIGHT
@export var max_health = 50
@export var attack = 5

var health = max_health:
    set(new_health):
        health = new_health

var _speed = 300.0

@onready var sword = get_node("Sword")
@onready var gun = get_node("Gun")

注釈

GDScriptコンパイラは、_ready コールバックの直前にonready変数を評価します。これを使用して、ノードの依存関係をキャッシュしたり、クラスが依存しているシーン内の子ノードを取得したりできます。これは上記の例が示すものです。

Member variables

Don't declare member variables if they are only used locally in a method, as it makes the code more difficult to follow. Instead, declare them as local variables in the method's body.

Local variables

Declare local variables as close as possible to their first use. This makes it easier to follow the code, without having to scroll too much to find where the variable was declared.

メソッドと静的関数

クラスのプロパティの後にメソッドが続きます。

エンジンがメモリ内にオブジェクトを作成するときに呼び出す _init() コールバックメソッドで開始します。 そしてGodotがノードをシーンツリーに追加するときに呼び出す _ready() コールバックを続けます。

These functions should come first because they show how the object is initialized.

_unhandled_input()_physics_process のような、その他の組み込みの仮想コールバックが次に来る必要があります。これらは、オブジェクトのメインループとゲームエンジンとの相互作用を制御します。

クラスの残りのインターフェイスであるパブリックメソッドとプライベートメソッドは、この順序でその後に続きます。

func _init():
    add_to_group("state_machine")


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


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


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 _on_state_changed(previous, new):
    print("state changed")
    state_changed.emit()

静的型付け

Godot 3.1から、GDScriptはオプショナルな静的型付けをサポートしています。

Declared types

To declare a variable's type, use <variable>: <type>:

var health: int = 0

関数の戻り値の定義をするには、``-> <type>``を使ってください:

func heal(amount: int) -> void:

Inferred types

In most cases you can let the compiler infer the type, using :=. Prefer := when the type is written on the same line as the assignment, otherwise prefer writing the type explicitly.

良い例:

var health: int = 0 # The type can be int or float, and thus should be stated explicitly.
var direction := Vector3(1, 2, 3) # The type is clearly inferred as Vector3.

Include the type hint when the type is ambiguous, and omit the type hint when it's redundant.

悪い例:

var health := 0 # Typed as int, but it could be that float was intended.
var direction: Vector3 = Vector3(1, 2, 3) # The type hint has redundant information.

# What type is this? It's not immediately clear to the reader, so it's bad.
var value := complex_function()

In some cases, the type must be stated explicitly, otherwise the behavior will not be as expected because the compiler will only be able to use the function's return type. For example, get_node() cannot infer a type unless the scene or file of the node is loaded in memory. In this case, you should set the type explicitly.

良い例:

@onready var health_bar: ProgressBar = get_node("UI/LifeBar")

Alternatively, you can use the as keyword to cast the return type, and that type will be used to infer the type of the var.

@onready var health_bar := get_node("UI/LifeBar") as ProgressBar
# health_bar will be typed as ProgressBar

This option is also considered more type-safe than the first.

悪い例:

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