Up to date

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

程式碼樣式方針

在參與貢獻 Godot 原始碼時需要遵守下述樣式方針。其中的一些規則會在 CI (持續整合, Continuos Integration) 過程中自動檢查,而審閱者也會要求你修正一些潛在的問題。因此,最好先依照下屬方式設定系統,並確保你的 Commit 都有符合本方針。

C++ 與 Objective-C

C++ 與 Objective-C 沒有明文的方針,但我們有由各個開發者認定的樣式,且會依照 clang-format 程式碼美化工具強制套用。該工具會處理我們所有的管理。下面舉例幾個:

  • 縮排與對齊都是使用 Tab 字元 (分別使用 1 個與 2 個 Tab)

  • 在數學與賦值運算子的周圍以及逗號後加上 1 個空格

  • 指標與參照運算子要加到變數識別項前,而不是型別名稱前

  • 有關標頭檔引用,請繼續閱讀以瞭解詳情

clang-format 所使用的規則列在 Godot 儲存庫中的 .clang-format 檔案內。

As long as you ensure that your style matches the surrounding code and that you not introducing trailing whitespace or space-based indentation, you should be fine. If you plan to contribute regularly, however, we strongly advise that you set up clang-format locally to check and automatically fix all your commits.

警告

Godot's code style should not be applied to third-party code, i.e. that is included in Godot's source tree but was not written specifically for our project. Such code usually comes from different upstream projects with their own style guides (or lack thereof), and don't want to introduce differences that would make syncing with upstream repositories harder.

第三方程式碼通常放在 thirdparty/ 資料夾內,因此可以輕鬆地在格式化腳本中排除掉。但有些稀有的例子,我們可能會直接在 Godot 的檔案中使用第三方程式碼片端,這時候可以使用 /* clang-format off *//* clang-format on */ 來讓 clang-format 忽略一段程式碼。

也參考

這些規範只涉及程式碼的格式化。拉取請求中所允許的語言功能列表請參閱 Bug 分級方針

在本機上使用 clang-format

首先,必須要安裝 clang-format。目前,必須要使用 clang-format 8.x 以相容 Godot 的格式。更新版本可能適用,但較舊版本有 Bug 且會使目前程式碼的格式跑掉。

安裝

下列為如何安裝 clang-format:

  • Linux:通常直接於發行版的 clang 工具鏈中附帶提供。若你使用的發行版提供了不合需求的版本,可以從 LLVM 網站 上下載預先編譯好的版本。而若使用 Debian 衍生版本,則可以使用這個 上游軟體倉

  • macOS 與 Windows:可以從 LLVM 網站 下載預先編譯好的二進位檔。可能會需要將二進位檔的資料夾加到系統的 PATH 環境路徑中以便直接呼叫 clang-format

要將 clang-format 套用到修改中有幾個方法:

手動使用

You can apply clang-format manually for one or more files with the following command:

clang-format -i <path/to/file(s)>
  • -i 代表改動應直接寫入到檔案內 (clang-format 預設只會將修正後的版本輸出到終端機上)。

  • 該路徑可指向多個檔案,可以直接指定多個檔案,或是像一般 Unix Shell 一樣使用萬用字元。在使用萬用字元時請注意不要將 clang-format 套用到 Godot 資料夾內編譯後的物件上 (.o 與 .a 檔案)。因此最好使用 core/*.{cpp,h} 而不是 core/*

Pre-commit Hook

為了更容易使用,我們提供了用於 Git 的 Pre-commit Hook,可以自動在所有 Commit 上執行 clang-format 並進行檢查,然後能將其更改套用到最終 Commit 上。

This "hook" is a script that can be found in misc/hooks, refer to that folder's README.md for installation instructions.

如果 clang-format 不在 PATH 中的話,則可能需要編輯 pre-commit-clang-format 來指向正確的二進位檔才能使用。該 Hook 已在 Linux 與 macOS 上測試過,但在 Windows 上的 Git Shell 應該也可以使用。

IDE 外掛

Most IDEs or code editors have beautifier plugins that can be configured to run clang-format automatically, for example, each time you save a file.

此處僅列出部分用於一些 IDE 的美化外掛:

(Pull requests are welcome to extend this list with tested plugins.)

標頭引用

建立新的 C++ 或 Objective-C 檔案或在現有檔案內引用新標頭檔時,必須遵守下列規則:

  • 檔案的頭幾行必須為 Godot 的版權標頭與 MIT 授權協議,請從其他檔案內複製過來。請記得更改檔案名稱。

  • .h 標頭檔內,Include 防護 (Include Guard) 應為 FILENAME_H 的格式。

  • .cpp 檔案 (如 filename.cpp) 中,第一個 Include 應為類別定義的檔案 (如 #include "filename.h"),並接上一行空行以作分隔。

  • 接下來的是 Godot 程式碼的其他標頭檔,按字母順序引入 (會由 clang-format 強制執行),並使用相對於根目錄的路徑。這些 Include 應以引號包含,如 #include "core/object.h" 。Godot 標頭檔 Include 區塊後方應包含一行空行以作分隔。

  • 最後接著是第三方標頭檔 (也就是從 thirdparty 或系統 Include 路徑內來的),應以 < 與 > 符號來 Include,如 #include <png.h> 。第三方標頭檔區塊後也應加上一行空行以作區隔。

  • Godot 標頭檔與第三方標頭檔都應在需要這些標頭檔的檔案內 Include,也就是當使用宣告式程式碼時應在 .h 標頭內,只有使用命令式程式碼時才應在 .cpp 內引入。

範例:

/**************************************************************************/
/*  my_new_file.h                                                         */
/**************************************************************************/
/*                         This file is part of:                          */
/*                             GODOT ENGINE                               */
/*                        https://godotengine.org                         */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.                  */
/*                                                                        */
/* Permission is hereby granted, free of charge, to any person obtaining  */
/* a copy of this software and associated documentation files (the        */
/* "Software"), to deal in the Software without restriction, including    */
/* without limitation the rights to use, copy, modify, merge, publish,    */
/* distribute, sublicense, and/or sell copies of the Software, and to     */
/* permit persons to whom the Software is furnished to do so, subject to  */
/* the following conditions:                                              */
/*                                                                        */
/* The above copyright notice and this permission notice shall be         */
/* included in all copies or substantial portions of the Software.        */
/*                                                                        */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,        */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF     */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY   */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,   */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE      */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                 */
/**************************************************************************/

