Attention: Here be dragons
This is the latest
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Godot.
Checking the stable version of the documentation...
常用引擎方法與巨集
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").utf8().get_data();
大多數情況下,建議使用 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。