SDK Bug & Feature Requests

Please check out the following rules and use the provided template when posting a bug report! Off-topic posts will be deleted.http://bit.ly/vrchat-bug-reports
Additional parameter interpolation uses
Parameter interpolation allows us to avoid blendtree smoothing setups for parameters that share the same local/remote smoothing rates, but not for more advanced uses, so I'd like to request a few things: The option to set local/remote interpolation times independently The option to control interpolation times dynamically at runtime, through another parameter's value The option to define interpolated parameters for contact parameters (without adding them to expression parameters) The option to skip interpolation when a parameter is driven by parameter drivers (new toggle, default to true) Alternatively to adding the above to the interface which can add complexity, give us a parameter "namespace" that gives us access to interpolated values without having to manually configure them in expression parameters, for example Lerp/<duration>/<originalParameter> : Float parameter Val is changed from 0.5 to 1.0 (immediately) Float parameter Lerp/1.5/Val interpolates that change over 1.5 seconds Allow Lerp/1.5/Val to be driven by parameter drivers - if it does not match Val then interpolate from the new value to Val over 1.5 seconds. Driving the interpolation parameter and the <originalParameter> to the same value at the same time would skip the interpolation. Multiple interpolated parameters could be defined for one parameter, like Lerp/0.5/Val to interpolate the same parameter over 0.5 seconds, giving us the option to use one locally and one remotely, and for various other uses. To support point #2, special non-duration definitions could be added too: Lerp/<originalParameter> used locally/remotely with different rates, dictated by: Lerp/LocalRate/<originalParameter> to set the local interpolation rate for the parameter Lerp/RemoteRate/<originalParameter> to set the remote interpolation rate for the parameter Optionally support Lerp/LocalRate and Lerp/RemoteRate without a parameter, to act as a "default" interpolation rate when an explicit override for a parameter isn't set. When rates aren't set, default to the current interpolation rate (I believe that's 0.1 seconds if I'm not mistaken?) Interpolation rate of 0 should be acting as a mirror of the original parameter (no frame buffer), if someone desires a frame buffer they can use 0.0001 or some other impossibly low value that is greater than 0 . Originally posted on the forums here , corrected for local parameters being supported and adjusted Inter namespace to Lerp , in case you'd like to support additional interpolation modes with different "namespaces", though Inter works if you'd add Inter/<originalParameter>/Mode int or suffix the <duration> with the mode like Inter/0.5E/Val for exponential.
0
·
Feature Request
Add a "clock" parameter (flip/flop bool) for parameter sync interval
Context: Parameter multiplexing systems have become widely used to support an ever-increasing number of features on avatars, and to make room for more than a handful of options once the VRCFT template was added. These systems have depended on the fairly consistent update rate of 10 times a second (0.1s interval) and so have been built with that documented behavior. Recent changes to how parameters are synced have made these systems less consistent, it was stated that these systems were never supported (despite the docs and consistent in-game behavior for years) but efforts are being made to not break these systems. I suggested versioning the Expression Parameters (just like physbones/raycast) so that new features (like bit width, signed/unsigned, etc) would only apply on new uploads, and that expression parameters "1.0" would sync as they have before, in my opinion that's still the best approach (guarantees that existing uploads would remain functional), that was unfortunately shut down "There will not be a compatibility shim, as we are making these changes to guarantee server stability and cost." -@pi . Regardless of expression parameter versioning or not, the multiplexing systems are unlikely to be going anywhere since many modern avatars often use 400-600 bits for their base features (VRCFT aside), and so we'd be encountering the same inconsistent interval issues (be it on all uploads, or only on "1.1" uploads if versioning is accepted as a solution) since the local avatar cannot tell when parameters are sent to remote, as our 0.1s interval no longer holds true, and for the lack of a better timing mechanism. So a parameter update clock is needed, for example ParameterUpdate as a bool, that simply flip/flops it's state once current parameter values are sent to remote users, the interval should be dictated by the "fastest" update a remote user sees (if one user is very close and should see the update in 0.1 seconds and another is very far and only receives an update in 1 sec intervals, it should be based on the closer user's 0.1 interval) as that's been what we've been operating on, though I would not oppose additional options like ParameterUpdateLast for the latest update and ParameterUpdateMedian for when most people would see the updated values. This clock could also be used to drive a local cue for a user for certain features, specially ones that require syncing with remote users, like world drops, by displaying an effect locally when the world drop should be active for nearby/most/all remote users, meaning that moving would not cause it to be misaligned.
0
·
Feature Request
Advanced parameter driver operations/formula support
It would be nice to have "advanced" Parameter Driver operators to: Set/unset bits (if it’s one entry, it should display up to 32 bits as this may be used locally as well, and for synced parameters highlight the “synced” bits in some way like an alternate background) AND/OR bits between two parameters Add/subtract/multiply/divide one parameter with another Copy parameters from X bits to Y bits, this could be used, for example, to “pack” multiple parameters in multiplexing systems, or in save systems (saving multiple synced parameters into a single one since the local one is 32 bits, and loading from one into multiple). Right now without horribly inefficient animator logic it’s practically impossible to set every bit in an int by a bool or set multiple bools via int bits (it’s possible, but it spans multiple frames due to multiple transition evaluations, or requires defining hundreds of transitions, one for each possibility, instead of nesting them), requiring us to create multiplexing int(s) alongside multiplexing bool(s), with these options we could slow down updates to as little as 1 bit per parameter update regardless of type, or reduce wasteful allocations and instead allocate just the the largest bit width used, and fill it with smaller types when the “large” types aren’t currently being synced. An alternative to defining specific additional operations, though I suspect far less likely (especially since you don’t want to encourage further uses of animators for logic, but I’d hope that any alternative we get would support this in the future so this work could be translated whenever the animator exodus happens), maybe an expression/formula operator, where a parameter list is converted to variables (since parameter names aren’t always valid variable names conversion in some form would be necessary, I’m imagining A through Z), and an expression could be performed using them, for example: C = A + B; D = (B & (1 << 3)) != 0; E *= 3; This would give us access to a lot of mathematical operations that are either impossible, impractical, or require complex (blendtree) setups, and could carry forward to action drivers and other animator alternatives in the future. Originally posted on the forums here
0
·
Feature Request
DPID mipmaps still break normal maps in SDK 3.10.6
Thanks for the 3.10.6 fix for swizzled normal maps ( https://feedback.vrchat.com/sdk-bug-reports/p/dpid-mip-mapping-breaks-normal-maps-if-swizzled ). On PC that case looks good in my tests now. However, normal maps without swizzle or Flip Green still seem to get broken or degraded mips, because DPID regenerates them from the raw PNG and discards the encoding that Unity's importer has already applied. A note on how this was put together: I read the SDK source in the 3.10.5 and 3.10.6 packages and ran a small test project, with help from AI assistants (Claude Opus, Claude Fable and GPT Astra) over several rounds of cross-review. I have tried to check every claim against code or measurements, but some details may still be off. Please treat this as a starting point rather than a definitive analysis. What I am seeing PNG alpha leaks into X (PC, new in 3.10.6). For PNG normal maps whose alpha channel is not fully opaque, the decoded X at every mip (mip 0 included) comes out as (X + 1) × alpha − 1 instead of X (alpha in [0, 1]), so normals lean toward −X. With alpha 128, X drops by about 0.5 at X = 0 and by about 1.0 at X = +1. With alpha 0 the result is X = −1 everywhere. This affects formats that keep alpha (RGBA32, DXT5 and BC7 in my tests); BC5 did not show it. 3.10.5 overwrote alpha with 1, which hid this. In my project, 54 of 1,424 DPID-target PNG normal maps (mostly from purchased outfits) have non-opaque alpha, and 29 of those contain fully transparent pixels. DXT5 quality loss (PC, 3.10.5 and 3.10.6). With the default Normal Quality compression, the mips (mip 0 included) show noticeably higher compression error than without DPID, at least on the detailed test texture below. Z forced to 1 (Android, 3.10.5 and 3.10.6). Every mip that DPID writes stores Z = 1, so normals are flattened on Quest. For unswizzled textures this includes mip 0. For swizzled / Flip Green textures mip 0 is kept but mips 1 and smaller are still affected, so the 3.10.6 fix does not fully cover Android. Environment VRChat SDK 3.10.6 (3.10.5 compared), Unity 2022.3.22f1, D3D11 editor DPID mipmaps on, conservative mode on Texture Type: Normal map, Mipmap Filtering: Kaiser, PNG source PC: Windows target, DXT5nm normal map encoding (the default). Android: XYZ encoding (the default) What I think is happening Notation: below, x, y, z and alpha are the stored [0, 1] channel values; X, Y, Z are the decoded [-1, 1] components. When OnPostprocessTexture runs, Unity has already re-encoded the normal map. Dumping the uncompressed import result shows: PC (DXT5nm target): each pixel is (1, y, y, x). Unity itself discards the PNG alpha at this point. Android (XYZ target): each pixel is (x, y, z, 1). The layout depends on the target format: judging from the BC5 measurements, a BC5 target appears to keep x in R. For textures with no swizzle, Flip Green or similar settings, PerceptualPostProcessor takes the fromFile path: it reloads the raw PNG as (x, y, z, alpha) via ImageConversion.LoadImage and regenerates every mip including mip 0 ( inPlace: false , so startMip is 0). The output keeps the raw layout instead of Unity's encoding. (LoadImage only handles PNG and JPG, so TGA / PSD sources fall back to the in-place path.) PC shaders decode X from R × A ( UnpackNormalmapRGorAG ; lilToon does the same). Since 3.10.6 keeps A, the PNG's alpha multiplies the stored x. 3.10.5 forced A to 1 ( pixel.ba = 1.0f ), which hid the leak on this path while destroying X on the in-place path. DXT5nm keeps X in the BC3 alpha block and only Y in the color block. In the raw layout X and Y share the color block, which loses precision. On Android, pixel.b = 1.0f in the compute shader overwrites Z on both paths, and shaders compiled with UNITY_NO_DXT5nm read xyz directly. Swizzled textures already take the in-place path, which is why 3.10.6 fixed that case on PC. Steps to reproduce (issue 1) Enable DPID mipmaps in the VRChat SDK settings. Import an RGBA PNG normal map whose alpha is below 255 (for example 128 everywhere). Texture Type: Normal map, Mipmap Filtering: Kaiser, Compression: None, Read/Write Enabled, no swizzle or Flip Green, Max Size not smaller than the image, Windows target. Read the mips with GetPixels(mip) and decode X as 2 × R × A − 1, or view it on a material: X is shifted toward −1. Set Mipmap Filtering to Box (DPID is skipped) or turn DPID off: X is correct again. For issue 2, compare a detailed opaque PNG normal map (for example the synthetic one below) at default compression with DPID on and off. For issue 3, switch to Android and check the blue channel of the mips. Measurements Test texture: 64 × 64 synthetic normal map with X = 0.7 sin(2πi/16), Y = 0.5 sin(2πj/32 + 1), Z = sqrt(1 − X² − Y²), encoded to PNG. The "alpha 128" variant has alpha 128 everywhere. Values are the mean absolute error of the decoded component against a box-averaged source (not renormalized), in [-1, 1] units (lower is better). "Mips 1-3" is the worst of mips 1 to 3. "No DPID" is Unity's own Kaiser mips, which are sharpened and so also differ from a box average. The 3.10.5 / 3.10.6 / Fix columns were produced with copies of the respective SDK code in a small test project, so please treat them as indicative rather than exact. Case 3.10.5 3.10.6 Fix No DPID PC, Flip Green, DXT5, mips 1-3, X 1.000 0.060 0.055 0.097 PC, default, DXT5, mip 0, Y 0.064 0.064 0.007 0.007 PC, default, DXT5, mips 1-3, Y 0.250 0.250 0.055 0.055 PC, alpha 128, uncompressed, mip 0, X 0.002 0.498 0.002 0.002 PC, alpha 128, DXT5, mip 0, X 0.033 0.497 0.009 0.009 PC, alpha 128, BC5, mip 0, X 0.009 0.009 0.009 0.009 Android, default, uncompressed, mip 0, Z 0.216 0.216 0.002 0.002 Android, default, uncompressed, mips 1-3, Z 0.216 0.216 0.020 0.012 Android, Flip Green, uncompressed, mips 1-3, Z 0.216 0.216 0.020 0.012 Android, default, ASTC 6x6, mip 0, Z 0.216 0.216 0.036 0.036 Android, default, ASTC 6x6, mips 1-3, Z 0.216 0.216 0.072 0.074 BC5 did not show the alpha shift in this test (uniform alpha); I have not tested spatially varying alpha. Proposed fix (for discussion) Mip normal maps in place, so DPID works on the texture Unity has already encoded, and stop overwriting channels. This is what I am running locally and it seems to behave, but I have only tested the cases listed here. Editor/VRCSDK/PerceptualPostProcessor.cs , after the existing fromFile checks: ```csharp if (normalMap) fromFile = false; `Editor/VRCSDK/Dependencies/VRChat/Resources/PerceptualMipmapping/PerceptualPostProcessor.compute`, in `Downsampling()`, remove the overwrite: ```hlsl float4 pixel = _Input[int2(x, y)]; // removed: if (normalMap) pixel.b = 1.0f; With both changes, the cases I tested came out comparable to Unity's own Kaiser mips: uncompressed, DXT5, BC7 and BC5 on PC, and uncompressed and ASTC on Android, each with default, Flip Green, OneMinusG swizzle and alpha-PNG sources. "Comparable" rather than "identical": in a few cases the fixed DPID mips were slightly further from the box average than Unity's (for example Android uncompressed mips 1-3 Z, 0.020 vs 0.012), which I read as DPID's sharpening rather than an encoding error. With ETC (not my project's default) the fix's Y / Z error at mips 1-3 was somewhat higher than Unity's while X was lower, so I would not call that case a clear win either way. Things to be aware of: For normal maps larger than Max Size, mip 0 becomes Unity's downscale instead of DPID's, and the smaller mips are generated from that. In the DXT5nm layout B duplicates G, so Y counts twice in the DPID distance. I could not measure a difference on the test texture, but I have not looked further. After applying the code change, existing normal maps keep their current mips until they are reimported. (The SDK's DPID toggle already reimports Kaiser textures, but a code change alone does not.)
0
·
Bug Report
[SDK][862] "Offline Test" option is broken with multiple clients
Please fix multi-client "Offline Testing" or provide a better way to test networking without a full world upload. The SDK provides two buttons for testing. One is for local testing and the other is for full uploads. Local testing, or "Offline Testing", still requires a network connection and also provides an option for the number of clients. While some things appear to work with only one client, when using more than one client, local testing breaks and behavior is unreliable. Since this is built right into the SDK, people believe that it is correct functionality and think that their world is broken, wasting many hours of debugging and more bad testing. Known issues: -Network IK only sends for master -OnPlayerJoined/OnPlayerLeft triggers do not fire -Sitting in stations force all clients to the same position -Object ownership does not act properly between clients -Sometimes only the master can execute ANY triggers -Some clients do not make it to the same instance -Some clients are kicked to home Previous canny relating to multi-client local testing was closed with the response that using the same account for the same instance is not supported. Users are required to log into different accounts. This is not a solution. The general user does not know they are required to have multiple accounts to test their own worlds properly. Multiple accounts can only enter the same world if the world has been fully uploaded. Some users also have a very slow or limited connection and uploading a full world is impractical. https://vrchat.canny.io/bug-reports/p/multi-client-bugs
9
·
tracked
Load More
→