《游戏引擎实现原理》引擎内核 目录

《游戏引擎实现原理》卷一《引擎内核》全书导航页:说明本卷定位、读者画像与前置知识、学习节奏与三条阅读路径,交代贯穿项目《微光岛》与从零引擎 helio,讲清 L1–L4 可运行性口径,并按五个部分列出 18 章 54 节的完整章节索引,另含序、前言、附录 A–D 与常见问题速查表,方便读者按需定位、跳读与随时查阅。

目录

欢迎来到《游戏引擎实现原理》。这一卷要陪你做一件很实在的事:用 TypeScript 从零写一个 3D 游戏引擎的内核 helio,写到它能让一个小方块在场景里走动。

为什么是「内核」而不是「整个引擎」?因为游戏引擎里最贵、最难、最不容易被讲清楚的部分,恰恰不是那些看得见的画面,而是看不见的底座——内存怎么分配、对象引用怎么不失效、实体和组件怎么组织、帧内怎么并发、数据怎么序列化。这些东西决定了引擎能跑多快、能撑多大、能不能热重载。渲染是把它们的结果画出来,编辑器是把它们的数据编辑出来。先有内核,才谈得上别的。

市面上讲引擎的书大多从「怎么用 Unity」或「图形学管线」切入。本卷走第三条路:每一节都写代码,每一节的代码都在本机真跑过,跑出来的结果就是这一节的结论。

这一卷写给谁

读者现状读完能拿到什么
有编程基础、想理解引擎原理会用某个引擎,但不知道里面怎么转一套从零写出的引擎内核,和对照它的工程判断力
想做自研引擎 / 独立开发有想法,但被「从哪下手」卡住一条可复制的实现路径:先最小可跑,再逐章长大
前端 / Web 开发者熟 TypeScript,缺系统编程经验内存布局、句柄、并发、反射这些平时被 GC 藏起来的东西
已读过渲染原理的读者懂管线,但不知道引擎怎么把它组织起来内核与渲染的接缝:句柄怎么传给 GPU、数据怎么上传

前置知识:会写 TypeScript(或 JavaScript),了解基本类型与异步;不需要图形学基础,不需要装任何游戏引擎。本卷全部代码在 Node 26 下直接运行,不需要浏览器(渲染要等卷二)。

四类读者,四种收获

下面把这四类人分别展开,你可以对照自己的处境挑一段读——它决定了你该走哪条阅读路径。

如果你有编程基础、想理解引擎原理。 你可能已经用 Unity 或 Godot 做过东西,但每当性能出问题、行为不符合预期时,你只能靠猜和试。这一卷给你的是「里面到底怎么转」的完整链条:从一帧怎么开始,到内存怎么摆、对象引用怎么保证不失效、系统之间怎么并行。读完之后,你手里不只是一个能跑的引擎,还有一套用来解释引擎行为的模型——看到任何引擎的架构图,你能说出每一层大概在做什么。

如果你打算自研引擎或做独立开发。 你缺的往往不是想法,而是「先写哪一块」的次序感。这一卷的 18 章本身就是一份施工顺序表:先立主循环,再补内存与句柄,然后才是容器、数学、ECS、并发、反射,最后装配。每一章都能独立跑通,你可以在任何一步停下,把它接到自己的项目里。第 18 章会把全部零件拼起来,给你一条「从空文件到一个能跑的引擎」的完整参照。

如果你是前端 / Web 开发者。 你的 TypeScript 很熟,但 GC 帮你把内存这件事藏了太久——你很少需要考虑对象在内存里怎么摆、一个引用为什么会失效、一段代码会不会因为缓存不友好而慢十倍。这一卷恰好把这些「被 GC 藏起来的东西」摊开:arena 分配器、对象池、世代句柄、SoA 布局、SharedArrayBuffer 与 Atomics。这些知识迁移到任何语言都成立,也是你从「写页面」迈向「写系统」的那道坎。

如果你已经读过渲染原理。 你懂管线、懂着色器、懂 GPU 在做什么,但你不清楚引擎是怎么把场景数据组织好、再交给渲染的:实体和组件怎么存、句柄怎么传到 GPU、顶点数据怎么上传。本卷讲的正是这层「内核与渲染的接缝」。卷二《渲染引擎》会在这套内核上接出真正的画面,你先在这里把地基打好,卷二才不会踩空。

三条阅读路径

本卷 18 章 54 节,一次读完大约 8 周(每天一小时),但不是每个人都该按同一种顺序读。下面三条路径覆盖了绝大多数人的需求。

