2、刷新循环基础:游戏循环的概念、固定时间步长 vs 可变时间步长、CPU与GPU的协作

说到动画刷新系统,最核心的东西其实就是那个「循环」。说白了,就是让画面一帧一帧地动起来。我刚开始做动画时,以为只要在循环里不断重绘就行了,结果跑起来要么卡成幻灯片,要么CPU风扇狂转。后来才明白——循环本身,是有讲究的。

2.1 游戏循环是什么?

游戏循环,也叫主循环。它是整个动画系统的发动机。每一帧,它都做三件事:

  1. 处理输入——鼠标、键盘、触摸
  2. 更新逻辑——位置、碰撞、状态
  3. 渲染画面——把结果画到屏幕上

这三件事不断重复,直到程序退出。听起来简单吧?但坑全藏在「什么时候做」和「做多快」里。

核心要点:游戏循环决定了动画的流畅度、响应速度和资源消耗。选错策略,后面全白搭。

2.2 固定时间步长 vs 可变时间步长

这是每个做动画的人都会遇到的选择题。我当年也纠结过,后来两种都踩过坑,今天一次性说清楚。

固定时间步长

固定时间步长,就是每次更新逻辑时,都假设过去了固定的时间。比如每帧更新 16.67ms(对应 60fps)。

# 固定时间步长伪代码
FIXED_DT = 1.0 / 60.0  # 每帧16.67ms
accumulator = 0.0

while running:
    frame_time = get_frame_time()
    accumulator += frame_time

    while accumulator >= FIXED_DT:
        update(FIXED_DT)   # 逻辑更新
        accumulator -= FIXED_DT

    render()  # 渲染

优点:

  • 物理模拟稳定,不会因为帧率波动而「跳帧」
  • 逻辑可预测,调试方便
  • 多人游戏同步容易

缺点:

  • 如果渲染太慢,逻辑会堆积(螺旋死亡)
  • 需要处理「剩余时间」

我曾经踩过的坑:有一次做物理模拟,用了可变时间步长,结果帧率低的时候物体直接穿墙了。换成固定步长后,问题立刻消失。物理模拟,一定要用固定步长。

可变时间步长

可变时间步长,就是每次更新时,把实际经过的时间传进去。帧率高就更新快,帧率低就更新慢。

# 可变时间步长伪代码
while running:
    dt = get_frame_time()  # 实际经过的时间
    update(dt)             # 逻辑更新
    render()               # 渲染

优点:

  • 实现简单,代码量少
  • 不会出现逻辑堆积

缺点:

  • 物理模拟不稳定,dt 太大时容易出问题
  • 帧率波动会直接影响游戏体验

对比表格

特性 固定时间步长 可变时间步长
物理稳定性 高 低
实现复杂度 中 低
帧率波动影响 小 大
CPU 占用 可控 随帧率变化
适用场景 物理模拟、竞技游戏 UI 动画、简单演示

我的建议:做动画系统,优先用固定时间步长。虽然代码多几行,但后面省心太多。可变步长只适合那些「丢了帧也无所谓」的场景。

2.3 CPU 与 GPU 的协作

很多人以为动画就是 CPU 算完,GPU 画完,完事。其实没那么简单。你想想看,CPU 和 GPU 是两套完全不同的硬件,它们怎么配合?

分工明确

  • CPU:负责逻辑计算、物理模拟、碰撞检测、场景管理
  • GPU:负责顶点处理、光栅化、像素着色、输出画面

说白了,CPU 是「大脑」,GPU 是「画师」。大脑想好了怎么动,画师才动手画。

流水线协作

现代渲染引擎用的是流水线模型。CPU 提交一帧的渲染指令,GPU 开始处理,同时 CPU 继续准备下一帧。就像工厂流水线,一个工位在加工,另一个工位在备料。

# CPU 与 GPU 协作示意
while running:
    # CPU 阶段
    update_logic()           # 更新物理、动画、AI
    prepare_render_data()    # 准备顶点、纹理、着色器

    # 提交到 GPU
    submit_to_gpu()          # 非阻塞调用,立即返回

    # CPU 继续做其他事
    # GPU 在后台并行渲染

关键点:CPU 提交渲染指令后,不会等 GPU 画完。它会立刻回来准备下一帧。这就是为什么帧率能跑满的原因——CPU 和 GPU 在并行工作。

同步问题

并行就会带来同步问题。最常见的坑是:

  • CPU 跑太快:提交了 3 帧的指令,GPU 才画完 1 帧,导致指令队列溢出
  • GPU 跑太快:GPU 空闲,等 CPU 喂数据

解决办法就是「垂直同步」(V-Sync)。它让 CPU 等 GPU 画完当前帧,再提交下一帧。代价是帧率被锁定在显示器刷新率(通常 60Hz)。

我曾经踩过的坑:有一次做高帧率动画,关了垂直同步,结果 GPU 温度飙到 90 度。因为 CPU 疯狂提交指令,GPU 根本停不下来。后来加了帧率限制,温度才降下来。别让 GPU 空转,那是浪费电。

2.4 知识体系总览

下面这张图,把本章的核心逻辑串起来了。你可以把它当作「刷新循环的脑图」。

刷新循环知识体系 游戏循环 固定时间步长 物理稳定 逻辑可预测 适合物理模拟 可变时间步长 实现简单 无逻辑堆积 适合UI动画 CPU与GPU协作 流水线并行 垂直同步 帧率控制 选择策略时,先问自己: 物理模拟?→ 固定步长 | UI动画?→ 可变步长

2.5 本章小结

刷新循环是动画系统的地基。选固定步长还是可变步长,取决于你的场景。物理模拟必须固定步长,UI 动画可以用可变步长。CPU 和 GPU 是并行工作的,别让任何一方空转。垂直同步能解决撕裂,但会锁帧率。