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.

常用引擎方法與巨集

Godot 的 C++ 原始碼中使用了數十種自訂方法與巨集,幾乎每個檔案都會用到。本頁面主要針對新手貢獻者,但對於撰寫自訂 C++ 模組的開發者也很實用。

格式化字串

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

這些巨集適用於所有可互相比較的型別(如 intfloat)。

微型效能檢測

如果你想對某段程式碼進行效能檢測,但不熟悉效能分析工具,可以使用以下程式碼片段:

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_DEFEDITOR_DEF,其他需要使用時則以 GLOBAL_GETEDITOR_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