Skip to content

游戏引擎中的模式

游戏引擎将模式推向极限——60fps 下每一帧都至关重要。

模式项目位置作用
对象池Godotpooled_list.h基于 freelist 的游戏对象池
双缓冲SDLSDL_render.c前后 buffer 交换实现无撕裂渲染
空闲链表Godotpooled_list.h非侵入式空闲链表,O(1) 实体分配/释放
环形缓冲区游戏音频各引擎通用主线程和音频线程间的无锁音频流缓冲
状态机Godotanimation_tree.h角色动画混合的动画状态机
Arena 分配器帧分配器通用模式每帧 bump 分配器——每帧重置,零释放开销
享元Godotservers/rendering/多个实例共享的网格/纹理资源
批处理Godot / Unity渲染批处理批量 draw call 减少 GPU 状态切换
标签联合体Godotvariant.hVariant::Type 枚举 + 联合体——GDScript 中每个值都是 Variant
脏标记Godot / Unity变换层级父变换脏标记使子节点世界矩阵失效——仅在访问时重算
事件循环Godotmain_loop.h主游戏循环——按固定步长处理输入、更新、渲染

模式如何协作:一帧游戏

在 60fps 下,每帧只有约 16ms 的预算。多个模式在这个预算内协同工作:

第 N 帧开始
1
事件循环

主循环驱动:处理输入、运行物理、更新游戏状态、渲染。固定时间步保证确定性模拟。

2
对象池 + 空闲链表

生成子弹从对象池获取槽位(O(1)),而非 malloc。销毁的实体返回空闲链表。

3
脏标记

移动父变换会将子节点标记为脏。仅重新计算本帧实际变化的节点的世界矩阵。

4
状态机

角色动画过渡(idle → run → jump)由状态机驱动。每个状态知道其混合树和退出规则。

5
批处理

按材质/纹理批量合并 draw call 以减少 GPU 状态切换。100 个相同纹理的精灵 = 1 次 draw call。

6
双缓冲

后缓冲区原子交换到前台。玩家看到完整帧,永远不会看到半画的画面。

7
Arena 分配器

每帧临时分配(粒子、调试绘制)使用 bump 分配器。帧结束时:指针归零,搞定。

核心洞察:游戏引擎最小化逐对象开销。池避免 malloc,脏标记避免不必要的重算,批处理避免多余的 GPU 调用,Arena 避免逐对象释放。所有这些共享同一设计哲学——每次操作 O(1),推迟或摊销昂贵的工作。

延伸阅读

基于 MIT 许可证发布。