Up to date

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

代码风格规范

在给 Godot 的源代码做贡献时,你需要遵循下面概述的样式规范。其中一些是通过持续集成过程进行检查的,评审人员将要求你修复潜在的问题,因此最好按照下面概述的方式设置系统,以确保所有提交都遵循规范。

C++ 和 Objective-C

There are no written guidelines, but the code style agreed upon by the developers is enforced via the clang-format code beautifier, which takes care for you of all our conventions. To name a few:

  • 缩进和对齐都是基于制表符的(分别是一个和两个制表符)

  • 数学和赋值运算符以及逗号后面有一个空格

  • 指针和引用运算符附加到变量标识符,而不是类型名称

  • 有关头文件的引入,请参见下文

Clang 格式使用的规则在 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忽略某块儿的代码.

参见

这些规范只涉及代码的格式化。拉取请求中所允许的语言特性列表请参阅 C++ 使用规范

在本地使用 clang-format

首先,你需要安装 clang-format。截至目前,你需要使用 clang-format 13 才能与 Godot 的格式兼容。后续版本可能也能用,但更早的版本就可能无法支持所有用到的选项,或者使用不同的格式,导致拉取请求存在样式问题。

安装

以下是如何安装 clang-format:

  • Linux: It will usually be available out-of-the-box with the clang toolchain packaged by your distribution. If your distro version is not the required one, you can download a pre-compiled version from the LLVM website, or if you are on a Debian derivative, use the upstream repos.

  • macOS and Windows: You can download precompiled binaries from the LLVM website. You may need to add the path to the binary's folder to your system's PATH environment variable to be able to call clang-format out of the box.

然后, 你就有不同的可能性将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中的通配符. 在通配时要小心, 以免对Godot树中的已编译对象(.o和.a文件)运行clang格式. 因此, 最好使用 core/*. {cpp,h} 而不是 core/*.

预提交钩子

为了易于使用, 我们为Git提供了一个预提交钩子, 它将在你的所有提交上自动运行clang-format来检查它们, 并允许你在最终提交中应用其更改.

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 来指向正确的二进制格式才能工作. 钩子在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 头文件中, 引入防护应该与 FILENAME_H 形式一起使用.

  • .cpp 文件(如 filename.cpp )中, 第一个引入应该是声明类的那个(例如 #include "filename.h"), 然后使用空行分隔.

  • 然后来自Godot自己的代码库的标头, 按字母顺序(由 clang-format 强制)引入, 并具有相对于根文件夹的路径. 这些引入应该用引号来完成, 例如 #include "core/object.h". 然后,Godot标头引入的块应用一个空行以进行分隔.

  • 最后, 第三方头文件(无论是来自 thirdparty 还是来自系统的包含路径)接下来, 应该用 < and > 符号包含, 例如 #include <png.h> . 第三方头文件块的后面也应该有一个空行来分隔.

  • Godot和第三方标头应包含在需要它们的文件中, 即, 如果在声明性代码中使用, 则在 .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 来执行的, 所以请看上面的说明来设置它. 请记住, 本风格规则只适用于Godot编写和维护的代码, 而不是第三方代码, 如 java/src/com/google 子文件夹.

Python

Godot的SCons构建系统是用Python编写的, 源代码树中包含的各种脚本也使用Python.

对于这些, 我们遵循 黑色风格指南 . 使用 Black使Python 更改变黑 .

本地使用 black

首先你需要安装 Black。Black 需要 Python 3.7+ 才能运行。

安装

下面介绍如何安装black:

pip3 install black --user

然后, 你有不同的可能性将黑色应用于你的更改:

手动使用

你可以使用以下命令将 black 手动应用于一个或多个文件:

black -l 120 <path/to/file(s)>
  • -l 120 表示每行允许的字符数为 120。这个数字是经过开发者们商定的。

  • 该路径可以指向多个文件, 可以一个接一个, 也可以像典型的unixshell一样使用通配符.

预提交钩子

为了便于使用, 我们为Git提供了一个预提交钩子, 它将在你的所有提交上自动运行以检查你的提交, 并让你在最终提交中应用其更改.

这个 "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.

注释风格指南

本注释风格指南适用于Godot代码库中使用的所有编程语言.

  • 以空间字符开始注释, 以将其与禁用代码区分开来.

  • 注释使用句子大小写. 注释以大写字母开头, 并始终以句号结束.

  • 使用反引号引用变量和函数名和值.

  • 将注释控制在~100个字符。

  • You can use TODO:, FIXME:, NOTE:, or HACK: as admonitions when needed.

示例:

// 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;
};