Apr: Tracy Profiler, Localization, Sync & Perf++!
Tracy Profiler, Game Localization, Better Synchronization, Performance Improvements and much more!

Welcome to our roundup of the latest updates from the last month!
Tracy Profiler Integration

Tracy frame overview
We integrated a powerful new tool to help you profiling the server-side performance: Tracy. You can now connect Tracy directly to your server and get a detailed overview of it's performance, including Lua calls, Timers, Events, network messages, loading times and much more!
This allows you to better understand your server's performance, identify real bottlenecks, and optimize your scripts and systems more efficiently.
By hovering over any bar in the timeline, you can inspect exactly what is consuming time at that moment, including detailed information about Lua calls, Timers, and callbacks:

Tracy detailed view while hovering
To use Tracy, launch the server using one of the following methods:
- Windows
- Linux
./NanosWorldServerTracy.exe
./NanosWorldServer.sh --tracy
Then connect using the Tracy Profiler client.
For more information, check the new Profiling Guide:
Profiling Guidecore-concepts/scripting/profilingLocalization
Game Localization

Main menu localized to Japanese
We are excited to announce that nanos world now supports in-game localization! You can now change the game language through Settings -> General.
Language settings
All translations are open source and available on Crowdin. If you'd like to help translate the game into your language, feel free to join the project and contribute!
We are currently supporting the following languages:
| Language | Translated | Proofread |
|---|---|---|
| German | ||
| Spanish | ||
| Finnish | ||
| French | ||
| Italian | ||
| Japanese | ||
| Portuguese (Brazil) | ||
| Russian | ||
| Turkish | ||
| Chinese (Simplified) |
We used AI-generated translations for Chinese, Russian, Italian, Japanese, and Polish, so if you are a native speaker of any of these languages, we would greatly appreciate your help proofreading the translations! Let us know if you want to be a proofreader o any language!
And if you'd like to contribute to any other language, we would be happy to add support for it as well. Just send us a message!
Alongside this feature, we also exposed new methods and events so package creators can implement their own localization systems: Client.GetLanguage() and LanguageChange (Client).
Docs Localization
Besides the game itself, our documentation is also open source and available on Crowdin.
We also implemented localization support for all API methods and event descriptions. You can now find them inside the src/api/.generated/ folder on Crowdin, fully open for translation contributions.
If you'd like to help translate the documentation into your language, join the Crowdin Docs project and start contributing! If you want to help with a new language, just send us a message so we can add it to the project.
Loading Screen Improvements

