4 月:Tracy 分析器、本地化、同步与性能++!
Tracy 分析器、游戏本地化、更好的同步、性能提升以及更多精彩内容!

欢迎阅读我们上个月最新更新的汇总!
集成 Tracy 性能分析器

我们集成了一个强大的新工具来帮助你分析服务器端的性能:Tracy。你现在可以直接将 Tracy 连接到你的服务器,并获得其性能的详细概览,包括 Lua 调用、计时器、事件、网络消息、加载时间等等!
这可以让你更好地了解服务器的性能,识别真正的瓶颈,并更高效地优化你的脚本和系统。
通过将鼠标悬停在时间线上的任何条上,你可以精确地检查当时是什么在消耗时间,包括关于 Lua 调用、计时器和回调函数的详细信息:

要使用 Tracy,请使用以下方法之一启动服务器:
- Windows
- Linux
./NanosWorldServerTracy.exe
./NanosWorldServer.sh --tracy
然后使用 Tracy 性能分析器客户端进行连接。
欲知更多信息,请查看全新的性能分析指南:
性能分析指南core-concepts/scripting/profiling本地化
游戏本地化

我们很高兴地宣布,nanos world 现在支持游戏内本地化了!你现在可以通过 设置 → 常规 来更改游戏语言。
所有翻译均已开源,并可在 Crowdin 上查看。如果你想帮助将游戏翻译成你的语言,欢迎加入该项目并做出贡献!
我们目前支持以下语言:
| 语言 | 已翻译 | 已校对 |
|---|---|---|
| 德语 | ||
| 西班牙语 | ||
| 芬兰语 | ||
| 法语 | ||
| 意大利语 | ||
| 日语 | ||
| 葡萄牙语(巴西) | ||
| 俄语 | ||
| 土耳其语 | ||
| 简体中文 |
我们对中文、俄语、意大利语、日语和波兰语使用了 AI 生成的翻译,因此如果你是这些语言的母语使用者,我们将非常感激你能帮助校对这些翻译!如果你想成为任何语言的校对员,请告诉我们!
如果你想为其他任何语言做出贡献,我们也很乐意添加对其的支持。只需给我们发送消息即可!
伴随着这一功能,我们还开放了新的方法和事件,以便资源包创作者可以实现他们自己的本地化系统:Client.GetLanguage() 和 LanguageChange (Client)。
文档本地化
除了游戏本身,我们的文档也是开源的,并可在 Crowdin 上查看。
我们还对所有 API 方法和事件描述实现了本地化支持。你现在可以在 Crowdin 上的 src/api/.generated/ 文件夹中找到它们,完全开放以供翻译贡献。
如果你想帮助将文档翻译成你的语言,请加入 Crowdin 文档项目并开始贡献!如果你想帮助一种新语言,只需给我们发送消息,以便我们将其添加到项目中。
加载屏幕改进

