Developer Update - 27 February 2025

Welcome to the Developer Update for February 27.

Today’s featured world is A Simple Fishing World by Puppet~.

Announcements

SPAAAAAAAAAAAAAAAAAACE (jam) (2)

Space Jam 2 is live! This World Jam, hosted by the National Space Society of Australia, is an opportunity for world creators to make a VRChat world fitting the chosen theme.

All entries will be featured in a world row, and there are monetary prizes for the winners! Check out our blog post to learn more.

Note for World Creators About Input Fields

There is currently a bug that allows input fields (of all types, Unity UI, TextMeshPro, and VRCUrl fields) to pop open VRChat’s keyboard even if they are disabled. That is, even if you set the InputField component to enabled = false, the keyboard will still pop up. The same is true for the Interactable property, which even causes fields to become grayed out visually – yet they remain interactable.

In a future update, we want to fix this. Both for semantic clarity, and since it allows creators more options in marking input fields as disabled. We do recognize that this is a breaking change, even if minor, and as such want to give you a heads-up.

This announcement is both to inform you of this change then, and to give a chance for feedback - is this something a commonly used prefab relies on, or are you aware of any existing functionality that would be broken by this? Let us know!

The Stream is Back!

We took a little break last week – but we’re back!

As usual, you can find us on Twitch at 2PM PST every Friday. We might have an extra surprise for you… no promises, though!

We Released 2025.1.2!

Main Menu Updates! Age Verification Changes!

…and more!

Read all about it here.

Development Updates

Avatar Gallery Update

We’ve updated the avatar pages on the VRChat website! They are less cramped and include more creator information. They also include some extra room for… upcoming features.

You can now edit many details of your avatar on the web, including the name, description, thumbnail, and new fields for styles, tags, and acknowledgements, as well as an avatar gallery.

Right now support for these new bits is limited across the platform, but we’ll have more to share about how these will work soon!

An Update on Soba

Soba’s development is still underway! We haven’t talked about it in a hot second, so we thought it would be prudent to share some of Soba’s features that we’ve been working on for Soba’s initial release.

As a note, we’re trying to be extra careful with what we share about Soba. Likewise, it should be noted this isn’t everything you can expect as part of Soba’s intial release, but it is the stuff we’re currently testing and iterating on at the present moment.

This might lead to questions like, “Where is X?” or “When will you discuss X?” and the answer to those sorts of questions is likely to be the same: we’ll talk about it when we’re ready!

First, let’s recap what we’ve already confirmed will be part of Soba’s launch:

  • Non-UdonBehavior classes (aka custom classes).
    • These classes can be abstract or static and can implement interfaces.
  • Custom interfaces.
  • Static fields.
  • All the existing features from Official UdonSharp.

With that said, we think we can add a few new ones to that list:

  • All custom classes can have:
    • Custom constructors, including static constructors, which will be evaluated when the world loads.
    • abstract, virtual, and of course override methods and properties for full custom inheritance trees.
    • Field Initializers which will be evaluated at runtime, just like in normal C#.
      • As an aside, compile time field initializers were a non-standard feature in UdonSharp. If you relied on this before, let us know and we will try our best to support your use-cases in more standard-conforming ways going forward.
  • Interfaces can have default implementations, and can inherit from existing and custom interfaces as needed. Implementing functions can be explicit or implicit.
  • Methods support optional and named parameters, including params.
  • Recursive methods no longer require a special [RecursiveMethod] attribute and no longer come with a performance penalty.

Once again, this isn’t an exhaustive list, however it does represent functionality we’ve tested using our own tools as well as community prefabs.

While we encourage you to ask questions, it’s unlikely that they will be replied to directly here, as often Soba-related stuff can get technical, and requires discussion with the rest of the team to comment on (which can take time).

Conclusion

ok bye, see you on March 13!!!

15 Likes

Sooooooo, what about custom structs :3

6 Likes

Nice :3

2 Likes

I really hope they add stats like they have for worlds. I want to see if my avatars have any favorites :)

6 Likes

I was supposed to put this in the list above, but yes, you can define custom structs!

4 Likes

Generics eg. Lists<> Dictionary<> Are still not planned at release I assume tho :thinking:

3 Likes

Custom constructors, including static constructors, which will be evaluated when the world loads.

I hope this is an omission, but static constructors in C# are required by the spec to not run the first time scripts are loaded, instead they are executed lazily when their types are first referenced. You need to be following the C# spec to a T or you will be breaking content when you inevitably want to fix things later.

The static constructor for a closed class executes at most once in a given application domain. The execution of a static constructor is triggered by the first of the following events to occur within an application domain:
• An instance of the class is created.
• Any of the static members of the class are referenced

9 Likes

(VRC Graph user) will be easier with Soba to send other data over P2P?
like when my friend makes their footstep system, would they be able to include extra data like step position, which sound it was, and who sent it?
because that would be GREAT!