路径 A:顺序通读(约 8 周)

最完整的一条。按顺序走完 18 章,每章的代码都亲手敲一遍。

第 1–3 章(地基)→ 第 4–6 章(内存与句柄)→ 第 7–10 章(容器与数学)
→ 第 11–13 章(数据导向与 ECS)→ 第 14–18 章(并发、反射与综合)

适合谁:想真正吃透引擎机制、或打算自研引擎的读者。第 18 章会把前 17 章的零件拼成一个能跑的引擎,不要跳过。这条路径最慢,但拿到的是一套完整的、能自己复现的模型。

路径 B:直奔 ECS 与内存(约 4 周)

已经懂容器与数学、只想看引擎最核心的两块的话:

4.1 → 4.2 → 5.1 → 6.1 → 6.2 → 6.3 → 11.1 → 11.2
→ 12.1 → 12.2 → 13.1 → 13.3 → 18.1 → 18.2

适合谁:时间有限、目标明确是「理解引擎最核心的内存与 ECS」的读者。这条路径读得快,但会牺牲一部分「为什么」。建议至少把第 4 章(内存)完整读——它是后面所有性能结论的地基;跳过它,11、12、13 章的实测数字会变成一堆没有根据的结论。

路径 C:按问题查(随时)

不打算通读,只在遇到具体问题时翻对应章节。

帧率/暂停问题 → 第 2 章;引用失效 → 第 6 章;性能上不去 → 第 11、13 章
存档读不出 → 第 17 章;多核跑不满 → 第 14、15 章;编辑器拿不到类型 → 第 16 章

适合谁:已经有一个能跑的项目,正被某个具体问题卡住的读者。下节「常见问题速查」就是为这条路准备的——它把「你想解决的问题」直接映射到「去看哪一节」。

贯穿项目:《微光岛》

全书只有一个项目:《微光岛》——一款低多边形 3D 收集冒险小游戏。玩家操控一个角色在一座程序化生成的小岛上走动,收集散落的「微光」,昼夜循环随时间推移。

选它,是因为它体量小到能从零写完,又覆盖了 3D 游戏的全部关键面:

玩法要素牵出的技术点对应章节
角色在岛上移动帧循环、固定步长、时间缩放2
场景里成百上千个物体内存布局、对象池、句柄4、5、6
物体挂在父子层级下变换、矩阵、四元数8、9
大量同类物体批量更新数据导向、ECS、查询调度11、12、13
程序化生成岛屿确定性、定点数、可复现随机10
加载与保存进度反射、序列化、版本迁移16、17
多核并行更新Job System、依赖 DAG14、15

范围红线:本卷只做到「一个小方块在场景里走动」为止。真正的画面要等卷二《渲染引擎》。这不是偷懒,而是先把地基夯到能承重。

本卷的可运行性口径

本套书的每一节都标注它属于哪一层,你据此知道「这一节的东西能不能在你机器上跑起来」:

层级含义你怎么验证
L1纯 TypeScript 内核,零运行时依赖Node 26 直接跑 .ts,或 vitest 跑单测
L2需要浏览器渲染用 headless Chromium 跑(本卷用不到,卷二大量使用)
L3只能做类型检查tsc --noEmit 通过
L4命令行不可复现正文会明确标注「需手动验证」
B性能基准跑出 JSON,数字写进附录 C

这五层各自意味着什么,值得展开说清楚:

  • L1——能真跑。 这是本卷的主战场。内存分配器、句柄系统、容器、数学、ECS、Job System,全部是纯 TypeScript、零运行时依赖,node src/xxx.ts 就能跑,配 vitest 就能断言。你看到的每一段 L1 代码,都是在本机跑过、被单测盯过的。
  • L2——需要浏览器。 本卷是内核,一节都用不到 L2。它存在的意义是给卷二《渲染引擎》留位置:等到 GPU 相关的代码登场,就得靠 headless Chromium 跑起来验证。提前写在这里,是为了让你知道「本卷为什么没有它」。
  • L3——只能类型检查。 少数代码依赖 Node 26 跑不出来的类型特性(比如平台相关的声明),能通过 tsc --noEmit 但无法直接执行。这类代码会被明确标注,正文会说明「为什么它跑不了」。
  • L4——命令行不可复现。 涉及真实硬件、真实时间或平台差异的部分(比如跨线程的真实调度抖动),命令行里复现不了。正文会标「需手动验证」,并给出你该手动观察什么。
  • B——性能基准。 凡是给出「快了 N 倍」的结论,背后都有一份 B 级基准:它跑出 JSON,原始数字汇总在附录 C。看到 B 级结论时,请连着附录 C 的原始数据一起看,而不是只记那个倍数。

