设置程序执行频率

注:在这一篇中你将了解到如何设置程序的 执行频率,以及如何选择 最合适的运行频率


基础用法

在脚本中,执行频率是通过 Runtime.UpdateFrequency 来控制的。

通常我们会在 构造函数 Program() 中进行设置:

public Program()
{
    // 构造函数:脚本加载时只执行一次
    // 通常用于初始化变量、查找方块、设置执行频率等

    Runtime.UpdateFrequency = UpdateFrequency.Update10;
    // 设置 Main() 函数的触发频率为:
    // 每 10 个 tick 执行一次
}

什么是 Tick?

Tick 就是游戏时间刻

在游戏中:1 Tick ≈ 1/60 秒

因此执行频率对应关系如下:

频率 实际时间 说明
Update1 每 tick 每刻执行(最快)
Update10 约 0.16 秒 常用频率
Update100 约 1.6 秒 低频任务

所有可用频率

可通过枚举组合使用:

Runtime.UpdateFrequency = 
    UpdateFrequency.Update100 |
    UpdateFrequency.Once;
// 每 100 tick执行一次,并且在下一tick之前只执行一次

可选值说明

UpdateFrequency 是一个枚举类型,它里面具体的值可以用之前 查询API 篇教学的按下 F12 快速查询里面的所有内容。具体如下:

枚举值 含义
None 不自动(循环)执行
Update1 每 tick(游戏刻)执行
Update10 每 10 tick 执行
Update100 每 100 tick 执行
Once 在下一 tick 之前执行一次

本篇只是作为前期示例和过度放出,后期教程所涉及到的所有API请自行通过 F12 自行查阅

实际例子

这里我们定义了一个变量 a 在每次 Main 函数被触发的时候,使 a 的值加一并输出:

using Sandbox.ModAPI.Ingame;
using XFEExtension.SpaceEngineers.ScriptingHelper;

namespace MyProject
{
    internal partial class Program : MyGridProgram, IProgramBase
    {
        // 注意,复制到游戏内编程块的时候应当从下面开始复制
        //------------------从此处开始复制------------------//

        int a = 0; // 定义 int 类型的成员变量 a

        public Program()
        {
            // 这里是 构造函数
            Runtime.UpdateFrequency = UpdateFrequency.Update100; // 设置 Main函数 触发频率为每100个tick触发一次
        }

        public void Main(string argument, UpdateType updateSource)
        {
            // 这里是 主函数
            a = a + 1; // 使 a 的值加一
            Echo($"变量 a 的值为:{a}"); // 在游戏编程块上输出 a 的值
        }

        public void Save()
        {
            // 这里是 保存函数
        }
        //------------------从此处结束复制------------------//
    }
}

我们复制到游戏中可以看到 a 的值增加的频率基本上是每 1.6 秒 增加一次

Image

接着让我们来修改 Runtime.UpdateFrequency 的值为 UpdateFrequency.Update10

Runtime.UpdateFrequency = UpdateFrequency.Update10;
// 设置 Main函数 触发频率为每10个tick触发一次

让我们再来看看效果

Image

可以看到,这一次相比于之前的 UpdateFrequency.Update100 要快多了,增加的频率基本上是每 0.16 秒 增加一次

现在我们更暴力一点,将其改成 UpdateFrequency.Update1 看看会发生什么

Runtime.UpdateFrequency = UpdateFrequency.Update1;
// 设置 Main函数 触发频率为每tick触发一次

Image

可以看到现在基本上是 0.016秒 就触发一次,非常的快速啊。

从这里也可以看出来,选择一个 合适的触发频率 有多么的重要——选择慢了你的程序可能来不及响应;选择快了又可能无端的增加额外的算力消耗。

选择合适的执行频率

那么现在我们就来讲讲如何选择最合适的触发频率,很多新手刚开始写脚本一上来不管什么功能的脚本就使用最高的执行频率

比如有一个太阳能板追踪太阳方向的脚本,将其的游戏刻设置为了:

Runtime.UpdateFrequency = UpdateFrequency.Update1

而游戏内太阳的移动速度非常缓慢,这个时候我们对于太阳能板位置的更新速度要求没那么严苛,而这些明明可以 100 tick 更新一次的数据,却偏偏写成了 1 tick 更新一次。这样做很容易导致游戏花费额外的 算力 去反复的计算太阳的位置和转子的朝向,最终导致游戏 模拟速度1 下降

因此推荐的选择策略为:

频率 逻辑类型 适用范围 特点 性能消耗
🟢 Update1 高频逻辑 实时控制、自动驾驶、姿态调整、PID 控制 即时响应 最高
🟡 Update10 常规逻辑 UI 刷新、状态检测、方块扫描、自动管理系统 性能与响应平衡 中等
🔵 Update100 低频任务 定期统计、监控区域、扫描库存、非实时检测 响应较慢 最低

触发后如何判断是哪种频率?

Main() 函数中,我们还是通过 Runtime.UpdateFrequency 来判断:

public void Main(string argument, UpdateType updateSource)
{
    if (Runtime.UpdateFrequency == UpdateType.Update10)
    {
        Echo("这是每10tick执行的逻辑");
    }
}

这样可以在 不同频率下执行不同代码

动态修改执行频率

你可以在运行时改变频率:

Runtime.UpdateFrequency = UpdateFrequency.None;

停止自动执行

或者:

Runtime.UpdateFrequency = UpdateFrequency.Update1;

使用新的执行频率

单次执行(Once)

用于延迟执行:

Runtime.UpdateFrequency = UpdateFrequency.Once;

特点:

  • 下一 tick 前只执行一次
  • 执行完自动恢复为 None

常用于:

  • 延迟初始化
  • 等待方块加载
  • 状态切换

性能优化建议

最佳实践

  1. 优先使用 Update10
  2. 不要长期使用 Update1
  3. 重计算逻辑尽量放到 Update100
  4. 使用状态机减少执行次数

小技巧:节流执行

可以用计数器进一步降低执行频率:

int counter = 0;

public void Main(string arg, UpdateType source)
{
    counter++;

    if (counter % 6 == 0)
    {
        Echo("实际执行频率降低了6倍");
    }
}

总结

设置执行频率的核心原则:

能低频就低频,能分离就分离

选择顺序建议:

Update100 → Update10 → Update1

而不是反过来。


  1. 模拟速度 是游戏 《太空工程师》 中的一种机制,这种机制使得游戏可以将计算逻辑分开。这样一来后端逻辑需要大量计算时,前端画面不会卡顿,只是会降低游戏的整体速度,而这个整体速度就是我们说的模拟速度,取值范围为 0.00 ~ 1.00。后台的计算量越大,这个值越小,模拟速度越低。