常见的引擎方法和宏

Godot的C++代码库使用了几十种自定义方法和宏, 这些方法和宏几乎在每个文件中都会用到. 本页面向初学者, 但对那些编写自定义C++模块的人也很有用.

打印文本

  1. // Prints a message to standard output.
  2. print_line("Message");
  3. // Prints a message to standard output, but only when the engine
  4. // is started with the `--verbose` command line argument.
  5. print_verbose("Message");
  6. // Prints a formatted error or warning message with a trace.
  7. ERR_PRINT("Message");
  8. WARN_PRINT("Message");
  9. // Prints an error or warning message only once per session.
  10. // This can be used to avoid spamming the console output.
  11. ERR_PRINT_ONCE("Message");
  12. WARN_PRINT_ONCE("Message");

如果你需要在信息中添加占位符, 请使用下面描述的格式字符串.

格式化字符串

vformat() 函数返回一个格式化的 String . 它的行为方式类似于C语言的 sprintf():

  1. vformat("My name is %s.", "Godette");
  2. vformat("%d bugs on the wall!", 1234);
  3. vformat("Pi is approximately %f.", 3.1416);
  4. // Converts the resulting String into a `const char *`.
  5. // You may need to do this if passing the result as an argument
  6. // to a method that expects a `const char *` instead of a String.
  7. vformat("My name is %s.", "Godette").c_str();

在大多数情况下, 尽量使用 vformat() 而不是字符串连接, 因为这样可以使代码更易读.

将整数或浮点数转换为字符串

在直接打印数字时, 这主要是有用的.

  1. // Prints "42" using integer-to-string conversion.
  2. print_line(itos(42));
  3. // Prints "123.45" using real-to-string conversion.
  4. print_line(rtos(123.45));

国际化字符串

Godot的代码库中有两种国际化类型:

  • TTR() . 编辑器(“工具”)的翻译 只在编辑器中处理. 如果用户在他们的一个项目中使用相同的文本, 如果他们提供了翻译, 但不会被翻译. 在为引擎做贡献时, 一般来说, 这是你应该为可本地化字符串使用的宏.

  • RTR() . 运行时翻译 如果提供给定字符串的翻译, 将在项目中自动本地化, 这种翻译不应该用在纯编辑器的代码中.

  1. // Returns the translated string that matches the user's locale settings.
  2. // Translations are located in `editor/translations`.
  3. // The localization template is generated automatically; don't modify it.
  4. TTR("Exit the editor?");

要在可本地化字符串中插入占位符, 请将本地化宏包裹在 vformat() 的调用中, 如下所示:

  1. String file_path = "example.txt";
  2. vformat(TTR("Couldn't open \"%s\" for reading."), file_path);

备注

当同时使用 vformat() 和翻译宏时, 总是将翻译宏包裹在 vformat() 中, 而不是相反. 否则, 字符串永远不会与翻译匹配, 因为当它传递给TranslationServer时, 它的占位符已经被替换了.

限制值

Godot提供了宏, 用于用下限(MAX), 上限(MIN)或两者都有(CLAMP)的值进行限定:

  1. int a = 3;
  2. int b = 5;
  3. MAX(b, 6); // 6
  4. MIN(2, a); // 2
  5. CLAMP(a, 10, 30); // 10

这适用于任何可以与其他值进行比较的类型(如 intfloat ).

微型基准测试

如果你想对一段代码进行基准测试, 但不知道如何使用分析器, 可以使用这个代码段:

  1. uint64_t begin = OS::get_singleton()->get_ticks_usec();
  2. // Your code here...
  3. uint64_t end = OS::get_singleton()->get_ticks_usec();
  4. print_line(vformat("Snippet took %d microseconds", end - begin));

这将打印从 begin 执行到 end 声明之间的花费时间.

备注

如果还不存在, 则可能需要 #include "core/os/os.h" .

当打开一个pull request时, 如果之前没有这个代码, 请确保删除这个代码段以及include.

获取项目/编辑器设置

有四种宏可供选择:

  1. // Returns the specified project setting's value,
  2. // defaulting to `false` if it doesn't exist.
  3. GLOBAL_DEF("section/subsection/value", false);
  4. // Returns the specified editor setting's value,
  5. // defaulting to "Untitled" if it doesn't exist.
  6. EDITOR_DEF("section/subsection/value", "Untitled");

如果在其他地方已经指定了默认值,就不要再指定了,以免重复:

  1. // Returns the value of the project setting.
  2. GLOBAL_GET("section/subsection/value");
  3. // Returns the value of the editor setting.
  4. EDITOR_GET("section/subsection/value");

建议每个设置只使用一次 GLOBAL_DEF/EDITOR_DEF 并在引用它的所有其他位置使用 GLOBAL_GET/EDITOR_GET

错误宏

Godot 提供了许多错误宏,可以更方便地报告错误。

警告

错误宏中的条件和 GDScript 内置的 assert() 函数的相反。如果其中的条件计算结果为 true 而不是 false,就会认为出现了错误。

备注

此处仅记录具有自定义消息的变体,因为新的贡献应该始终使用这些变体。确保提供的自定义消息包括足够的信息,让不了解 C++ 的人也可以诊断问题。如果某个方法拿到了无效的参数,则可以打印有问题的无效值以简化调试。

对于不需要显示可读性信息的内部错误检查,请删除宏名末尾的 _MSG,并且不要提供信息参数。

另外,总是尽量返回可处理的数据,这样引擎才能保持良好的运行。

  1. // Conditionally prints an error message and returns from the function.
  2. // Use this in methods which don't return a value.
  3. ERR_FAIL_COND_MSG(!mesh.is_valid(), vformat("Couldn't load mesh at: %s", path));
  4. // Conditionally prints an error message and returns `0` from the function.
  5. // Use this in methods which must return a value.
  6. ERR_FAIL_COND_V_MSG(rect.x < 0 || rect.y < 0, 0,
  7. "Couldn't calculate the rectangle's area.");
  8. // Prints an error message if `index` is < 0 or >= `SomeEnum::QUALITY_MAX`,
  9. // then returns from the function.
  10. ERR_FAIL_INDEX_MSG(index, SomeEnum::QUALITY_MAX,
  11. vformat("Invalid quality: %d. See SomeEnum for allowed values.", index));
  12. // Prints an error message if `index` is < 0 >= `some_array.size()`,
  13. // then returns `-1` from the function.
  14. ERR_FAIL_INDEX_V_MSG(index, some_array.size(), -1,
  15. vformat("Item %d is out of bounds.", index));
  16. // Unconditionally prints an error message and returns from the function.
  17. // Only use this if you need to perform complex error checking.
  18. if (!complex_error_checking_routine()) {
  19. ERR_FAIL_MSG("Couldn't reload the filesystem cache.");
  20. }
  21. // Unconditionally prints an error message and returns `false` from the function.
  22. // Only use this if you need to perform complex error checking.
  23. if (!complex_error_checking_routine()) {
  24. ERR_FAIL_V_MSG(false, "Couldn't parse the input arguments.");
  25. }
  26. // Crashes the engine. This should generally never be used
  27. // except for testing crash handling code. Godot's philosophy
  28. // is to never crash, both in the editor and in exported projects.
  29. CRASH_NOW_MSG("Can't predict the future! Aborting.");

参见

关于每个错误宏的更多信息,参见 Godot 代码库中的 core/error_macros.h

一些函数会返回错误代码(体现为 Error 返回类型),这个值可以直接从错误宏中返回。参见 core/error_list.h 中的可用错误代码列表。