通用方法与宏
最后同步日期:2026-04-15 | Godot 官方原文 — Common engine methods and macros
通用方法与宏
Godot 的 C++ 代码库里有几十个自定义的方法和宏,几乎在每个源文件中都能看到它们的身影。本页主要面向初学贡献引擎代码的开发者,但对编写自定义 C++ 模块的人也同样有用。
打个比方:这些方法和宏就像"工具箱"——你不需要记住每一个,但知道有哪些工具可以在关键时刻省去大量重复劳动。
打印文本
在引擎代码中,有几种不同的打印方式,适用于不同场景:
// 向标准输出打印一条消息。
print_line("Message");
// 非 String 类型的参数会自动转换为 String 再打印。
// 如果传入多个参数,它们会用空格连接在一起。
print_line("There are", 123, "nodes");
// 向标准输出打印一条消息,但只在引擎以 --verbose 命令行参数启动时才会显示。
print_verbose("Message");
// 使用 BBCode 富文本格式打印消息。
// 支持一部分 RichTextLabel 所支持的 BBCode 标签,
// 在编辑器的 Output 面板中也会以格式化形式显示。
// 在 Windows 上,需要 Windows 10 或更高版本才能在终端中显示格式。
print_line_rich("[b]Bold[/b], [color=red]Red text[/color]");
// 打印一条带调用栈的格式化错误或警告消息。
ERR_PRINT("Message");
WARN_PRINT("Message");
// 每个"会话"只打印一次错误或警告消息。
// 可以用来避免控制台输出被刷屏。
ERR_PRINT_ONCE("Message");
WARN_PRINT_ONCE("Message");如果你需要在消息中插入变量值,请使用下面介绍的格式化字符串方法。
格式化字符串
vformat() 函数返回一个格式化后的 String。它的行为类似于 C 语言的 sprintf():
vformat("My name is %s.", "Godette");
vformat("%d bugs on the wall!", 1234);
vformat("Pi is approximately %f.", 3.1416);
// 将结果 String 转换为 const char *。
// 如果你需要将结果传递给一个期望 const char * 而非 String 的方法时,
// 可能需要这样做。
vformat("My name is %s.", "Godette").c_str();在大多数情况下,尽量使用 vformat() 而不是字符串拼接,因为这样代码更易读。
将整数或浮点数转换为字符串
使用 print_line() 打印数字时不需要手动转换,但在其他一些场景中你可能需要手动转换。
// 使用整数转字符串函数,将 42 转为 "42"。
String int_to_string = itos(42);
// 使用实数转字符串函数,将 123.45 转为 "123.45"。
String real_to_string = rtos(123.45);国际化字符串
Godot 代码库中有两种国际化宏:
TTR():编辑器("工具")翻译——只在编辑器中生效。如果用户在自己的项目中使用相同的文本,即使他们提供了翻译也不会被翻译。在为引擎贡献代码时,通常应该使用这个宏。RTR():运行时翻译——如果用户为给定字符串提供了翻译,在项目中会自动本地化。这种翻译不应该在仅限编辑器的代码中使用。
// 返回与用户区域设置匹配的翻译字符串。
// 翻译文件位于 editor/translations 目录。
// 翻译模板是自动生成的,不要手动修改。
TTR("Exit the editor?");要在可翻译字符串中插入占位符,将翻译宏包裹在 vformat() 调用中:
String file_path = "example.txt";
vformat(TTR("Couldn't open \"%s\" for reading."), file_path);提示
当同时使用 vformat() 和翻译宏时,始终将翻译宏包裹在 vformat() 中,而不是反过来。否则,字符串在传递给 TranslationServer 时占位符已经被替换了,永远不会匹配到翻译。
限制值的范围(Clamp)
Godot 提供了几个宏来限制值的范围:
MAX(a, b):取较大值——确保结果不低于某个下限MIN(a, b):取较小值——确保结果不超过某个上限CLAMP(value, min, max):同时限制上下界
int a = 3;
int b = 5;
MAX(b, 6); // 结果为 6(6 比 5 大)
MIN(2, a); // 结果为 2(2 比 3 小)
CLAMP(a, 10, 30); // 结果为 10(3 被"夹"到 10-30 的范围内)这些宏适用于任何可以互相比较的类型(如 int、float 等)。
微基准测试
如果你想测试某段代码的执行速度,但不会用性能分析器(profiler),可以用这个代码片段:
uint64_t begin = Time::get_singleton()->get_ticks_usec();
// 在这里放你要测试的代码...
uint64_t end = Time::get_singleton()->get_ticks_usec();
print_line(vformat("Snippet took %d microseconds", end - begin));这会打印从 begin 声明到 end 声明之间经过的微秒数。
提示
你可能需要添加 #include "core/os/os.h"(如果该文件尚未包含它的话)。
当你提交 Pull Request 时,记得删除这个测试代码片段以及你添加的 include(如果之前没有的话)。
获取项目/编辑器设置
Godot 提供了四个宏来读取项目设置和编辑器设置:
// 返回指定项目设置的值,如果不存在则默认为 false。
GLOBAL_DEF("section/subsection/value", false);
// 返回指定编辑器设置的值,如果不存在则默认为 "Untitled"。
EDITOR_DEF("section/subsection/value", "Untitled");如果默认值已经在其他地方指定过了,就不要重复指定,以免造成冗余:
// 返回项目设置的值(默认值已在别处定义)。
GLOBAL_GET("section/subsection/value");
// 返回编辑器设置的值(默认值已在别处定义)。
EDITOR_GET("section/subsection/value");最佳实践是:每个设置只在一处使用 GLOBAL_DEF/EDITOR_DEF(定义默认值),在其他所有引用该设置的地方使用 GLOBAL_GET/EDITOR_GET。
错误宏
Godot 提供了大量错误宏,让错误报告更加方便。
注意
错误宏中的条件判断方式与 GDScript 的 assert() 函数相反。当宏内的条件计算为 true 时才会触发错误,而不是 false。
提示
以下只列出了带自定义消息(_MSG 后缀)的变体,因为新代码中应该始终使用这些变体。请确保提供的自定义消息包含足够的信息,即使不懂 C++ 的人也能诊断问题。如果方法收到了无效参数,可以把无效值打印出来以便调试。
对于不需要显示人类可读消息的内部错误检查,可以去掉宏名末尾的 _MSG 并且不提供消息参数。
另外,始终尽量返回可处理的数据,让引擎能够继续正常运行。
// 如果条件满足,打印错误消息并从函数返回。
// 用于没有返回值的函数。
ERR_FAIL_COND_MSG(!mesh.is_valid(),
vformat("Couldn't load mesh at: %s", path));
// 如果条件满足,打印错误消息并从函数返回 0。
// 用于有返回值的函数。
ERR_FAIL_COND_V_MSG(rect.x < 0 || rect.y < 0, 0,
"Couldn't calculate the rectangle's area.");
// 如果 index < 0 或 index >= SomeEnum::QUALITY_MAX,
// 打印错误消息并从函数返回。
ERR_FAIL_INDEX_MSG(index, SomeEnum::QUALITY_MAX,
vformat("Invalid quality: %d. See SomeEnum for allowed values.", index));
// 如果 index < 0 或 index >= some_array.size(),
// 打印错误消息并从函数返回 -1。
ERR_FAIL_INDEX_V_MSG(index, some_array.size(), -1,
vformat("Item %d is out of bounds.", index));
// 无条件打印错误消息并从函数返回。
// 只在需要复杂错误检查时使用。
if (!complex_error_checking_routine()) {
ERR_FAIL_MSG("Couldn't reload the filesystem cache.");
}
// 无条件打印错误消息并从函数返回 false。
// 只在需要复杂错误检查时使用。
if (!complex_error_checking_routine()) {
ERR_FAIL_V_MSG(false, "Couldn't parse the input arguments.");
}
// 使引擎崩溃。通常不应该使用这个宏,
// 除非是为了测试崩溃处理代码。
// Godot 的设计理念是永远不崩溃,无论是在编辑器中还是在导出的项目中。
CRASH_NOW_MSG("Can't predict the future! Aborting.");错误宏速查表
| 宏名称 | 作用 | 使用场景 |
|---|---|---|
ERR_FAIL_COND_MSG(cond, msg) | 条件为真时返回(无返回值) | 无返回值的函数中的条件检查 |
ERR_FAIL_COND_V_MSG(cond, ret, msg) | 条件为真时返回指定值 | 有返回值的函数中的条件检查 |
ERR_FAIL_INDEX_MSG(idx, size, msg) | 索引越界时返回(无返回值) | 数组/枚举索引范围检查 |
ERR_FAIL_INDEX_V_MSG(idx, size, ret, msg) | 索引越界时返回指定值 | 有返回值的索引检查 |
ERR_FAIL_MSG(msg) | 无条件返回(无返回值) | 复杂错误检查后返回 |
ERR_FAIL_V_MSG(ret, msg) | 无条件返回指定值 | 复杂错误检查后返回值 |
CRASH_NOW_MSG(msg) | 使引擎崩溃 | 仅用于测试崩溃处理 |
