Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

空闲处理与物理处理

游戏是通过循环来运行的,每一帧都需要先更新游戏世界的状态,然后再把它绘制到屏幕上。Godot 为 Node 类提供了两个虚方法来完成帧循环处理:Node._process()Node._physics_process()。如果你在脚本中定义了这两个函数的其中之一,或者两者都定义了,引擎就会自动进行调用这个(这些)虚函数。

可以使用两种帧循环处理方式:

  1. 空闲处理(Idle processing)可以用来执行每帧更新节点的代码,执行频率会尽可能地快。

  2. 物理处理(Physics processing)的执行频率是固定的,默认为每秒 60 次。物理处理和游戏的实际帧率无关,可以让物理平滑执行,故一切与物理引擎相关的行为都应该用物理处理帧循环函数来进行处理,如移动可能会与环境相碰撞的实体。

在脚本中定义 _process() 方法就会激活空闲处理。可以通过调用 Node.set_process() 来对空闲处理的启用状态进行控制。

引擎每需要绘制一帧画面,就会调用一次该方法:

func _process(delta):
    # Do something...
    pass

切记:引擎调用 _process() 的频率以应用的实际帧率为准,该实际帧率会根据时间的变化而变化,在不同设备上该实际帧率也会有所不同。

该函数的参数 delta 表示从上一次调用 _process() 开始所经过的秒数,借助这个参数就可以进行与帧率无关的计算。例如,为移动物理做动画时,应该始终将速度值乘上 delta

物理处理使用的是类似的虚函数:_physics_process(),用于必须在每一次物理迭代前进行的计算,比如移动可能会与游戏世界发生碰撞的角色。前面提到过,为了实现平稳的物理交互,_physics_process() 的执行间隔是尽可能固定的,可以在“项目设置”的“Physics -> Common -> Physics Fps”(物理 -> 常规 -> 物理 FPS)中修改物理迭代之间的间隔,默认设置是每秒 60 次。

引擎每进行一次物理计算,就会调用一次该方法:

func _physics_process(delta):
    # Do something...
    pass

_process() 函数不与物理处理同步执行,且其执行频率会受到硬件和游戏优化的影响。在单线程游戏中,会在物理迭代后执行。

要观察 _process() 的执行,可以创建一个只有单个 Label 节点的场景,然后把下面的脚本附加给这个 Label 节点:

extends Label

var time = 0

func _process(delta):
    time += delta
    text = str(time) # 'text' is a built-in Label property.

运行场景,你就会看到一个每帧都会增加的计数器。