You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Godot中使用GDScript实现按自定义帧率运行函数的自适应定时器

让Godot代码按自定义帧率稳定执行的解决方案

我来帮你搞定这个需求——要让指定代码按自定义帧率(比如60FPS)稳定运行,核心是根据设备实际的时间流逝动态调整执行时机,而不是依赖固定的等待时间。毕竟不同设备的帧率波动会导致固定wait_time的Timer执行频率不准,下面给你两种实用的实现方案:

方案一:用_process结合时间差判断(精度最高,推荐)

这种方法直接在每帧中检查时间差,能抵消帧率波动的影响,保证执行频率尽可能贴近目标帧率。

代码示例

# 自定义目标帧率(比如60FPS)
var target_fps = 60
# 目标执行间隔(秒):1秒除以帧率
var target_interval = 1.0 / target_fps
# 记录上一次执行代码的时间(单位:秒)
var last_exec_time = 0.0

func _ready():
    # 初始化上次执行时间为当前时间
    last_exec_time = OS.get_ticks_msec() / 1000.0

func _process(delta):
    # 获取当前时间(转换为秒)
    var current_time = OS.get_ticks_msec() / 1000.0
    # 计算距离上次执行的时间差
    var time_since_last = current_time - last_exec_time

    # 当时间差达到或超过目标间隔时,执行代码
    if time_since_last >= target_interval:
        # --------------------------
        # 这里放你要按目标帧率执行的代码
        print("按60FPS执行的代码触发")
        # --------------------------

        # 更新上次执行时间,注意要扣除超出目标间隔的部分,避免累积误差
        # 比如如果卡顿导致时间差超过0.02秒,下次会从正确的时间点开始计算
        last_exec_time = current_time - (time_since_last % target_interval)

关键细节

  • OS.get_ticks_msec()获取系统时间比单纯累加delta更准确,因为delta在卡顿帧会突然变大,容易导致误差累积。
  • 更新last_exec_time时的取余操作,能保证即使某次执行延迟了,后续的执行节奏也能回到目标帧率上,不会出现“越慢越卡”的情况。

方案二:改进Timer节点的动态等待时间(适合异步场景)

如果你更习惯用Timer节点,也可以动态调整它的wait_time来适配帧率波动。不过这种方法的精度略低于方案一,适合不需要严格帧同步的异步触发场景。

代码示例

var target_fps = 60
var target_interval = 1.0 / target_fps
var timer:Timer
var last_timeout_time = 0.0

func _ready():
    # 创建并初始化Timer
    timer = Timer.new()
    timer.one_shot = false # 设置为循环触发
    timer.wait_time = target_interval
    add_child(timer)
    timer.connect("timeout", self, "_on_timer_timeout")
    timer.start()
    last_timeout_time = OS.get_ticks_msec() / 1000.0

func _on_timer_timeout():
    # --------------------------
    # 这里放你要执行的代码
    print("Timer触发执行")
    # --------------------------

    # 计算实际触发间隔,微调下一次的等待时间,抵消误差
    var current_time = OS.get_ticks_msec() / 1000.0
    var actual_interval = current_time - last_timeout_time
    last_timeout_time = current_time
    # 调整wait_time,让下一次触发更贴近目标间隔
    timer.wait_time = target_interval - (actual_interval - target_interval)

方案选择建议

  • 如果需要严格控制执行频率(比如动画更新、物理模拟),优先选方案一,它的精度更高,能适配各种帧率波动。
  • 如果是异步触发的单次/循环任务(比如延迟提示、周期性检查),方案二更简洁,不需要每帧处理逻辑。

内容的提问来源于stack exchange,提问作者Joe

火山引擎 最新活动