标签:引擎架构
-
多 SceneTree 的可行性:为什么插件里不能随便 new MainLoop
SceneTree 表面上是可替换的 MainLoop,但渲染、输入、视口、单例注册全围绕"一棵树"假设搭建;要第二棵树,官方给的答案是 SubViewport 而不是第二个 SceneTree。
-
String/StringName 的内部表示与哈希缓存
StringName 用一张全局静态表把字符串比较变成指针比较,这篇拆 core/string/string_name.h 的结构,讲清为什么 NodePath 与信号名的比较必须走 StringName 而不是 String。
-
命令行解析与启动参数:--editor、--headless 的分发逻辑
godot --editor --headless 这些参数在 Main::setup() 里被一棵参数树消化,这篇读 main/main.cpp 的参数解析段,讲清参数怎么决定显示驱动、脚本服务器和 MainLoop 的选择。
-
doctest 单元测试与 clang-format 工作流:给引擎提 PR 前的自检清单
Godot 的测试跑在引擎二进制里而不是独立测试程序,这篇讲 tests/ 目录的 doctest 集成方式、headless 跑法,以及 clang-format 在 CI 上的卡点。
-
ObjectDB 与对象泄漏检测:退出时那堆 "ObjectDB instances leaked" 怎么读
游戏退出时打印的 "ObjectDB instances leaked at exit" 不是报错是遗产清单,这篇讲 ObjectDB 的注册机制、泄漏报告的读法,以及它和 Orphaned Nodes 的区别。
-
Godot 4.x 源码目录速览:main/core/scene/servers/modules/editor 各管什么
第一次 clone Godot 源码的人都会被 40 多个顶层目录劝退。这篇把 4.x 的目录按"分层职责"重新组织成一张地图,并标出每层最值得先读的文件。
-
core/os 层:OS 单例如何抽象平台差异
Godot 跨六个桌面/移动/Web 平台,平台差异被压在 core/os 的 OS 基类和 platform/ 的派生实现里。这篇讲 OS::get_singleton() 的分发机制、虚函数表的覆盖策略,以及为什么"单例 + 继承"比"接口 + 工厂"更适合引擎。
-
Variant 的内部结构:union 加类型标签怎么装下四十多种类型
Variant 是脚本与 C++ 之间的通用货币,要在固定 24 字节里装下从 int 到 Transform3D 再到 Object 指针的 40 多种类型。这篇拆 core/variant/variant.h 的内存布局,讲清 4 字节类型标签加 16 字节 union 的取舍。
-
Callable 与信号的关系:bind 的参数存在哪
Callable 是"可调用的东西"的统一表示,bind 的参数不是存在信号里而是存在 Callable 自己内部。这篇读 core/variant/callable.h 与 callable_bind.cpp,讲清信号发射时参数怎么拼接。
-
多线程基础设施:WorkerThreadPool 与 TaskGroup
WorkerThreadPool 是引擎内部所有"扔给后台干"的活儿的统一入口,这篇讲它的任务队列、Group 语义,以及为什么引擎不用 std::async 也不让业务自己起线程。
-
ERR_FAIL_COND 家族:引擎错误处理宏的设计逻辑
Godot 源码里看不到一个 try/catch,错误处理全靠 ERR_FAIL_COND、ERR_CONTINUE、CRASH_NOW 这三十多个宏。这篇讲这套宏的设计动机、六个变体的分工,以及"不用异常"换来的东西。
-
ResourceLoader 的加载链:ResourceFormatLoader 的注册与选择
load("res://foo.tscn") 的第一个分叉点是 recognize 而不是扩展名:ResourceFormatLoader 列表按优先级询问"你认这个路径吗"。这篇拆加载链的每一环和自定义 loader 的接入方式。
-
RID 句柄系统:服务器对象为什么不用裸指针
RenderingServer、PhysicsServer 对外暴露的不是对象指针而是 RID——一个 64 位整数句柄。这篇讲 RID 的查表实现、为什么它能带来线程安全和热重载能力,以及 RID_Owner 的槽位复用机制。
-
RefCounted 引用计数与 memnew/memdelete:引擎为什么不用 shared_ptr
Godot 的资源生命周期靠 RefCounted + Ref<T> 管理,内存分配靠 memnew/memdelete 宏。这篇讲这套组合为什么故意绕开 std::shared_ptr,以及引用计数在继承体系里是怎么实现的。
-
Vector/HashMap/LocalVector:Godot 为什么不用 STL
core/templates 下有一套自研容器,这篇对比 Vector、LocalVector、HashMap 与 STL 对应物的设计分歧,讲清拷贝语义、内存模型和 ABI 稳定性这三条不用 STL 的理由。
-
Mutex/RWLock 封装与服务器线程模式:thread_safe 编译宏的影响
Godot 的锁不是 std::mutex 的直接包装,而是一套带"可编译期消除"语义的封装,这篇讲 Mutex/RWLock 的分层、THREAD_SAFE 宏如何让锁在单线程构建里消失,以及服务器的线程模式设置。
-
引擎版本演进:3.x 到 4.x 还了哪些架构债
Godot 4.0 是一次刻意的"破而不立然后立",这篇对照 3.x 到 4.x 的架构变化:VisualServer 拆分、GDScript 重写、信号系统重设计,以及迁移时真正会咬人的差异。
-
Godot 引擎底层原理导览:一张给源码读者的地图
给想翻 Godot 源码的人的一张地图:节点层与服务器层的二分结构、主循环节拍、脚本运行时位置,以及这个分类下每篇深度文章的阅读路径。
-
Object 基类与 ClassDB:Godot 反射系统与信号槽的地基
C++ 没有反射,Godot 用 GDCLASS 宏和 ClassDB 静态注册表造了一套。这篇讲类怎么注册、方法怎么绑定、信号连接存在哪,以及 emit_signal 为什么要在发射前复制一份连接列表。
-
Main 类启动流程拆解:从 main() 到 MainLoop 开始迭代
main/main.cpp 四千多行,但真正决定"引擎怎么活过来"的只有 setup、setup2、start 三段。这篇把启动序列按依赖关系理一遍,标出每步为什么必须在这个位置。