游戏引擎中的模式
游戏引擎将模式推向极限——60fps 下每一帧都至关重要。
| 模式 | 项目 | 位置 | 作用 |
|---|---|---|---|
| 对象池 | Godot | pooled_list.h | 基于 freelist 的游戏对象池 |
| 双缓冲 | SDL | SDL_render.c | 前后 buffer 交换实现无撕裂渲染 |
| 空闲链表 | Godot | pooled_list.h | 非侵入式空闲链表,O(1) 实体分配/释放 |
| 环形缓冲区 | 游戏音频 | 各引擎通用 | 主线程和音频线程间的无锁音频流缓冲 |
| 状态机 | Godot | animation_tree.h | 角色动画混合的动画状态机 |
| Arena 分配器 | 帧分配器 | 通用模式 | 每帧 bump 分配器——每帧重置,零释放开销 |
| 享元 | Godot | servers/rendering/ | 多个实例共享的网格/纹理资源 |
| 批处理 | Godot / Unity | 渲染批处理 | 批量 draw call 减少 GPU 状态切换 |
| 标签联合体 | Godot | variant.h | Variant::Type 枚举 + 联合体——GDScript 中每个值都是 Variant |
| 脏标记 | Godot / Unity | 变换层级 | 父变换脏标记使子节点世界矩阵失效——仅在访问时重算 |
| 事件循环 | Godot | main_loop.h | 主游戏循环——按固定步长处理输入、更新、渲染 |
模式如何协作:一帧游戏
在 60fps 下,每帧只有约 16ms 的预算。多个模式在这个预算内协同工作:
第 N 帧开始▼7
Arena 分配器
每帧临时分配(粒子、调试绘制)使用 bump 分配器。帧结束时:指针归零,搞定。
核心洞察:游戏引擎最小化逐对象开销。池避免 malloc,脏标记避免不必要的重算,批处理避免多余的 GPU 调用,Arena 避免逐对象释放。所有这些共享同一设计哲学——每次操作 O(1),推迟或摊销昂贵的工作。
延伸阅读
- Godot Engine (GitHub) · SDL (GitHub)
- Game Programming Patterns (book) by Robert Nystrom