我们实现了一个新系统,可以在本地缓存服务器的需求列表。这意味着如果你重新连接到一个你之前已经加入过且其需求没有发生变化的服务器,客户端将跳过重新下载,而是直接从本地缓存中加载它们。
这显著改善了大型服务器的加载时间,特别是在断开连接或被踢出后重连时。
我们还添加了几个新的加载步骤,以对连接过程中发生的事情提供更清晰的反馈,帮助玩家更好地理解加载的每个阶段。
此外,我们大幅提升了校验文件中步骤的性能,减少了拥有大量内容和需求的服务器的加载时间。
性能与优化
网络
我们通过引入一个新的内部系统,大幅提升了高玩家数量下的服务器性能,该系统会将所有待处理的网络消息打包在一起,并在每个服务器帧结束时统一刷新。这使我们能够优化消息排序并减少内部网络开销。
同样的优化也在客户端上实现,显著提高了内部网络 API 调用的性能。
另一个重大改进是我们处理瞬态同步数据(如语音通话、移动、旋转、速度和跳跃)的方式。这些更新现在被视为不可靠的,使其处理速度快了近 10 倍。
为了避免出现角色在视觉上“原地移动”等问题,我们还实现了一个客户端断连检测系统,当在一定时间内未收到更新时,该系统会自动停止角色移动。
API 事件
我们通过在没有该事件的订阅者时完全跳过参数构建,为事件引入了另一个内部优化。
此前,即使没有人监听该事件,参数和中间表也总是会被复制和构建。现在,参数构建会被推迟,直到我们知道至少有一个订阅者为止。
这显著提升了频繁触发(但未被使用)的事件的性能。
缓存
Server.SetValue
现在,Server.SetValue() 同步的值在发送给正在加入的客户端之前,会自动进行缓存和压缩。
与玩家加入时通过 Events.CallRemote() 手动发送数据相比,这使得 Server.SetValue() 成为处理持久化同步数据时一个更高效的选择。
我们还为较大的 Server.SetValue() 有效载荷实现了一个分块系统,因为内部网络层有 512 KB 的最大数据包大小限制,这个新系统允许通过 Server.SetValue() 发送更大的数据而不会出现问题,它会自动将数据拆分为多个块并在客户端重新组装。
其他内部缓存
我们为玩家、实体、角色和其他频繁访问的数据实现了几个新的内部缓存和查找列表。
这避免了重复的内部迭代,并提高了严重依赖这些集合的多个系统的性能。
API 方法调用
我们还重构了几个内部 Lua API 调用,使它们明显更快、更高效,特别是对于没有参数或返回值的简单方法。
脚本改进
延迟实体生成系统
我们为实体实现了一个全新的延迟生成系统,允许你创建实体而不会立即在客户端上生成它们,直到你显式调用 Entity:FinishSpawn()。
这在创建后配置多个属性时非常有用,可以避免不必要的中间网络更新。
为此,我们向大多数实体构造函数添加了一个新的最后一个参数 defer_spawn,当将其设为 true 时,你必须在设置完该实体所需的所有值后调用 FinishSpawn(),才能在客户端上实际生成它。任何执行网络同步的 API 调用在完成该实体的生成之前都不会被传输。
使用示例:
local mesh = "nanos-world::SK_Chicken"
local abp = "nanos-world::ABP_Chicken"
-- 将 'defer_spawn' 作为最后一个参数传为 'true' 给构造函数
local chicken = CharacterSimple(Vector(), Rotator(), mesh, abp, ColisionType.Auto, true, true)
-- 设置我们想要的一切
chicken:SetHealth(50)
chicken:SetMaxHealth(50)
chicken:SetAirControl(0.5)
chicken:SetJumpZVelocity(300)
chicken:SetGravityScale(0.5)
chicken:SetCapsuleSize(20, 20)
chicken:SetSpeedSettings(300, 150)
chicken:SetAIAvoidanceSettings(true, 30)
chicken:SetRotationSettings(Rotator(0, 500, 0), false, true)
-- 实际在客户端上生成它
chicken:FinishSpawn()
当使用继承类系统时,FinishSpawn() 会在离开继承类的构造函数后在内部自动调用,因此在这种情况下你无需手动调用它:
function MyAK47:Constructor(loc, rot)
-- 将 'defer_spawn' 作为最后一个新的 Weapon 参数传为 'true'
self.Super:Constructor(loc, rot, "nanos-world::SK_AK47", CollisionType.Auto, true, true)
self:SetAmmoSettings(30, 1000)
self:SetDamage(30)
self:SetSpread(30)
self:SetRecoil(0.25)
self:SetBulletSettings(1, 30000, 30000, Color(100, 58, 0))
self:SetSightTransform(Vector(0, 0, -1), Rotator(-1.5, 0, 0))
self:SetLeftHandTransform(Vector(22, 0, 9), Rotator(0, 60, 90))
self:SetRightHandOffset(Vector(-10, 0, 0))
self:SetHandlingMode(HandlingMode.DoubleHandedWeapon)
self:SetCadence(0.1)
self:SetWallbangSettings(200, 0.75)
self:SetParticlesBulletTrail("nanos-world::P_Bullet_Trail")
self:SetSoundDry("nanos-world::A_Rifle_Dry")
self:SetAnimationCharacterFire("nanos-world::AM_Mannequin_Sight_Fire")
self:SetAnimationReload("nanos-world::AM_Mannequin_Reload_Rifle")
...
self:SetMagazineMesh("nanos-world::SM_AK47_Mag_Empty")
self:SetCrosshairMaterial("nanos-world::MI_Crosshair_Regular")
-- 这里不需要调用 FinishSpawn()
end
在优化性能和减少网络占用时,强烈建议使用延迟生成系统,因为最终的实体状态可以在单次压缩同步中发送,而不是进行多次更新。
弃用 VehicleWheeled 的 auto_create_physics 参数
随着新延迟生成系统的引入,VehicleWheeled 的 auto_create_physics 参数已被弃用,因为现在可以在生成载具之前更高效地对其进行配置。
新方法与事件
下面列出了与本月功能和改进相关的所有新方法和事件。
新方法
新事件
改进的 API
- 语音通话(例如
Player:SetVOIPGlobalChannelSetting())现在支持多达 63 个频道,而不是 31 个。 - 大多数实体构造函数都获得了一个新的
defer_spawn参数,以使用新的延迟生成工作流。
同步
我们对 Actor 和角色的同步进行了多项改进,提升整体的一致性、稳定性和性能,同时修复了多个边缘情况下的同步问题。
主要的改进之一是增强了客户端的插值。强行对齐系统(当 Actor 距离其同步位置太远时将其传送)现在会根据 Actor 的速度进行动态调整,这使得快速移动的 Actor 突然发生对齐跳跃的可能性大大降低。
新的远距离修正系统
由于使用 distance_optimization 优化的远距离 Actor 不会为遥远的玩家更新,我们实现了一个全新的远距离修正系统。
以前,远处的 Actor 只有在移动后才会再次更新。现在,客户端会跟踪哪些 Actor 被视为“睡眠”,并在玩家再次接近它们时自动向服务器请求更新的数据。
这确保了 Actor 在重新变得相关时始终拥有准确的位置和旋转。
新的水体浮力配置
我们在地图的 Package.toml 中添加了一个新属性:enable_water_buoyancy。
使用虚幻的水体插件的地图现在如果打算在 Actor 上使用浮力组件,必须显式启用此选项。
这使得在不需要水模拟的地图上,Actor 可以跳过不必要的水体物理逻辑和 Pontoon 组件的创建。
欲知更多信息,请查看包指南:
地图 Package.tomlcore-concepts/packages/packages-guideUI 改进
我们在详细的帧时间调试信息中添加了一个新的 1% 最低帧 指标。该值显示过去一分钟内最慢的 1% 帧的平均帧率。
在按下加入愿望单按钮后,游戏测试的退出弹窗也将不再出现:

