1. Neos VR
  2. News
  3. More optimizations improving performance, MMC coming to end, 17 languages

More optimizations improving performance, MMC coming to end, 17 languages

Hello, and welcome back to the Neos Weekly Update!

This week we have a few topics to cover, from the MMC coming to an end, more optimizations, audio bug mitigations, and new Neos translations. We went through a chunk of MMC entries on the official livestream, if you missed it, you can watch the recording below!

So far we’ve heard a lot of positive feedback from you on being able to maintain a stable framerate even in sessions with over 20 people and unoptimized avatars! There are many more optimizations to come and we strive to keep moving that number higher and higher.



We fit as many people as we could into a single session!

[h2]Metaverse Maker’s Competition coming to an end![/h2]
The MMC has come to a close, and currently the submissions are being voted on! As of currently writing this post, community voting is still underway so if you haven’t voted on your favorite MMC submissions, now’s your chance!

Once the community votes are submitted, the Judges will start viewing submissions from the 4th to the 8th, and after they will cast their votes. There are 79 entries, and 201 participants, so this will be a massive undertaking since community turnout was so amazing!

Frooxius, 0utsider and Medra will be Judging alongside Kent Bye and Jak from Disrupt, who have graciously agreed to participate in judging the submissions. We’re honored to have them with us during this event, thanks guys!

[h2]Optimizing the blendshape impact of your avatars[/h2]
One of the major performance related optimizations this week was a group of functions for optimizing skinned meshes, typically used for full body avatars. One common way that many avatars can waste performance are blendshapes, particularly when blendshapes affect only a small portion (like the face), but the avatar is a single skinned mesh.

In such cases, the blendshapes for the rest of the body are zero, but they still have to be all recalculated with every change. For geometry dense avatars this can be very wasteful. From our tests the actual affected geometry of a 50K vertex avatar can be around 2000-5000 vertices. This means that every time the face blendshapes update, over 45K vertices are wastefully recomputed with no actual difference.

To help remedy this, there is now a new option called “Separate parts of mesh unaffected by blendshapes”. This will automatically split up your mesh into triangles that are affected by blendshapes and ones that are not. For geometry dense avatars this can provide a significant performance boost.

However adding extra mesh adds its own performance cost, so whether this is a good optimization to make will depend on a few factors. Particularly on the absolute number of vertices that are unaffected by the blendshapes.

If it’s in the range of dozens of thousands, it’s generally a good optimization to make. If most of the mesh is affected by blendshapes (e.g. blend shapes that change the body type) or overall the avatar is low poly, it’s better to leave it as is. You can test the impact by spawning multiple copies of the avatar in an empty world and comparing performance.

[h3]To optimize your avatar we recommend following steps:[/h3]
  • First if possible, bake all the separate meshes into a single one first. If you don’t change outfits often, it can be worth having a separate copy of your avatar for edits and then a baked optimized version for social use.
  • If not, using the new option “Merge submeshes with the same material” can help reduce draw calls if you’re using the same material for multiple parts of the avatar.
  • Run the “Separate parts of mesh unaffected by blendshapes” on the resulting mesh(es). If the resulting unaffected part has a lot of geometry, keep this version.

To help you with making more changes and tweaks, we’ve also added other mesh processing tools in-game. For example you can now split skinned mesh into multiple meshes based on the material or strip empty bones from mesh data.

[previewyoutube][/previewyoutube]
WARNING: Has loud music on!

You can also use a new “Proxy” method for updating the bounding box of your mesh from another mesh. For example if you run into issues with a small separate chunk of your avatar de-rendering, you can configure it to use bounds of a bigger mesh. This option is very cheap as it doesn’t require any real time calculations, so it is even more performant than the FastDisjointRootApproximate method.

We hope that providing those quick to use optimization tools directly in-game will allow everyone to better optimize their content and avatars and help achieve better performance in worlds. We’re also looking into ways to automate this system to make the iteration process very quick and painless.

[h2]Hierarchy moved event system redesign[/h2]
Another notable optimization this week was the redesign of the system for propagating moved events through the hierarchy e.g. when a parent object moves, some child objects deeper in the hierarchy need to know about this, for example any objects with colliders on them.

Previously this system was coupled with other events, such as activation and deactivation and general changes. This caused movement events to be propagated into parts of hierarchy where it wasn’t necessary as well as parts of hierarchy that were disabled locally. The system would also have to go through all immediate children, even if only a few of them actually contain part of the hierarchy listening to the events.

