跳至正文

6 月:刻、网络代码与追踪!

· 10 分钟读完
Gabriel • SyedMuhammad
lead developer™

刻、网络代码与追踪!

欢迎阅读我们上个月最新更新的汇总!

刻​

刻是游戏跳动的心脏,我们在这里处理输入、网络回调、脚本事件以及其他一切。

我们在客户端和服务器端都大幅改进了刻循环和计时器系统:

服务器端​

我们完全重构了核心刻循环,实现了更精确的计时算法。这种新算法消除了过去影响内部计时器甚至 Timer 类的微小但累积的计时误差。

因此,我们将 Config.toml 中的配置从 tick_rate 改为 max_tick_rate,现在以 赫兹 (Hz) 为单位,而非毫秒。默认值现在是 30 Hz(即每帧 33.33ms),与客户端匹配以实现更好的同步。

我们还改进了高刻持续时间的日志,显示更好的诊断信息,如下所示:

WARNING Server Tick time extremely high! Server may be very overloaded or stuck.
Tick Duration: 117.90ms (8/s). Average: 39.07ms (25/s). Configured: 33.33ms (30/s).

客户端​

以前,所有 nanos world 处理都在物理模拟之后进行。这包括网络、快照、插值、Lua 事件处理、CEF 绘制、3D 调试绘制等。

它确实能工作……但我们意识到它可以好得多。

我们现在重新排序并确定了内部刻的优先级,使低延迟任务(如网络同步和输入)在帧中尽快发生,而需要帧被完全读取的任务在有数据可供使用时才执行。

这确保在帧准备好时执行正确的逻辑,修复了使用“旧”帧数据工作的问题。

结果?感知流畅度和响应性急剧提升。以下是使用物理枪的前后对比:

沙盒物理枪之前,文本和粒子位置有大量抖动和不同步
沙盒物理枪之后,不再有抖动和残影

仅仅通过调整算法的处理顺序就实现了这一巨大改进。

计时器​

计时器之前依赖于帧之间的增量时间。随着时间推移,这导致了轻微的误差,非常细微,但足以累积。

我们现在使用基于真实时钟的算法来以更高精度追踪经过的时间。

在比较计时器和 Lua clock 方法时非常明显,它们几乎完全同步。

备注

计时器和 Tick 事件仍然继承配置帧时间的误差范围(例如 33ms)。

我们还修复了间隔计时器中的一个长期漏洞,它没有补偿执行开销。现在,设置为每 1 秒触发的计时器将准确每 1 秒触发,无论什么情况,连续调用没有延迟。

网络代码改进​

此外,得益于 Tick 改进和其他内部低级网络改进,我们的网络延迟显著降低了!与地球另一边的人一起游玩的品质感大幅提升!

我们甚至降低了调试绘制颜色的阈值,以更准确地检测延迟。在这里你可以注意到现在接收的数据包更加均匀分布:

之前接收的网络快照数据包:过大的修正(大箭头)和延迟(黄色)
现在接收的网络快照数据包:均匀分布,大多为绿色且小
提示

箭头越大,本地插值与接收到的网络真实位置之间的“误差”就越大。

黄色箭头表示数据包接收耗时超过 2 帧(66ms)。这个阈值从旧的 450ms 降低了,即使如此我们现在几乎看不到黄色了!

阅读更多关于网络调试以及每种颜色/箭头含义的信息:

🧑‍💻 主控概念core-concepts/scripting/authority-concepts

追踪​

内部追踪处理方面的一些重大改进。

追踪可见性​

我们的追踪函数使用虚幻的 TraceByObjectTypes,它不关心碰撞追踪通道。这对 nanos world 实体和出于游戏目的创建的自定义地图来说工作正常。

但我们发现一些用户制作的地图(或 FAB 地图)中有对象(如 WorldStatic)设置为忽略可见性通道上的碰撞,但查询碰撞仍然启用。这些对象仍然被我们的追踪检测到,即使它们不应该被检测到,破坏了游戏玩法的某些方面,例如沙盒的物理枪或生成菜单无法正常工作。

为了修复此问题,我们在 TraceMode 枚举中新增了 TraceMode.TraceOnlyVisibility。

这种新的追踪模式确保追踪仅返回匹配传入对象类型且具有可见性通道阻挡的对象,使其成为我们沙盒常用追踪的必备功能,并修复了我们在自定义 FAB 地图上遇到的所有问题。

撞击点​

应社区要求,我们还在追踪返回值中新增了信息:ImpactPoint,这是追踪与撞击对象碰撞的接触点!

资产包自动重载​

开发环境中的一个常见问题是开发者可以在服务器仍在运行时修改资产文件,使所有预计算的哈希在技术上无效,导致客户端本地文件不匹配,在某些情况下使用过时哈希向服务器请求更新文件,导致下载错误并阻止他们连接,直到完全重启服务器。

