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.
Udon Graph has unexpected behavior when a Branch is used in the Body of a For loop
SDK ver: 3.10.2 There seems to be certain conditions where the False output of a Branch does not update the value for the index of the loop properly, causing the loop to pass the incorrect value into "Get" nodes for arrays. This issue occurs in both ClientSim and in-game. I don't know if I fully narrowed it down, but I was assisting someone with Udon, and in the process encountered what appears to be a bug in the compiler. In my provided example, this graph should loop through an array of MeshRenderers, and then change the material depending on the value of the isToggled bool. see video in action: https://www.youtube.com/watch?v=VanIgAJRwoI The "True" side executes as expected, but when the Branch evaluates to "False", the loop executes the expected number of times, but it reuses the last value of the index instead of updating the index along with the loop. This makes is to the 4 cubes in the array change to red when isToggled is True, but when isToggled is false it sets the last cube in the array to blue 4 times in a row. Possibly the issue could be with the "MeshRenderer[] Get" node, as if its input "int" is not getting updated properly during the loop. As can also be seen in the video, for some odd reason, adding a "Debug Log" node with a "String Format" node that accesses the index prevents the unexpected execution from occurring. Curiously, it's specifically the "String Format" node that prevents the issue, as disconnecting it (but keeping the Debug Log) still has the issue occur.
0
·
Bug Reports
Using [UdonBehaviourSyncMode(BehaviourSyncMode.NoVariableSync)] just continues using last set value on an object with no other scripts
When adding [UdonBehaviourSyncMode(BehaviourSyncMode.NoVariableSync)] to an udon# class, It will just continue using the last setting. For example if you add [UdonBehaviourSyncMode(BehaviourSyncMode.Continuous)] and then compile, then change it to [UdonBehaviourSyncMode(BehaviourSyncMode.NoVariableSync)] and compile again, you get the expected behavior, and calling SendCustomNetworkEvent() works. If you then change it to [UdonBehaviourSyncMode(BehaviourSyncMode.None)] and compile, then change it to [UdonBehaviourSyncMode(BehaviourSyncMode.NoVariableSync)] and compile again It will continue to behave exactly as if it's still set to None. SendCustomNetworkEvent() does not work. This is on an object that doesn't have any other scripts on it. I haven't tested the case with other scripts. You can look at the debug inspector to confirm that this is what is happening. From the documentation: "NoVariableSync: Enforces that there are no synced variables on the behaviour, hides the sync mode selection dropdown, and allows you to use the behaviours on GameObjects that use either Manual or Continuous sync." It seems like the case where a script using NoVariableSync being used on an object that doesn't have another script on it may have been overlooked. Since I'm updating a script in a prefab I'm releasing from None to NoVariableSync because I want to use network events now, it's not going to work for anyone updating to the new version. I am forced to set it to Continuous. Does anyone know if it makes any difference to bandwidth usage?
1
·
Bug Reports
·
tracked
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
Load More