关于基准数字的诚实声明

本卷会出现不少性能数字——内存占用、遍历耗时、加速比。它们都来自作者本机实测,并附带原始数据(附录 C)。但它们有一个必须说清楚的边界:

这些数字是同机相对量级,绝对数值不可移植。 V8 的 JIT 会在运行时把热点代码编译成机器码,GC 会在不确定的时刻介入,微基准对循环写法极其敏感——同一段代码,换个循环顺序、换个预热次数,结果可能差 50%。所以当你看到「SoA 比 AoS 快 1.6 倍」时,请把重点放在方向而不是倍数上。

真正稳定的结论是那些量级差异,比如「对象数组的堆增量是 60 MB,TypedArray 是 0 MB」——这种结论不会因为写法微调而翻转。本卷会刻意把「方向性结论」和「具体倍数」分开表述:前者你可以直接采信,后者请当作「作者机器上的参考值」。附录 C 会给出测量方法,鼓励你在自己的机器上复现一遍。

全书目录

第 1 部分 地基

引擎是什么、一帧怎么转、子系统怎么活。

节文章核心内容
1.1引擎的分层与模块边界平台层到游戏层的五层划分,对照 Unity / Unreal / Godot / Bevy
1.2本书范围与站内分工本卷讲什么、不讲什么,与站内既有渲染与引擎文章的分工
1.3一个引擎最少要有哪些零件最小可运行引擎的零件清单与骨架代码
2.1帧、时间与帧预算帧预算的构成,滑窗统计帧耗时
2.2固定步长、累加器与渲染插值固定步长循环、插值系数、死亡螺旋与钳制
2.3时间缩放、暂停与慢动作缩放时间轴与未缩放时间轴,暂停时 UI 仍推进
3.1子系统注册、启动顺序与逆序关闭依赖拓扑排序启动、逆序关闭、循环依赖检测
3.2PAL 平台抽象层时间、文件、线程、日志的平台抽象与 Node / Web 双实现
3.3断言、日志分级与配置系统 CVar断言语义、五级日志与分类开关、类型化配置项

第 2 部分 内存与句柄

引擎里最贵的东西,是内存。

节文章核心内容
4.1为什么要自己管内存分配节奏与布局可预测性,实测堆增量差异
4.2线性 arena 与栈式分配器bump 分配、对齐、峰值水位、帧内临时内存
4.3对齐、padding 与 TypedArray 上的真实布局手工布局顶点结构时的对齐陷阱与大小计算
5.1对象池与 freelist预分配与空闲链表,对照 new/GC 的实测
5.2块分配器与大小类按 2 的幂分大小类,固定 buffer 上切块与碎片统计
5.3内存标签、预算与泄漏检测按标签统计占用、超预算告警、分配计数泄漏检测
6.1为什么指针会失效悬垂引用在 TS 里的表现:旧引用读到新对象
6.2slot map 与世代句柄索引 + 世代的句柄编码,槽位复用与失效检测
6.3稀疏集、句柄回收与 ECS 的接缝稀疏集 O(1) 增删查与紧凑遍历,接上 ECS

第 3 部分 容器与数学

自己写的容器,和游戏里真正用得上的数学。

节文章核心内容
7.1动态数组与开放寻址哈希增长策略与开放寻址的探测、删除与装载因子
7.2位集合、环形缓冲与侵入式链表位运算集合、无分配环形缓冲、零额外内存的链表
7.3字符串 intern、资源 GUID 与名字表字符串驻留、句柄化的名字与资源标识
8.1向量代数与 TypedArray 布局向量运算与连续内存布局,零分配约定
8.2矩阵、行/列主序与左/右手坐标系主序与手性的约定,以及它们带来的转置陷阱
8.3变换复合与逆变换平移旋转缩放的复合顺序与逆变换求法
9.1欧拉角、万向节死锁与四元数万向节死锁的复现与四元数的引入动机
9.2四元数运算与最短弧插值乘法、共轭、归一化与 slerp 的最短弧处理
9.3曲线、样条与缓动贝塞尔、Catmull-Rom 与常用缓动函数
10.1浮点确定性与跨端一致性浮点在不同平台上的不可复现性从何而来
10.2定点数:为确定性模拟准备定点数的表示、运算与它换来的确定性
10.3数值稳健:epsilon、饱和与除零比较阈值、饱和运算与除零防护的工程做法

第 4 部分 数据导向与 ECS

把数据摆对,比把算法写巧更重要。