我们正在引入新的资产包自动重载系统!这个新系统实时检测资产文件夹内的文件更改,并排队自动重载受影响的资产包。它重新计算所有哈希(就像服务器启动时一样),允许在服务器保持在线时更新资产包。

备注

这不是热下载系统。已连接的玩家仍然需要重新连接才能下载更新的文件。

此系统旨在消除开发过程中的许多问题,如不一致的哈希、无声的不同步或神秘的崩溃。

资产包重载期间,新玩家连接将被暂时阻止,直到完全就绪。

加载屏幕数据​

我们修订了 LoadingScreen JavaScript 对象的结构。现在,server 和 player 信息整齐分离:

index.js
var LoadingScreen = {
server: {
ip,
port,
name,
description,
},
player: {
nanos_id,
nanos_username,
steam_id,
}
}
备注

旧格式现已弃用,使用时会显示警告。

新系统统计信息​

我们新增了一个小而实用的调试功能:系统统计信息。启用时它与帧时序面板一起出现,显示实时 RAM 和 VRAM 使用情况。

你可以在调试设置中启用它!

我们打算将来扩展此统计信息以显示更多信息。

更新日志 Markdown​

我们新增了一个游戏内 Markdown 解析器,可将 Markdown 转换为虚幻富文本。这意味着更新日志现在格式正确,并在菜单中精美显示:

游戏菜单更新日志控件显示标题和粗体文本

不再有纯文本或奇怪的断裂标签!

修复河流​

这快成传统了:时不时地,我们的河流(或一般的水)会完全出问题。 😅

很长一段时间以来,一个视觉漏洞导致河流看起来完全破碎,除非你手动保存设置。这影响了每张地图上的每条河流,直到现在我们都没能找到可靠的修复方法。

但我们成功实现了一个变通方案来缓解这个问题!所以河流可以再次正常流动,没有故障性的渲染缝隙。

UI 响应性​

我们修复了几个在非 16:9 宽高比(如 4:3 或 16:10)下损坏的 UI 屏幕。资源库、设置、查找服务器、新游戏等现在都已修复!

现在一切应该在常见屏幕格式下正确缩放:

资源库屏幕在 4:3 下正常显示

资源库屏幕在 16:9 下正常显示

其他改进​

文件传输改造​

我们再次对文件传输系统进行了多项改进!我们大幅改造了内部系统以改进并行下载,修复了下载每个文件时发生的所有卡顿/停顿。

我们还提高了整个系统的健壮性,以防止崩溃并提高下载的稳定性!

Lua 内部栈​

我们对 Lua 实现进行了结构性改进,以确保 API 调用现在更像原生 Lua 函数调用。现在 API 调用期间会保留 Lua 栈,而以前它总是被清空。虽然以前这没有导致重大问题,但它阻止了钩子等工具在 API 调用时访问正确的栈信息。

相关问题#932

Lua 内部内存​

我们增强了 Lua 的内部内存管理,解决了垃圾回收器在卸载后未能正确清理环境和一些用户数据的问题,导致潜在的内存泄漏。

所有实体和环境现在都正确地从内存中清除,解决了以前导致文件和数据库保持打开甚至崩溃的问题。

防火墙警报​

Windows 防火墙弹窗

我们改进了 Steam 安装过程,在安装 nanos world 时自动将所有可执行文件添加到防火墙。打开特殊 WebUI 页面或启动服务器时不再有请求权限的弹窗!

致命错误​

我们修复了大量 Failed to send Message 致命错误,这些错误由于一个内部漏洞困扰了我们很长时间。它们发生在客户端和服务器,淹没了我们的日志和崩溃报告器。

结语​

这又是一个打磨和核心改进的月份,我一直完全专注于让 nanos world 及其所有内部系统尽可能稳定,目标是达到几乎没有崩溃或慢性问题的状态。在深入开发重大新功能并能够不受干扰地专注于它们之前,这个基础至关重要。

这些改进对于为游戏构建坚实的基础至关重要:流畅的游戏玩法、一致的行为和更少的漏洞。这种可靠性是赢得玩家和开发者信任、继续在上面工作和创作精彩内容的关键!

更多 GitHub 问题已解决,在我认为这轮整理完成之前还有几个计划处理。我们新的内部崩溃处理实现已被证明非常有效,它为我解决一些罕见错误和崩溃提供了宝贵的见解。如果你遇到崩溃并知道如何复现,请告诉我们!这大大加快了修复它们的时间!

幕后已经有很多令人兴奋的事情正在开发中,我一直在获得大力支持,这将使我能够很快带来惊人的更新。

感谢大家这个月的测试和打磨!另外,感谢所有向我的 Ko-fi 捐款的人,你们的支持意义重大,帮助这一切继续下去!下个月见!! 😄

Ko-fiKo-fi