We implemented a new system that locally caches the server requirements list. This means that if you reconnect to a server you've already joined before and its requirements haven't changed, the client will skip downloading them again and load them directly from the local cache.
This significantly improves loading times for large servers, especially when reconnecting after a disconnect or kick.
We also added several new loading steps to provide clearer feedback about what is happening during the connection process, helping players better understand each stage of loading.
Additionally, we greatly improved the performance of the Validating Files step, reducing loading times for servers with large amounts of content and requirements.
Performance & Optimization
Networking
We drastically improved server performance for high player counts by introducing a new internal system that bundles all pending network messages together and flushes them at the end of each server frame. This allows us to optimize message ordering and reduce internal networking overhead.
The same optimization was also implemented on clients, significantly improving the performance of internal networking API calls.
Another major improvement is how we handle transient sync data such as VOIP, movement, rotation, velocity, and jumps. These updates are now treated as unreliable, making them almost 10x faster to process.
To avoid issues such as characters visually "moving in place," we also implemented a client-side desync detection system that automatically stops character movement when updates are not received for a certain period of time.
API Events
We introduced another internal optimization for Events by skipping argument construction entirely when no subscribers exist for that event.
Previously, parameters and intermediate tables were always being copied and constructed even if nobody was listening to the event. Now, argument construction is deferred until we know there is at least one subscriber.
This significantly improves performance for frequently (not used) triggered events.
Caching
Server.SetValue
Now, Server.SetValue() synced values are automatically cached and compressed before being sent to joining clients.
This makes Server.SetValue() a much more efficient option for persistent synchronized data compared to manually sending data through Events.CallRemote() when players join.
We also implemented a chunking system for larger Server.SetValue() payloads, since the internal networking layer has a maximum packet size limitation of 512 KB, this new systems allow sending larger data through Server.SetValue() without issues by automatically splitting it into multiple chunks and reassembling it on the client side.
Other Internal Caches
We implemented several new internal caches and lookup lists for players, entities, characters, and other frequently accessed data.
This avoids repeated internal iterations and improves the performance of multiple systems that rely heavily on these collections.
API Methods Calls
We also refactored several internal Lua API calls, making them considerably faster and more efficient, especially for simple methods without parameters or return values.
Amélioration des scripts
Defer Entity Spawn System
We implemented a new Defer Spawn system for entities, allowing you to create entities without immediately spawning them on clients until you explicitly call Entity:FinishSpawn().
This is extremely useful when configuring multiple properties after creation, avoiding unnecessary intermediate network updates.
For that, we added a new last parameter to most of entities constructor defer_spawn, when setting it to true, you must call FinishSpawn() after setting all the values you need on that entity, to actually spawn it on the clients. Any API call that does a networking sync will not be transmitted before Finishing the Spawn of that entity.
Usage example:
local mesh = "nanos-world::SK_Chicken"
local abp = "nanos-world::ABP_Chicken"
-- Pass 'defer_spawn' as 'true' to the last parameter of the constructor
local chicken = CharacterSimple(Vector(), Rotator(), mesh, abp, ColisionType.Auto, true, true)
-- Set everything we want
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)
-- Actually spawn it on clients
chicken:FinishSpawn()
When using Inherited Classes System, the FinishSpawn() is automatically internally called after leaving the constructor of the inherited class, so you don't need to call it manually in that case:
function MyAK47:Constructor(loc, rot)
-- Pass 'defer_spawn' as 'true' to the last new Weapon parameter
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")
-- It's not needed to call FinishSpawn() here
end
Using the Defer Spawn system is highly recommended when optimizing performance and reducing network usage, since the final entity state can be sent in a single compressed synchronization instead of multiple updates.
Deprecated VehicleWheeled auto_create_physics parameter
With the introduction of the new Defer Spawn system, the auto_create_physics parameter of VehicleWheeled has been deprecated, since vehicles can now be configured more efficiently before spawning.
New Methods & Events
All new methods and events related to this month's features and improvements are listed below.
New Methods
New Events
Improved APIs
- VOIP (e.g.
Player:SetVOIPGlobalChannelSetting()) now support up to 63 channels instead of 31. - Most of entities constructor got a new
defer_spawnparameter to use the new Defer Spawn workflow.
Sync
We made several improvements to actor and character synchronization, improving overall consistency, stability, and performance while fixing multiple edge-case sync issues.
One of the main improvements was enhancing client-side interpolation. The hard snap system (which teleports actors when they become too far from their synced position) is now dynamically adjusted based on actor speed, making fast-moving actors significantly less likely to snap abruptly.
New Distant Fix-up System
Since distant actors optimized with distance_optimization are not updated for far-away players, we implemented a new Distance Fix-up System.
Previously, far-away actors would only update again after moving. Now, the client tracks which actors are considered "sleeping" and automatically requests updated data from the server whenever the player gets close to them again.
This ensures actors always have accurate positions and rotations when becoming relevant again.
New Water Buoyancy Config
We added a new property to the map Package.toml: enable_water_buoyancy.
Maps using Unreal's Water Plugin must now explicitly enable this option if they intend to use buoyancy components on Actors.
This allows actors to skip unnecessary Water physics logic and Pontoon component creation on maps that do not require water simulation.
For more information, check the Package Guide:
Map Package.tomlcore-concepts/packages/packages-guideUI Improvements
We added a new fps 1% low metric to the detailed frame timings debug information. This value displays the average framerate of the slowest 1% of frames during the last minute.
New fps 1% low metric in debug view
The Playtest quit popup will also no longer appear after pressing the Wishlist button:

Quit popup when in Playtest
We also improved Windows taskbar loading progress so it now displays the overall loading progress instead of only the current loading step progress:
Taskbar progress while connecting to a server
Server Browser

nanos world Find Servers tab
The Server Browser now displays servers from both the Main and Playtest AppIDs, making it easier to discover all available servers regardless of which branch you are currently using.
Note that connections between different AppIDs are still restricted. For example, Playtest clients cannot connect to Main servers.
C:/Users/ Path Encoding Fix
We also finally solved a long-standing issue affecting users whose Windows usernames contained accented or non-UTF8 characters in their C:/Users/ directory.
This issue could previously cause crashes and prevent Packages or WebUI content from loading correctly.
Paths are now properly encoded, allowing affected users to play normally without any issues.
Updated Deps
- Updated HTTP library to 0.43
- Updated CEF to version 147
- Updated Sentry to 1.11
- Updated SQLite to 3.53
- Updated several other internal dependencies to their latest versions
Conclusion
April was heavily focused on core engine improvements, networking optimizations, loading performance, synchronization reliability, and overall quality-of-life upgrades for both players and developers.
From the Tracy profiler integration and the new localization system to major networking refactors and scripting optimizations like Defer Spawn, this update brings substantial improvements across nearly every area of nanos world.
We also continued polishing many long-standing issues and internal systems, improving stability, scalability, and the overall development experience.
As always, thank you to everyone contributing feedback, translations, bug reports, and packages for the community. Your support continues to help shape nanos world into a better game every month! 💙🩵
See you in the next update!