#ifndef MY_NEW_FILE_H
#define MY_NEW_FILE_H

#include "core/hash_map.h"
#include "core/list.h"
#include "scene/gui/control.h"

#include <png.h>

...

#endif // MY_NEW_FILE_H
/**************************************************************************/
/*  my_new_file.cpp                                                       */
/**************************************************************************/
/*                         This file is part of:                          */
/*                             GODOT ENGINE                               */
/*                        https://godotengine.org                         */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.                  */
/*                                                                        */
/* Permission is hereby granted, free of charge, to any person obtaining  */
/* a copy of this software and associated documentation files (the        */
/* "Software"), to deal in the Software without restriction, including    */
/* without limitation the rights to use, copy, modify, merge, publish,    */
/* distribute, sublicense, and/or sell copies of the Software, and to     */
/* permit persons to whom the Software is furnished to do so, subject to  */
/* the following conditions:                                              */
/*                                                                        */
/* The above copyright notice and this permission notice shall be         */
/* included in all copies or substantial portions of the Software.        */
/*                                                                        */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,        */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF     */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY   */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,   */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE      */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                 */
/**************************************************************************/

#include "my_new_file.h"

#include "core/math/math_funcs.h"
#include "scene/gui/line_edit.h"

#include <zlib.h>
#include <zstd.h>

Java

Godot 的 Java 程式碼 (大部分都在 platform/android 內) 也會強制由 clang-format 套用,因此請參考上方的說明設定 clang-format。請注意,樣式指南僅套用至由 Godot 撰寫且由 Godot 維護的程式碼,如 java/src/com/google 子資料夾內的第三方程式碼則不應套用。

Python

Godot 的 SCons 建置系統是以 Python 撰寫的,而程式碼中還有多個腳本也是使用 Python。

這些檔案,我們遵守 Black style guide 。請使用 Black 來黑化你的 Python 程式碼。

在本機上使用 Black

首先,必須要先安裝 Black。要執行 Black 需要至少 Python 3.6.0+。

安裝

安裝 Black:

pip3 install black --user

接著有幾種方式可以將 Black 套用至修改上:

手動使用

可以使用下列指令手動套用 black 至一個或多個檔案:

black -l 120 <path/to/file(s)>
  • -l 120 表示每行最多允許 120 個字元。這個數字是由多位開發人員公認的。

  • 路徑可以指向多個檔案,可以直接寫出多個檔案,或是使用如一般 Unix Shell 的萬用字元。

Pre-commit Hook

為了簡化使用,我們也提供了用於 Git 的 Pre-commit Hook,會在所有 Commit 上自動執行 Black,並允許將這些修改套用至最終的 Commit 上。

該「hook」是放在 misc/hooks 內的一個腳本檔。請參考該資料夾中的 README.md 以瞭解安裝說明。

編輯器整合

Many IDEs or code editors have beautifier plugins that can be configured to run black automatically, for example, each time you save a file. For details, you can check Black editor integration.

C# 風格指南

本注釋風格指南適用於Godot程式碼庫中使用的所有程式設計語言.

  • 以空間字元開始注釋, 以將其與禁用程式碼區分開來.

  • 注釋使用句子大小寫. 注釋以大寫字母開頭, 並始終以句號結束.

  • 使用反引號引用變數和函式名和值.

  • 將注釋控制在~100個字元。

  • 你可以在需要的時候使用 TODO: , FIXME: , NOTE: , HACK: 作為強調.

範例

// Compute the first 10,000 decimals of Pi.
// FIXME: Don't crash when computing the 1,337th decimal due to `increment`
//        being negative.

不要在注釋中重複程式碼的內容. 解釋 為什麼 而不是 如何 .

錯誤例 :

// Draw loading screen.
draw_load_screen();

你可以在函式或巨集定義上面使用Javadoc風格的注釋. 建議只對不公開給腳本的方法使用Javadoc風格的注釋. 這是因為公開的方法應該在 class reference XML 中進行記錄.

範例

/**
 * Returns the number of nodes in the universe.
 * This can potentially be a very large number, hence the 64-bit return type.
 */
uint64_t Universe::get_node_count() {
    // ...
}

對於成員變數, 不要使用Javadoc式的注釋, 而是使用單行注釋:

class Universe {
    // The cached number of nodes in the universe.
    // This value may not always be up-to-date with the current number of nodes
    // in the universe.
    uint64_t node_count_cached = 0;
};