Godot Engine 原始碼閱讀筆記:01 引擎的程式執行
上一篇(Godot Engine 原始碼閱讀筆記:00 程式碼目錄結構)
01 目標
知曉 Godot Engine 的啟動流程
理解遊戲引擎的主迴圈(loop)
對比 Godot Engine 的主迴圈
GO:
知曉 Godot Engine 的啟動流程 (以 X11 平臺為參考)
Godot Engine 以根據不同的平臺(platform),在 /platform 中對應實現了程式的啟動入口,在 /core 中做了 OS 層面的抽象,在各自 platform 中會有對應的實現
在 /platform/x11/godot_x11。cpp 中有很簡單的 main 方法,如下:
int main(int argc, char *argv[]) {
OS_X11 os;
setlocale(LC_CTYPE, “”);
char *cwd = (char *)malloc(PATH_MAX);
char *ret = getcwd(cwd, PATH_MAX);
Error err = Main::setup(argv[0], argc - 1, &argv[1]);
if (err != OK) {
free(cwd);
return 255;
}
if (Main::start())
os。run(); // it is actually the OS that decides how to run
Main::cleanup();
if (ret)
chdir(cwd);
free(cwd);
return os。get_exit_code();
}
OSX11 繼承自 /drivers/unix/osunix。cpp, OSUNIX 繼承自 OS ,並且實現了通用的類 Unix 系統的介面,因此放在了 /drivers 目錄下
/main/main。cpp 中的 Main 類,是 Godot Engine 的生命週期管理物件,setup 對系統進行了引數解析並初始化操作, 包括引擎內部物件的建立,根據引數判斷是需要啟動 “專案管理器”,“編輯器”,“遊戲”,“場景”,“指令碼”等
setup 之後,osx/win/x11 平臺還有 需要執行 Main::setup2 這裡初始化了音訊/ARVR/物理引擎等各 Servers。
Main::start 在 setup 成功後執行,根據不同引數判斷系統所需的 MainLoop 物件
editor 的 MainLoop 為 SceneTree , UI 物件為: EditorNode
project_manager 的 MainLoop 為 SceneTree, UI 物件為:ProjectManager
如果是執行指令碼,則會根據指令碼建立對應的 MainLoop 物件
start 成功後,便呼叫 os。run() 進入引擎主迴圈。
主迴圈退出後,Main::cleanup 做好清場工作。
2。
理解遊戲引擎的主迴圈(loop)
現代遊戲引擎的主迴圈邏輯都大同小異,可參考 (Game Loop · Sequencing Patterns · Game Programming Patterns) , (deWiTTERS Game Loop)
一般遊戲的 MainLoop 做以下事情:
loop:
// 輸入處理
input_event_process()
// 更新遊戲邏輯,包括物理/音效/腳步等模組
update()
// 渲染
render()
FPS(每秒幀數),遊戲要執行流暢,必須要保證一定的 FPS ,所以在遊戲中,就會根據走過的時間來呼叫 loop 中的業務邏輯,通常也會將前後兩幀的時間差(delta) 作為引數傳入到其他模組的 update 中。
3。 對比 Godot Engine 的主迴圈
來到 os。run() 的實現中(OS_X11::run)
void OS_X11::run() {
force_quit = false;
if (!main_loop)
return;
main_loop->init();
//uint64_t last_ticks=get_ticks_usec();
//int frames=0;
//uint64_t frame=0;
while (!force_quit) {
process_xevents(); // get rid of pending events
#ifdef JOYDEV_ENABLED
joypad->process_joypads();
#endif
if (Main::iteration())
break;
};
main_loop->finish();
}
也是很簡潔,除了平臺相關的人機互動介面(滑鼠/鍵盤/觸控/遊戲手柄等)處理外,while 迴圈中,其他業務由 Main::iteration 完成
Main::iteration 和其他引擎的 loop 基本一致
Main::iteration
loop:
計算 fps
物理引擎 update
顯示引擎 draw update
指令碼引擎 frame process
音訊引擎 update
最後在 Main::cleanup 中做了各模組的記憶體清理工作。