The new system is built on the same framework created for the dynamic variables for notifying about hierarchy changes. This system pretty much solves all of the above problems. It comes at some small overhead and memory cost, but in most scenarios it comes significantly on top, by significantly reducing wasted cycles.

To help better utilize this system the general change events were fully decoupled from transform changes as well and components and LogiX now explicitly listen to moved events only when needed (e.g. for LogiX only when it’s locally active).

As a result a lot of wasted cycles are saved both in complex worlds and with avatars or items. Particularly when avatars have complex hierarchies that are active only for a particular user, those hierarchies will no longer need to listen on the events for other users.

While this subtly changes some of the behaviors, for the most part it remains the same. We have tested a range of items, avatars and worlds to make sure nothing is broken, but if you do find anything broken by the optimizations, please let us know!

[h2]Audio Bug mitigations, moving LogiX visuals and other optimizations[/h2]
One of the infamous problems affecting many users is the “audio bug”, causing stuttery audio after a long use or particularly impactful scenarios. Unfortunately the actual source of the problem is a bug in the Steam Audio Spatializer, so we can’t fix the underlying issue ourselves, but we have implemented a range of mitigations that should also help with overall performance.

In short, audio outputs that are part of disabled hierarchy will not allocate an audio source in the spatializer until they’re activated. The update loop will now also delay updating connectors if the world is currently in the background.

This fixes cases where actions in background worlds would cause the audio bug, due to the spawned audio sources being allocated even if not needed, but it skips many other unnecessary updates to audio-visual output as well.

Having unpacked LogiX should now also perform significantly better if the whole setup is moving in the world. Previously subtle numerical differences in the wire mesh parameters would constantly force the meshes to update, which in turn forces the colliders to update. This would cause heavy CPU utilization, sometimes completely overwhelming weaker machines and causing other things like the core UI to not update.

[h2]New Translations: Spanish, Russian, Estonian, Norweigan, Polish[/h2]
We’ve been receiving new translations by our community members to localize Neos in their languages. Neos is now available in 17 languages and 2 variants!

Skywind Kitsune has been working on Spanish, PineappleDreams on Estonian, REBORN on Norweigan, Art0007i on Polish, and GhostZ36 and BrotiwkA on Russian. Thank you for your continued help on making Neos available to speakers of your native languages!

Steam doesn't even allow us to list all of the supported languages!

[h2]Community Highlights[/h2]
[h3]We fit 32 people in The Roost![/h3]
Ark Gullwing’s The Roost has been mentioned in the community highlights before, but this weekend we fit 32 normal avatars onto the dancefloor with a tolerable framerate. It was a real pumped up night! We definitely can’t wait for the huge dance parties of Neos’s future!
[previewyoutube][/previewyoutube]

[h3]MMC Showcase Livestream - Part 1[/h3]
Nexulan and friends went through a lot of the MMC worlds this past Friday stream, showing off the many creations and submissions by competitors. It was quite a fun show, so check it out here if you missed the stream!

Because of the huge volume of the entries, we only covered part of them so far. Make sure to tune in for the next stream to see more!
[previewyoutube][/previewyoutube]

[h2]What’s Next?[/h2]
Our plan is to continue on with many optimizations to keep improving the overall performance of Neos. We’ll be likely refactoring the engine update loop system, to support more efficient and flexible bucketing and grouping of items, in order to enable things like variable rate updates, native asynchronous multithreaded updates and more efficient data based updates. It’ll also allow for marking certain components as constantly updated, to reduce overhead of tracking changes every frame.

Similarly we’ll also refactor the connector system, which pushes Neos changes to the Unity renderer, which now has significant amounts of overhead and investigate decoupling from the Neos’ update loop, to allow for better parallelization and in the future also complete process separation.

Currently the upgrade to BEPUv2 is halted due to a Unity JIT compiler bug. We’re waiting on bugfix to be backported from Unity 2020.1. We’d also like to upgrade to this version of Unity, but unfortunately this is blocked by another bug in the renderer when using single pass rendering. We have reported this bug to Unity and are waiting on a fix while we work on the other optimizations.

There are many more planned optimizations, if you’d like to check out details, we recommend looking at the #devlog channel on our official Discord and the official GitHub. We can’t wait to bring you more performance updates to make your Neos experience a lot more comfortable!