节文章核心内容
11.1缓存层级与访存代价缓存层级与连续 / 随机访存的实测差距
11.2SoA / AoS / AoSoA 的真实差异三种布局的速度与内存实测,以及什么时候不该用 SoA
11.3从 OOP 到批处理的重构方法一步步把一个面向对象的更新循环改造成批处理
12.1从继承到组合到数据三种组织方式的对照与它们各自的代价
12.2组件存储:稀疏集与 archetype两种组件存储方案的实现与取舍
12.3实体生命周期与句柄复用实体的创建、销毁与句柄安全复用
13.1查询匹配与缓存命中组件集合的匹配算法与查询结果缓存
13.2迭代顺序、变更检测与脏标记稳定的迭代顺序、变更检测与脏标记传播
13.3系统依赖声明与并行调度声明系统间的读写依赖并推导并行分组

第 5 部分 并发、反射与综合

让它跑满多核,让它能被编辑,最后把它拼起来。

节文章核心内容
14.1为什么 JS 也需要 Job Systemworker_threads、SharedArrayBuffer 与主线程之外的计算
14.2线程池、任务队列与 Atomics 同步工作线程池、任务队列与原子同步原语
14.3work stealing 队列的真实实现每个工作者一个双端队列与窃取策略
15.1依赖 DAG 与拓扑执行任务依赖图的构建与拓扑执行
15.2任务图构建与帧内调度每帧构建任务图并调度到工作线程
15.3与主循环、渲染线程的同步跨线程同步点与帧边界的确立
16.1引擎为什么需要反射编辑器、序列化与脚本绑定对类型信息的需求
16.2类型注册与属性描述符类型与属性的描述符设计与注册表
16.3显式注册表 + 代码生成扫描不用装饰器元数据的反射方案与代码生成
17.1反射驱动的序列化:JSON 与二进制由类型信息驱动的两种序列化格式
17.2引用、句柄与循环的处理对象引用、句柄与循环引用的序列化策略
17.3版本化与迁移schema 版本号与旧存档的迁移路径
18.1内核装配:把前 17 章拼成引擎把前面所有零件组装成一个可运行的引擎
18.2《微光岛》第一个能走动的方块用拼好的内核跑出第一个确定性 demo
18.3回顾与路线:进入渲染卷本卷小结与卷二《渲染引擎》的衔接

序、前言与附录

篇目内容
序为什么在 2026 年还要从零写一个引擎
前言本套书的技术选型、可运行性口径与环境准备
附录 A helio 内核 API 与模块速查全书出现的模块、类型与关键 API 一览
附录 B 环境与复现速查Node 版本、依赖、如何跑通每一层的代码
附录 C 实测数据汇总全书基准的原始数字与测量方法
附录 D 常见错误与 FAQ易错点、报错含义与排查清单

常见问题速查

你想解决的问题去看
帧率不稳、逻辑和渲染对不上2.2
暂停游戏时 UI 却停住了2.3
子系统启动顺序错了导致崩溃3.1
每帧都在分配、GC 频繁触发4.1 、5.1
内存越跑越碎、分配越来越慢5.2 、5.3
对象删了但旧引用还能读到东西6.1 、6.2
遍历实体时性能上不去11.2 、13.1
模型旋转后出现奇怪的翻转9.1 、8.2
旋转插值走了「远路」、转半圈才到位9.2
跨设备 / 跨平台模拟结果对不上10.1 、10.2
数值比较飘忽、除法偶发炸出 Inf10.3
存档在新版本读不出来17.3
存档里的对象引用变成了空17.2
单核跑满、其他核闲着14.1 、15.2
想让编辑器编辑属性却拿不到类型16.2 、16.3
反射元数据到处散落、难以维护16.3
更多报错原文与排查清单附录 D

怎么用这份索引

  • 想系统学:走路径 A,从第 1 章 1.1 开始。
  • 想抓重点:走路径 B,从第 4 章 4.1 开始。
  • 想查问题:直接用上面的「常见问题速查」,或跳到对应小节。
  • 想配代码:每一节的代码块都标了层级与来源文件,L1 的可以直接复制出来在 Node 26 上跑,跑不通再回附录 B 对版本。
  • 每篇正文末行都有「上一节 / 下一节」导航,也可以随时回到本页。

相关阅读

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「engine」更多文章

  1. 《游戏引擎实现原理》工程与实战 目录
  2. 《游戏引擎实现原理》9.3 选型与自研的判断标准
  3. 《游戏引擎实现原理》9.2 同一个特性在不同引擎里的实现路径