我们还改进了 Windows 任务栏的加载进度显示,现在它会显示总体的加载进度,而非仅显示当前加载步骤的进度:
服务器浏览器

服务器浏览器现在会同时显示来自 主要 和 游戏测试 AppID 的服务器,从而更容易发现所有可用的服务器,无论你当前使用的是哪个分支。
请注意,不同 AppID 之间的连接仍然受到限制。例如,游戏测试客户端无法连接到主要服务器。
C:/Users/ 路径编码修复
我们还终于解决了一个长期存在的问题,该问题会影响那些 Windows 用户名在 C:/Users/ 目录中包含重音符号或非 UTF8 字符的用户。
此问题以前可能会导致崩溃,并阻止包或 WebUI 内容正常加载。
路径现在已被正确编码,允许受影响的用户正常进行游戏而不会出现任何问题。
更新依赖项
- 更新 HTTP 库至 0.43
- 更新 CEF 至版本 147
- 更新 Sentry 至 1.11
- 更新 SQLite 至 3.53
- 更新了其他几个内部依赖项至其最新版本
结语
4 月份的重点主要放在核心引擎改进、网络优化、加载性能、同步可靠性以及面向玩家和开发者的整体生活质量升级上。
从 Tracy 性能分析器的集成和新的本地化系统,到重大的网络重构以及像延迟生成这样的脚本优化,本次更新为 nanos world 的几乎每个领域都带来了实质性的提升。
我们还继续打磨了许多长期存在的问题和内部系统,提高了稳定性、可扩展性和整体开发体验。
一如既往,感谢所有为社区贡献反馈、翻译、错误报告和资源包的每一个人。你们的支持持续帮助着 nanos world 每月变得更好! 💙🩵
下一次更新再见!


