World/Udon Bugs & Feature Requests

Post about current World or Udon bugs feature requests. One item per post!
Non-constructive and off-topic posts will be moved or deleted.
SendCustomNetworkEvent Stops Working
Under certain conditions that I can't reproduce reliably, all network events stop working for a player. It looks like it always happens when the owner/master changes. This causes big issues in high frequented instances where the master changes a lot. World where it happens to me: https://vrchat.com/home/world/wrld_3fb6208d-54d7-4a9f-9cf9-11341fa36037 All objects are active and never get deactivated. Serialization and Deserialization works fine for all players. The network is not clogged and is happy. The network events stop working completely for the client that experiences this behavior regardless of the target (All, Owner) and they don't send or receive any events anymore. The behavior never recovers. If another client tries to send a network event directly to that player (owner) the event gets blocked. I verified that the code works by executing the methods on the client with the bug by hand. (Thanks BobyStar) The code sends maybe 3 events in 20 seconds on multiple UdonSharpBehaviours. I attached some code examples that don't get executed from the network event, but if I execute them by hand it works. The error that's after the rpc call was captured on a non-owner client that tried to send a network event to the owner who was experiencing the behavior described above. This was after I pressed a button that executes the "StartLobby" method. In the code example with the Debug logs I see the first log "All players finished race!" but I don't see the "OnGame Done!" on any client.
4
·
Bug Reports
·
needs more information
Synced arrays have unexpectedly large overhead (in bytes)
Synced arrays have about 40 bytes of overhead which I cannot explain how those bytes could be used internally. For a long time I thought synced objects had 12 bytes of base overhead, 4 bytes of overhead per synced variable and then the actual variable data. That would explain the 20 bytes for a single synced int... though the single synced byte with 14 is new to me. Either way, in the case of a script with a single synced byte array, let's assume the 12 + 4 bytes of overhead are correct (base + per variable), so that's 16. Then let's assume it stores the length of the array in an int, even though that could be done in a space optimized way, but let's just go with 4. That's 20 bytes of total expected overhead for a script with a single synced byte array. However as we can see in the demo log output at the end, it's 64 byteCount when syncing an empty byte array. Ok but where is the issue? I've created a lockstep networking implementation on top of VRChat's networking. It requires "heartbeats" to be sent by a tick sync script, that's how clients know they're allowed to advance to the next tick(s). This script sends both the current tick as well as all associated input action ids. Must be in the same script to avoid race conditions. That's a variable amount of data, so it must use an array (I ended up just using a single byte array for all synced data). Even if no input actions are sent and it just syncs the current tick, that's 68 bytes per sync, which at a tickrate of 10 equates to 680 bytes per second, which is over 5% of the 11kb global manually synced limit. I wanted a tickrate of 20, but then we're at 10% while the system is effectively idle. Not to mention that to my knowledge avatar syncing also counts to this 11kb limit. Ultimately I feel bad for wasting both server and user bandwidth... but it is outside of my control. The actual payload is just 2 to 3 bytes per sync (because ticks (uint) are serialized in a space optimized way), so 97% to 95.5% is overhead. Reducing the overhead by 66% (getting rid of those 40 unknown bytes) would be huge. I think there's a high chance for this to be unintended behavior, so the bug report category fits best. Demo synced array script: https://gist.github.com/JanSharp/4e59bd352d97b4001a82b5b868f13fdf#file-syncedarraydemo-cs Demo scene and all scripts: https://gist.github.com/JanSharp/4e59bd352d97b4001a82b5b868f13fdf Demo world: https://vrchat.com/home/world/wrld_6bf7ead7-fc62-412d-bbac-f0ee310f0fad Potential demo log output: (<dlt> stands for debug log tracker, so not actually relevant) <dlt> single synced byte variable - result.success: True, result.byteCount: 14 <dlt> single synced int variable - result.success: True, result.byteCount: 20 <dlt> result.success: True, result.byteCount: 64, data.Length: 0 <dlt> result.success: True, result.byteCount: 68, data.Length: 1 <dlt> result.success: True, result.byteCount: 68, data.Length: 2 <dlt> result.success: True, result.byteCount: 68, data.Length: 3 <dlt> result.success: True, result.byteCount: 68, data.Length: 4 <dlt> result.success: True, result.byteCount: 72, data.Length: 5 <dlt> result.success: True, result.byteCount: 72, data.Length: 6 <dlt> result.success: True, result.byteCount: 72, data.Length: 7 <dlt> result.success: True, result.byteCount: 72, data.Length: 8 <dlt> result.success: True, result.byteCount: 76, data.Length: 9 <dlt> result.success: True, result.byteCount: 76, data.Length: 10
2
·
Bug Reports
Checking a system-defined enum with equality operators fails
Checking the equality/inequality of a system-defined enum with equality/inequality operators ( == / != ) will fail. As a result, this example codes in the document don't work as expected: https://creators.vrchat.com/platforms/android/android-best-practices/#2-detect-mobile-players-in-your-world-automatically public override void OnInputMethodChanged(VRCInputMethod inputMethod) { if (inputMethod == VRCInputMethod.Touch) { // Run code for touch input } else { // Run code for non-touch input } } (The UdonGraph version (attached image) also has an identical issue.) Workaround Cast to underlying values and compare them. if ((int)inputMethod == (int)VRCInputMethod.Touch) Analysis UdonSharp compiles the expression inputMethod == VRCInputMethod.Touch into EXTERN, "SystemObject.__Equals__SystemObject__SystemBoolean" Although Object.Equals(Object) is overridden by Enum.Equals(Object) , which the inputMethod may have, with comparing underlying value, this EXTERN seems to call the Object.Equals directly (maybe via reflection API), and it returns the unexpected result (by only comparing the referencing instances). The EXTERN, "SystemObject.__Equals__ comes from here https://github.com/vrchat-community/UdonSharp/blob/22307065bd408dfd163fe46b0b8b701a4efcbc00/Packages/com.vrchat.UdonSharp/Editor/Compiler/Binder/BoundNodes/BoundInvocationExpression.cs#L420 And replacing the System_Object of this line with System_Enum doesn't work because the Enum.Equals is not exposed. Suggestions Temporary, rewrite the example codes using cast operator Expose System.Enum.Equals And replace the EXTERN with System.Enum.Equals
4
·
Bug Reports
·
tracked
UdonSharpBehaviour throws ArgumentNullException during PrefabStage autosave when Unity pseudo-null object is serialized
Environment: Unity version: 2022.3.22f1 VRChat SDK Worlds: 3.10.3 VRChat SDK Base: 3.10.3 UdonSharp included with SDK Project uses Prefab Mode / PrefabStage with UdonSharpBehaviour components YamaPlayer package present: net.kwxxx.yama-stream 1.5.18 Observed: When opening or editing prefabs containing UdonSharpBehaviour components in Prefab Mode, Unity logs repeated ArgumentNullException errors from OdinSerializer UnitySerializationUtility. Error: ArgumentNullException: Value cannot be null. Parameter name: unityObject VRC.Udon.Serialization.OdinSerializer.UnitySerializationUtility.SerializeUnityObject(...) UdonSharp.UdonSharpBehaviour.UnityEngine.ISerializationCallbackReceiver.OnBeforeSerialize() and similarly: UnitySerializationUtility.DeserializeUnityObject(...) UdonSharp.UdonSharpBehaviour.UnityEngine.ISerializationCallbackReceiver.OnAfterDeserialize() Trigger: Open a prefab containing UdonSharpBehaviour in Prefab Mode Move a child object or let PrefabStage autosave run Errors repeat, sometimes dozens/hundreds per save Expected: PrefabStage autosave should not throw if a Unity pseudo-null UdonSharpBehaviour or serialized target is encountered. It should skip invalid objects or handle UnityEngine.Object pseudo-null safely. Additional finding: For diagnosis only, I temporarily tested a local guard around the SDK serialization path. The test indicated that the affected object was not a normal C# null reference, but behaved as null through Unity's overloaded UnityEngine.Object null comparison. With that guard in place, the exception stopped. I am not using this as a permanent workaround and do not intend to publish content with a modified SDK. This observation is included only to help identify the likely failure path. Additional observation: I have encountered this issue twice. In both cases, once the issue started occurring in the project, checking out older repository commits did not reliably make the issue disappear. This suggests that the trigger may involve Unity Library/cache/generated SDK state or some project-local serialized state, not only the currently checked out asset files.
1
·
Bug Reports
·
tracked
Load More