also, unrelated, could Udon Graph get the better Array UI that Udon Sharp scripts have? I can’t drag and drop a bunch of things into a list, I have to do it one at a time, and it’s awful.

Isn’t this what people use to easily share their social links?

1 Like

“compile time field initializers were a non-standard feature in UdonSharp”

I’m not sure what you are talking about here.
The following compile-time field initializer is standard C#.

public class Example : UdonSharpBehaviour
{
public const int X = 10;
}

Can you elaborate on why you are saying that compile time field initializers were a non-standard feature?

I’d like some examples of non-standard compile time field initializers, otherwise I have no idea if I am using any in my code to let you know so you can help support our use cases.

1 Like

I’d need an example of this - I know input fields are often used for copying out links, but disabled fields specifically? (note that this would not affect readOnly, just enabled and interactable)

1 Like

While you’re at working on a new system for world programming,

  • how about we add some generics/globals for avatars and worlds to discretely interact more?

ie: layer collide parameters, physbone & contact sender/receivers, maybe a world able to push some pre-defined osc variables

(know people that wanted to be able to make something like a pokemon system where you could do stuff in a world and then it fed stats and data to the avatar which you could take and use elsewhere as a pokemon trainer for example)

Having avatars dedicated to worlds that are designed to interact with the world in certain ways is a topic i’ve seen come up more often over time.


The real big one for me:

  • will we ever see a modular functionality for Soba so we can have Soba-powered spawnable props/items independent of worlds??

This would be transformative, because imagine not having to waste world perf by having pool tables and all these other sorts of minigames and arcade machines etc baked into the world, but instead spawnable items (maybe even have the world have snap points for said item spawns). Imagine being able to drop a projector videoplayer in some really beautiful landscape world that didn’t have one and just chill and watch a movie there!

Implementation could look like: using a modified clone of avatar api, world spawning like the new stickers/sharing stuff, and supporting soba for programming functionality.
*for moderation and performance : have only 1 instance of a unique prop id per world instance (perhaps per user), and gave a group permission for allowed to use or not in group instances, as well as obviously a global disable.

I want to make vehicles really really badly, but do not want them confined to one measly world.

There is a HUGE marketplace opportunity for this too!!! :moneybag: (we know you needwant money)
This is the type of thing that certainly has vastly more monumental interest by both creators and players than it appears on the surface.


…Even a “maybe” for either of these things would give a lot of hope.


. . .
as a ps: i noticed a change in the last update that prevented the ability for worlds to grab portals… this was not a much used feature but it had great potential for making dedicated portal zones or portal gates, or the world giving a clear indication that portals are not wanted in this area… I’d wanted to use this logic to have gates that sucked up your portals and held them in a nearby frame instead of letting them be in the middle of hallways or whatever.
I don’t think this was a good change, cuz this type of function could be immensely useful, especially if it’s an easy to use built-in prefab.

Finally! That’s great!

They’re talking about regular fields. U# currently runs field initializers for UdonSharpBehaviours at compile time because Udon doesn’t have a reasonable mechanism for running them on initialization. For example if you have some code like this

class MyBehaviour : UdonSharpBehaviour
{
    VRCPlayerApi _localPlayer = Networking.LocalPlayer; // Actually run at compile-time in U#

    private Start()
    {
        Debug.Log(_localPlayer != null ? "valid" : "null");
    }
}

U# would run the field initializer for _localPlayer in-editor during compile which would print null in-game and in play mode since in the editor the LocalPlayer returns null.

Soba would instead run the field initializer when the behaviour is initialized as you would in normal C#. So you’d have it print valid in-game and in play mode instead.

6 Likes

Thanks for the heads up! This is correct, and we will make sure static constructor semantics work properly. As a side-note, Soba will have a proper versioning system - but we’ll have more on that later.

Field initializers that are not constant will not run at compile-time, but at a specific place during runtime. As an example, a class-field like string data = "test".ToUpper(); would behave differently: In U#, this would run "test".ToUpper() at compile time, and directly store “TEST” in the constructed program. In Soba, this will keep the full expression of "test".ToUpper() in the assembled program, and run the case-conversion in the loaded world in VRChat.

3 Likes

Only hope I have is for us to be able to get a method to import old avatars into Unity.

I’m just excited to see what future features Soba will provide that warrant the product name change, rather than just updating Udon. Must be some big features.

“upcoming features”, ooh. Hope it’s nothing locked behind VRC+ though, gonna be worried about this every time there’s something new now. orz

1 Like

Regarding InputFields prompting a keyboard even when disabled, I rely on this for an “Attendance” tracking system we use, which tracks how long people have been in the world, giving a list of Username and Time in World. By having the keyboard pop up, I’m able to click it, and hit Copy, but people can’t Alter that text while in-game so I know the data is complete and valid. It’s a Very handy way of getting data out of the game and into an external tracker of some kind