常用引擎方法與巨集
Godot 的 C++ 原始碼中使用了數十種自訂方法與巨集,幾乎每個檔案都會用到。本頁面主要針對新手貢獻者,但對於撰寫自訂 C++ 模組的開發者也很實用。
列印文字
// Prints a message to standard output.
print_line("Message");
// Non-String arguments are automatically converted to String for printing.
// If passing several arguments, they will be concatenated together with a
// space between each argument.
print_line("There are", 123, "nodes");
// Prints a message to standard output, but only when the engine
// is started with the `--verbose` command line argument.
print_verbose("Message");
// Prints a rich-formatted message using BBCode to standard output.
// This supports a subset of BBCode tags supported by RichTextLabel
// and will also appear formatted in the editor Output panel.
// On Windows, this requires Windows 10 or later to work in the terminal.
print_line_rich("[b]Bold[/b], [color=red]Red text[/color]")
// Prints a formatted error or warning message with a trace.
ERR_PRINT("Message");
WARN_PRINT("Message");
// Prints an error or warning message only once per session.
// This can be used to avoid spamming the console output.
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);
// Converts the resulting String into a `const char *`.
// You may need to do this if passing the result as an argument
// to a method that expects a `const char *` instead of a String.
vformat("My name is %s.", "Godette").c_str();
大多數情況下,建議使用 vformat() 來取代字串串接,這樣能讓程式碼更易讀。
將整數或浮點數轉換為字串
使用 print_line() 列印數字時不需要這麼做,但在其他情境下仍可能需要手動轉型。
// Stores the string "42" using integer-to-string conversion.
String int_to_string = itos(42);
// Stores the string "123.45" using real-to-string conversion.
String real_to_string = rtos(123.45);
國際化字串
Godot 的程式碼中有兩種國際化方式:
TTR():編輯器(「工具」)翻譯 只會在編輯器內處理。如果使用者在專案中用到相同文字,即使有提供翻譯也不會套用。為引擎貢獻時,這通常是處理可翻譯字串時應該使用的巨集。RTR():執行階段翻譯 若專案有提供對應字串的翻譯,則會自動在遊戲運行時套用。這類翻譯不應用於僅限編輯器的程式碼。
// Returns the translated string that matches the user's locale settings.
// Translations are located in `editor/translations`.
// The localization template is generated automatically; don't modify it.
TTR("Exit the editor?");
若要在可翻譯字串中插入預留位置,請如以下範例將在地化巨集包在 vformat() 呼叫中:
String file_path = "example.txt";
vformat(TTR("Couldn't open \"%s\" for reading."), file_path);
備註
當 vformat() 與翻譯巨集同時使用時,務必將翻譯巨集放在 vformat() 內部,而不是反過來。否則,字串送到 TranslationServer 時預留位置已經被取代,將無法正確翻譯。
限制數值範圍
Godot 提供用來限制數值下界(MAX)、上界(MIN)或同時限制上下界(CLAMP)的巨集:
int a = 3;
int b = 5;
MAX(b, 6); // 6
MIN(2, a); // 2
CLAMP(a, 10, 30); // 10
這些巨集適用於所有可互相比較的型別(如 int 和 float)。
微型效能檢測
如果你想對某段程式碼進行效能檢測,但不熟悉效能分析工具,可以使用以下程式碼片段:
uint64_t begin = Time::get_singleton()->get_ticks_usec();
// Your code here...
uint64_t end = Time::get_singleton()->get_ticks_usec();
print_line(vformat("Snippet took %d microseconds", end - begin));
這會印出從 begin 宣告到 end 宣告之間所花費的時間。
備註
若尚未包含 #include "core/os/time.h",請記得加上。
在送出 Pull Request 時,請務必移除這段程式碼片段以及包含的檔案(如果本來沒有的話)。
取得專案/編輯器設定
可用於此的巨集有四種:
// Returns the specified project setting's value,
// defaulting to `false` if it doesn't exist.
GLOBAL_DEF("section/subsection/value", false);
// Returns the specified editor setting's value,
// defaulting to "Untitled" if it doesn't exist.
EDITOR_DEF("section/subsection/value", "Untitled");
若預設值已於其他地方指定,請勿重複指定以避免冗餘:
// Returns the value of the project setting.
GLOBAL_GET("section/subsection/value");
// Returns the value of the editor setting.
EDITOR_GET("section/subsection/value");
建議每個設定僅用一次 GLOBAL_DEF/EDITOR_DEF,其他需要使用時則以 GLOBAL_GET/EDITOR_GET 讀取。
錯誤巨集
Godot 提供多種錯誤巨集,讓錯誤回報更加便利。
警告
錯誤巨集中的條件判斷方式與 GDScript 內建的 assert() 函式**相反**。當條件式為 true 時就會觸發錯誤,而非 false。
備註
這裡僅說明帶有自訂訊息的變體,因為建議所有新貢獻都應優先使用這些形式。請確保自訂訊息中包含足夠資訊,即使不懂 C++ 也能協助診斷問題。若方法收到無效參數,也可印出該值以便除錯。
若僅需內部錯誤檢查且不需要顯示人類可讀訊息,可將巨集名稱結尾的 _MSG 移除,並省略訊息參數。
同時,請盡量回傳可處理的資料,以便引擎可以正常持續運作。
// Conditionally prints an error message and returns from the function.
// Use this in methods which don't return a value.
ERR_FAIL_COND_MSG(!mesh.is_valid(), vformat("Couldn't load mesh at: %s", path));
// Conditionally prints an error message and returns `0` from the function.
// Use this in methods which must return a value.
ERR_FAIL_COND_V_MSG(rect.x < 0 || rect.y < 0, 0,
"Couldn't calculate the rectangle's area.");
// Prints an error message if `index` is < 0 or >= `SomeEnum::QUALITY_MAX`,
// then returns from the function.
ERR_FAIL_INDEX_MSG(index, SomeEnum::QUALITY_MAX,
vformat("Invalid quality: %d. See SomeEnum for allowed values.", index));
// Prints an error message if `index` is < 0 >= `some_array.size()`,
// then returns `-1` from the function.
ERR_FAIL_INDEX_V_MSG(index, some_array.size(), -1,
vformat("Item %d is out of bounds.", index));
// Unconditionally prints an error message and returns from the function.
// Only use this if you need to perform complex error checking.
if (!complex_error_checking_routine()) {
ERR_FAIL_MSG("Couldn't reload the filesystem cache.");
}
// Unconditionally prints an error message and returns `false` from the function.
// Only use this if you need to perform complex error checking.
if (!complex_error_checking_routine()) {
ERR_FAIL_V_MSG(false, "Couldn't parse the input arguments.");
}
// Crashes the engine. This should generally never be used
// except for testing crash handling code. Godot's philosophy
// is to never crash, both in the editor and in exported projects.
CRASH_NOW_MSG("Can't predict the future! Aborting.");
也參考
更多各錯誤巨集的詳細資訊,請參見 Godot 原始碼中的 core/error/error_macros.h。
部分函式會回傳錯誤碼(以 Error 型別呈現)。這個值可直接由錯誤巨集回傳。可用的錯誤碼列表請參考 core/error/error_list.h。