On Udon 2, Soba and Why We Changed Directions

Hello everyone! So, let me cut right to it: Our announcement of Soba / the change in direction from Udon 2 didn’t go well.

There were a lot of things we could’ve done better, and that starts with explaining why we changed direction in the first place.

Udon 2 Development Troubles

From the community’s perspective, Udon 2 was a massive upgrade to Udon that would deliver more features and significant performance improvements. However, behind-the-scenes development was more difficult than initially anticipated.

We knew about many of these issues relatively early on, but they seemed solvable. As time went on, more and more issues began cropping up with development. Some of these issues are related to the initial performance promises made of Udon 2 in the first place.

Internal benchmarking showed that, while in certain situations the initial performance improvements of Udon 2 held up, these situations were extremely specific and unlikely to mimic “real life” usage.

While math-heavy code would see an improvement (which was one of the reasons why we showed off a procedurally generated maze as having a performance increase), more standard code would not see the same huge benefits.

Diving Into Udon 2 Performance Struggles

To go a little deeper on this: Code built to be optimized in Udon uses techniques that were directly counterproductive in Udon 2. In Udon, as it stands now, if you want to write performant code, you are incentivized to outsource work to externs (functions that execute outside of Udon in the native C# environment).

In Udon 2, however, relying on externs too heavily results in significant penalties due to marshalling – the process of copying data in and out of Udon 2. Those penalties were severe enough that in some situations they would negate the execution speed bonuses of Udon 2, causing the overall performance to be worse.

We communicated this in a positive way early on: we thought that there was still reason to push forward because you would get a good amount of benefits immediately, and if you change the way you write your code you can get even more benefits. That turned out to be not entirely true, and the reality of the situation was that in the worst cases, you would need to rewrite your code just to get any benefit at all.

As development continued, it became more apparent this was a bad idea. If you are writing a “sequel” to another language used by most of your advanced creators, and you tell them they have to rewrite their code in a different style in order to get any significant benefits… that’s not exactly “creator friendly.”

Spotting Major Issues for Creators

Additionally, if you didn’t reupload your world with the Udon 2 SDK, the Udon 2 client would run in a “compatibility mode” that ran “original” Udon inside Udon 2. This was almost always slower than “original” Udon would’ve ran by itself – in internal benchmarks, this compatibility mode took anywhere from two to ten times longer to run existing code.

This created a situation where we had to decide to either include both Udon and Udon 2 in the client (which resulted in even bigger memory regressions than the ones Udon 2 already had) or to ship with this compatibility mode which would punish anyone using “old” Udon code – which would then force them to fix a bunch of compiler errors, else they wouldn’t be able to upload their world.

This was a problem that had been worked on for months without any significant progress being made, and served as yet another major roadblock from Udon 2 ever making it to creators.

The Sunk Cost Fallacy and Cutting Losses

Of course, there was a big desire here to bring Udon 2 across the finish line, and to some extent, we fell into the sunk-cost fallacy. As commenters had pointed out, two years of work had gone into this project (which initially was only supposed to take 3 - 6 months to complete), and there was still a feeling from the engineering side that these were all solvable problems.

Udon 2 was also a complex project, built with complex code. This led to significant problems with benchmarking and diagnosing issues, with engineers on the team struggling to get a stable “real world” project running using Udon 2.

That is to say nothing of fears about how negative the end user experience could have been, too. Forcing people to rewrite their code – not just to see performance gains, but to get their worlds to compile at all – became a serious concern.

Udon 2 Continues to Hit Roadblocks

Late into development, as more of Udon 2 made it to our internal QA team, these issues (and more – some of which were shared in the previous thread, such as a severe memory regression on all platforms) became more apparent.

Other problems also cropped up with differences in Udon 2’s performance between the VRChat client and the editor. While this happens with original Udon, it is fairly consistent and predictable – with Udon 2, these performance gaps were massive and inconsistent. This meant that you might tweak your code, expect it to be faster due to its performance in the editor, then run it in VRChat and see a serious regression.

Taking a Hard Look at Udon 2

Eventually, all of these issues above led to a very real internal question: Is Udon 2 something that can reasonably be released? Can we achieve the initial promises made when Udon 2 was announced?

Going all-in on Udon 2 also carried a few additional risks, which led to even more questions: If we ship Udon 2 as a complete replacement for Udon, how much content were we willing to break? How long would it take to get old VRChat content “working”?

These are questions that were made more difficult by the fact that the Udon 2 development branch was severely behind VRChat’s main development branch. It would have taken weeks – if not months – to get Udon 2 running in the latest version of VRChat. The Udon 2 internal branch had gotten so complex, that fundamentally it wasn’t workable by most of the team, creating a huge bottleneck.

This led to a large engineering review of the project. What was discovered was that continuing development on Udon 2 would be irresponsible. Shipping it, maintaining it, improving on it, or delivering more “user-friendly” tools on top of all of that would all be far out of reach.

The question then became “okay, Udon 2 is unshippable. Can we still achieve the initial goals set by the project?”

Why We Moved Forward With Soba

A proposal was then made internally for Soba. Soba’s point is simple: It fulfills most of those original promises and does so in a way that is far easier for the team to maintain and iterate on quickly. It also solves some of the engineering problems we discussed earlier. For example, Soba doesn’t require marshalling like Udon 2 does.

In short, while Soba hasn’t reached parity with Udon 2 yet, it has progressed at a much faster pace. Likewise, it is being built from the ground up with a focus on being maintainable across multiple contributors and scalable instead of trying to sew together a series of hacks to make it work.

We’ve also seen some concern about Soba failing to address how Udon (or Udon 2) is difficult to use for newer creators. While we want to do that, and we’re mindful of it, we’re trying not to fall back into the old VRChat mindset of promising the world and delivering none of it. We’ll complete this task, then ingest feedback, carefully plan our next steps, and iterate.

Lessons Learned, Moving Forward

At the same time, the above history is why we’re so leery about sharing benchmarks. It’s also, in a large way, an artifact of an older VRChat that operated differently. We’re a lot more focused now, which has led to us being able to finish long-standing projects (like Persistence) and tackle major asks from the community (like Age Verification) without spinning our wheels as we have in the past.

Without going further off the rails in this post, I know that there are other projects the creator community really cares about that haven’t made it past the finish line yet. We know. Further, we know that you want more transparency about them. A big obvious question and fear that we’re potentially facing with this post is: how do we know this won’t happen to those things, too?

The honest answer? I can’t promise they won’t. However, if they get cut, delayed, or changed, we think the community at least deserves an answer as to why right out of the gate, as detailed as this one.

During the development of Udon 2, many lessons were learned, many of them hard lessons. While this post isn’t going to make the loss of Udon 2 any easier – we know we hyped it up far too much, and we know that it was promising things that creators really wanted – but we hope it makes our decisions more understandable.

38 Likes

Thanks for elaborating some more on the decision. There’s a lot I’d like to say, but ultimately given the circumstances you made the choice that you felt made sense for you. Thank you for taking the time to put this together. And thank you for formatting this less as a “corporate speak” post.

I’m still frustrated about this as I’m sure others are, but I do not want to press it further personally since I don’t think it would change much. I think your messaging would’ve been received a bit better if this was the kind of thing you started with. Sorry for getting heated, and sorry to everyone reading this, I wish stuff had gone differently.

42 Likes

This is some welcome transparency! Thank you for taking the time to write this out.

I feel like a lot of the dramatic replies of the previous developer update could have been avoided by briefly explaining that Udon 2 was no longer viable in the main post rather than not even mentioning it at all. A lot of creators had given up on Udon 2 after waiting so long, so seeing it replaced with no mention at all was shocking.

Looking forward to Soba’s development. I’m personally hoping it will allow for an easier way to network sync objects such as toggles and buttons, currently I feel like it’s much too complex and unreliable with Udon Graph or UdonSharp.

9 Likes

Likewise, I really appreciate getting the more in depth explanation over what initially felt like an awkward not-fully-addressed pivot from what had previously been shown and planned, so thank you and the team for taking the time to do that. It helps both to provide the context to better understand the intention of the change, as well as gives a better picture of what we can realistically expect by understanding why it was chosen to begin with.

8 Likes

Sweet, I love Soba drinks! Noodles are overrated anyway. I don’t know how I got here or what im talking about.

5 Likes

Ditto. From my personal perspective on the whole situation, it seemed like communication about the future of U2 wasn’t very good on day 1 of the Soba announcement. I was initially confused about whether Soba was a direct replacement for U2 or a completely separate project in the works. Seemed like U2 was suddenly dropped for (what people claim to be) a downgrade from what was originally promised. That, and the feedback forums got name changes to Soba, which was also pretty confusing. In summary, discontinue in-dev highly requested and hyped feature with not communication + sudden new feature that appears to not fully deliver on hyped feature’s claims = bad understanding of what’s going on. The hyping up of U2 made it seem like a giant game changer to VRChat world creation for sure, as why I was excited for it, and so were many of us.

There are a couple of things I would respectfully like to criticize about the whole situation. First is the initial announcement. I believe it would have been miles better and less chaotic if a post with this transparency was included in a dev update, perhaps, that announces the discontinuation of Udon 2. Nitty and gritty details are sometimes needed to fully understand a situation like this. Not having the full context really failed at cultivating a positive discussion forum to discuss things respectfully. It would also be far less confusing as to what is happening. Second is the re-naming of the canny posts. Since U2 and Soba are 2 different things, it seemed very confusing when the canny post was renamed, especially since I had no idea Udon 2 was long gone by this point. Where did my Udon go?? NOOO!!! :sob:. I would highly recommend not renaming cannies to completely different names for completely different features.

Though, I am very pleased with this follow up post, as it goes over why U2 was such an ass kicker, what it would mean if it was pushed in it’s current state, why the pivot to Soba was done, and what was learned/will work hard AF to not repeat in the future. This level of transparency is wonderful to see. Development is not a straight shot by any means and I get that fully. Hurts even more that such a revolutionary system unfortunately is not feasible in the end. It’s a fine balance between teasing new things to prepare users about what’s coming in the future, but also not getting to ahead of yourselves and reveal things you couldn’t actually deliver on. I do really want to thank VRChat for providing this deep dive into U2 and Soba. I have few criticisms personally of the communications I see but I felt this one needed some feedback from someone like myself. I said all this because I want VRC to take the feedback and use it to prevent a situation like this from happening again, because I love this platform. I desperately want to see VRC keep improving in all aspects, and I hope my post helps to fill the feedback bin on communications.

That being said, I am excited for when Soba is ready. Seems pretty epic. Thanks for all the hard work, and I hope the communications team sees this fr (I spent a half hour writing this I should go to bed)

2 Likes

Good lesson for VRChat in the future.

This is a decent piece of PR.

Maybe you could hire a PR consultant for a few months, I think it would help.

2 Likes

Hi, this is a nice explanation as to why Soba was chosen ober Udon 2, however Im curious as to why Luau maintained by Roblox was not chosen?
It appears to fit all this criteria, with the added benifit of great performance as well as nice documentation.

Any numbers and explanations or we just need to believe you despite all the lies we received in all these years?

As would be interesting to see benchmarks, examples, and analysis for cases like that - where its actually slower. As using externs being slower is imho expected by most experienced developers, its the same when writing code for most scripting language environments like that, even Unity itself.
So how much higher the cost of calling externs was, what code caused it, was it already optimized as much as possible?
After all this time its very hard to believe anything vrc team says is true and not just random excuse, as you can make so many of them with 0 burden of needed to provide any evidence.

I don’t see how soba changes that? It was said it would be also a choice of the user and you still end up supporting 2 VMs running at the same time in every world?

At most as a fellow developer i can TRY to believe that Udon 2 development got out of hand, as one developer should never be responsible for a big feature like that.

I see the original argument of magical 1GB memory usage also disappeared, was it false after all, was it not analyzed enough, as I hoped to see actual data about that with explanation what exactly lead to such memory usage with no reasonable ways to fix it. And not just another “trust me bro” argument.

6 Likes

I love reading the details!

Feels more open to discussion, so I’d like to offer my perspective.

First, as a newly hatched programmer, it would be enriching to progress my skills alongside the development of Soba. I find in-depth details fascinating and it inspires me to want to experiment.

Next, I hope VRChat is around for a long time in good standing. The freedoms that the platforms brings people (especially highly marginalized people!) cannot be understated, so I hope it can continue being a positive part of peoples lives.

Lastly, I’ve always thought of VRChat as a great medium for testing the boundaries and possibilities of VR. Having systems that are maintainable and stable is vital to continued development of really cool stuff that push the limits.
Even though the VRChat SDK is quite limited, it still allows for plenty of creativity and easy access to feedback from users.

To recap, the VRChat SDK and community has made opportunities available for me to grow and I’m still on for the ride. This platform is still very much a sanctuary for many who need it dearly for various reasons. Having a stable environment to test VR capabilities streamlines development of cool VR stuff!

You guys might not always get to see it - or maybe you do - but some of us are at the edges of our seats for these features and are rooting for you all from the sidelines.

The show must go on! I hope in the future we can get more fun deep dives on VRChat SDK features.

And with that, I thank you.

Rusty

1 Like

This is a good writeup Strasz; I do also think you would have had issues with the app store at the end of the day on the old system too, but it’s nice to have a clear technical overview of the perf/dev problems.

This was a good idea for a project; it’s just unfortunate that the mad scramble to rebuild community sentiment after EAC left you with this project announced well before it was ready. It sucks when these things fall behind and the well-understood issues with the “overheated” VRChat that was caused by the mass-hirings during covid can’t have helped.

I’ll probably bug you lot about a writeup about Soba itself and how a second look at the Udon-style approach has worked out. Whilst I’m chirpy on getting The Stupid fixed from the Udon approach via a re-do, there’s still consequences for this approach; Soba isn’t a free lunch either.

Great to see a deep dive explanation and the comments being more civil as well, although some people already show that they will never be satisfied and won’t believe anything seemingly until probably they get access to the source code and remotely connect to the devs’ PCs for themselves, lol

i just expect same transparency as most good tech companies do in their post mortems, no one needs to share their code there. Just industry standard approach, nothing more.

Hey Moonorama,
I was also a bit confused on the sudden change to Soba and what it was supposed to be. I hope they consider finding a way to include some deep dives into SDK features in future dev updates. Between the Twitch streams and the dev updates videos/discussion posts, they are really innovating on interactions with the community.

You know what, even if I’m not happy and receptive to Udon 2 being replaced with Soba, I have to give credit where credit is due, you’re actually trying to be transparent with the community, even if it took us a while to get here.

I do have to suggest though, next time you plan to make such a major change for the community (whether the creators or general community), please put this type of transparency in the root post. I, alongside many others, weren’t just disappointed because of the change, but also from the lack of transparency.

In your initial developer update, you straight up didn’t give us any information whatsoever into why this was done, which immediately struck red flags for a lot of the community, then, quite frankly, took too long to give us initial responses to our questions, and then create this thread.

Overall, thank you for still giving us transparency even if it was later than it should have been, any progress is better than no progress. Even if I’m still skeptical about your promises with Soba, I do appreciate that you finally gave us unadulterated transparency on the situation.

I just hope that Soba delivers on what everything that you’re saying it could deliver on.

1 Like

That isn’t the community’s fault, though. The VRChat team has an extremely bad track record for delivering on their promises. Especially on-time, so people are going to be skeptical until they can see it for themselves.

Alongside that, your take on our expectations is a fallacy and misconstrues the actual expectations of the community. We want to see that VRChat can deliver on what we’re now being promised. We don’t want to “get access to the source code and remotely connect to the devs’ PCs for themselves”.

I assume your wording was intended for the sake of humour, but it doesn’t exactly read that way when the community’s concern is genuine.

2 Likes

Given how Udon 2 wouldn’t have needed to use externs for nearly as much Udon 1 does, the increase in the performance penalty increase must have been pretty substantial to outweigh that and a JIT.

What code was this impacting, yet still needed to be fast(er)?

I wonder if reimplementing some of the more standalone Unity functions in WASM (and then redirecting calls to the WASM version) would be able to mitigate this.
The vector and matrix functions come to mind, if those where left as externs (given they are from UnityEngine) then the cost of marshalling would be significant relative to the size of the function called.

What is the extern cost with Soba, and how does it compare to Udon 1?

In the more detailed Soba graph posted in the Dev update thread (Developer Update - 25 November 2024 - #42 by Merlin), it was shown that code was run on Mono JIT in editor, and on Soba in VRC.
Based on the above quote, is that incorrect or outdated? is the Editor expected to also use Soba (as is the case with Udon 1 and its VM)?

Also, would it have not been possible to run WASM in editor? or was there something preventing that approach?

It was stated before that one of the reason WASM was dropped was because of Apples restrictions against using a JIT. I note, however, that same reason is not restated here.

Was that restriction a reason for not looking into other alternatives using JIT (Mono/CoreCLR, or a different language ran on a JIT compiler)?

Would it be possible for Soba to get a JIT in future?
I understand writing one is a pretty complex task, made morose with the need to support two architectures.

I’ll admit, I wasn’t super sold on the WASM approach, but I’m also unconvinced of the reasons given to drop it for your own interpreter.

One of the points shown on Hai’s graph was the ability to bundle 3rd party .Net libs. Given that, based on the chart I linked earlier, Soba (indirectly?) runs CIL, would is be possible to do this with Soba?

1 Like

I feel like VRChat not going deep enough into tech details (postmortems, as suggested above) is hurting their credibility among tech-oriented crowd quite a bit here.

The OG promise of Udon 2 that could be read between the lines was using two industry-standard technologies (WASM and some sort of CIL AOT) that both can provide excellent performance and interoperability. With WASM one could use any programming language, with enough community-powered elbow grease, and having off-the-shelf CLR would mean VRChat could focus on truly important things (more VRC+ gated features!).

Further discussion did reveal, as I understood it, that WASM was used as a sandbox for Mono interpreter - worse for performance, and not really delivering on WASM universality angle. I can see how this specific approach would have some of the problems that were mentioned in this and previous posts - not unsolvable, but I’d argue about the general direction of using yet another interpreter anyway.

The ideal outcome for the tech-savvy here would be reinstatement of WASM-based world scripting, with C# being AOT-compiled into modules actually loaded and JITed in the client, without any interpreter proxies. Other than the inevitable WASM interpreter on iDevices, that is - common Apple L - but Soba has no hopes for JIT on iStuff either. Speaking of Apple, limiting everyone’s performance by that of the worst platform sounds odd. We’re not getting quest’s hard 20k poly limit and “no very poors” on PC, why apply it to scripting performance?

What we get instead is Udon 1.5 Soba, seemingly an expansion on the concept of the original Udon VM, which boils down to a basic bytecode interpreter, and VRC is now standing in front of the monumental task of reimplementing CLR. The entire Mono team tried that once. We all know how well that is going, and how long it took to get to its current capabilities.

Sure, the initial scope of Soba is way smaller. Sure, we’ll get some very basic CLR features like generics soon™. Sure, the outer format is a CIL Assembly, so you can swap Soba interpreter for something faster later on. But let me ask this: if I take an off-the-shelf C# library, how long would it take for Soba to be able to run it, on average? And if at some point it manages to run some horribly outdated net35 build of it, how fast would it run? If I transpile WASM bytecode into the subset of CIL supported by Soba, how big would a performance drop be compared to a proper solution with WASM JIT?

There is a huge chicken-and-egg problem with Udon and what people do with it. All we see is relatively simple, as Udon doesn’t provide the performance for complex stuff. The promised “up to 10x” speedup of Soba would barely get us into “current worlds don’t tank your framerate as hard” territory. Take a look at what creators can achieve with GPU shaders - that’s the benchmark for what should be possible and performant in “Udon Next”, not the current compute-restricted use cases. Oh, and the painful networking (what’s an RPC with arguments?) doesn’t help at all either.

Oh, and speaking of WASM - slim modules built from a native language or a restricted subset of C# on a JIT runtime with gas metering would open the doors for proper, safe and performant avatar scripting instead of having to build and run abysmal spaghetti mess animators that tank your performance even on distance-hidden avatars. You could’ve built the tech stack once and used it everywhere. Somehow I doubt we’ll see any kind of proper avatar scripting anytime soon, in part because of lackluster performance of existing and upcoming scripting solutions.

All in all, I wonder if VRChat ever considered a WASM-first scripting approach (no interpreters!), and if so, why was it not chosen (Apple is not a valid argument here). It looks like you end up having two scripting runtimes anyway. Why build more of the same, similarly mediocre thing with only some aspects improved, when you could build practically the best thing possible instead?

11 Likes

I don’t understand how this is different from running both Udon and Soba in the client. Or do you plan to run the old Udon code in Soba?

So, just checking in here to note that we likely won’t be responding to any of the technical questions posted above in this thread. This isn’t because we’re ignoring you, but rather because it’s more efficient to gather them up, and then when we’re ready to post an update on Soba, answer them all at once (see what we’re doing with Age Verification).

I realize this might mean you don’t get answers quickly, but most of the questions folks are asking aren’t really things I can quickly get an answer for, and typically require me to pull an engineer aside to ask them to clarify something/explain something in more detail. As you can probably imagine, my focus right now is on making sure the community is receiving detailed, but correct answers. That’s harder and more time consuming to do in cases like this, but I think it’s worth it.

As far as when that will be, I’m not sure! I wouldn’t necessarily expect it this year, though, as we’re pretty heads down on finishing a bunch of stuff up to end the year.

But don’t let that dissuade you from asking hard questions. I’ll do my best to get them answered.

8 Likes