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
Advanced Contact Parameters silently fail in emulators (E.G Gesture Manager) unless the avatar root Animator has a controller
Summary In SDK 3.10.6, Advanced Contact Parameters (e.g. Sender Local Position) don't update in Gesture Manager or Av3 Emulator play mode unless the avatar root's Animator has a Controller assigned. Nothing is logged when this fails. Build & Test in the client works correctly, so this only affects the editor workflow. Reproduction Avatar with a contact receiver using Advanced Parameters (e.g. Sender Local Position X/Y/Z), with those parameters in the FX controller. Leave the avatar root Animator's Controller field empty. Enter play mode in Gesture Manager. The parameters stay at 0. Assign a controller containing those parameter names to the Animator's Controller field. They now update. (A dummy controller with just the parameter names is enough.) Av3 Emulator doesn't update them in either case. What I found in the SDK source AvatarDynamicsSetup.cs creates an AnimParameterAccessAvatarSDK per enabled advanced parameter, bound to the avatar root Animator. Its constructor looks the name up in animator.parameters . With no controller, nothing is found and the accessor marks itself invalid. Every later write is then a silent no-op. Emulators that supply their own accessor for the base contact parameter have no documented way to do the same for the advanced ones, so those fall back to the SDK's root-Animator version. Requests Log a console warning when an advanced-parameter accessor is created invalid (Animator missing or no controller, or the parameter not found). Don't depend on the root Animator's controller for this. Resolve the parameters from the descriptor's FX controller instead, or create the accessors lazily. Document how emulator authors should supply accessors for the advanced parameters, since the feature shipped with both major emulators not yet handling it. SDK 3.10.6, Unity 2022.3.22f1, Gesture Manager 3.9.9. Related report on the Gesture Manager tracker: https://github.com/BlackStartx/VRC-Gesture-Manager/issues/105
1
·
Bug Report
·
tracked
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.)
1
·
Bug Report
·
tracked
[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
Android build and test not working
Followed the this https://creators.vrchat.com/platforms/android/build-test-mobile/ but it fails to lunch vrchat on my phone after building it even puts the file on my phone so i know for sure adb is working and getting this in my editors console and tried this with 2 different world projects now AdbException: ADB failed with exit code 1. StdOut:Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.vrchat.mobile.playstore/com.vrchat.app.MainActivity (has extras) } StdError:Error type 3 Error: Activity class {com.vrchat.mobile.playstore/com.vrchat.app.MainActivity} does not exist. VRC.SDK3.Editor.Builder.ADB.Command (System.String[] arguments) (at <8c33ac67c14b4f31a7515261397206c6>:0) VRC.SDK3.Editor.Builder.ADB.StartVRChatIntoWorld (System.String remoteBundleFilePath, System.String appPackageName) (at <8c33ac67c14b4f31a7515261397206c6>:0) VRC.SDK3.Editor.Builder.VRCWorldAssetExporter.RunWorldTestAndroid (System.String bundleFilePath) (at <64d127784e7f4289a5a7ffbe49df807e>:0) VRC.SDK3.Editor.Builder.VRCWorldAssetExporter.RunScene (System.String bundleFilePath) (at <64d127784e7f4289a5a7ffbe49df807e>:0) Rethrow as WorldAssetExportException: An ADB command failed to execute. Check the console for more details. VRC.SDK3.Editor.VRCSdkControlPanelWorldBuilder.Build (System.Boolean runAfterBuild) (at ./Packages/com.vrchat.worlds/Editor/VRCSDK/SDK3/VRCSdkControlPanelWorldBuilder.cs:2576) VRC.SDK3.Editor.VRCSdkControlPanelWorldBuilder.BuildAndTest () (at ./Packages/com.vrchat.worlds/Editor/VRCSDK/SDK3/VRCSdkControlPanelWorldBuilder.cs:3282) VRC.SDK3.Editor.VRCSdkControlPanelWorldBuilder.OnBuildAndTestAction () (at ./Packages/com.vrchat.worlds/Editor/VRCSDK/SDK3/VRCSdkControlPanelWorldBuilder.cs:2147) System.Runtime.CompilerServices.AsyncMethodBuilderCore+<>c.<ThrowAsync>b__7_0 (System.Object state) (at <27124aa0e30a41659b903b822b959bc7>:0) UnityEngine.UnitySynchronizationContext+WorkRequest.Invoke () (at <cb81df0c49c643b1a04d9fc6ccca2433>:0) UnityEngine.UnitySynchronizationContext.Exec () (at <cb81df0c49c643b1a04d9fc6ccca2433>:0) UnityEngine.UnitySynchronizationContext.ExecuteTasks () (at <cb81df0c49c643b1a04d9fc6ccca2433>:0)
4
·
Bug Report
·
tracked
Proposal for fixing Audio Filters (eg low-pass) support for AVPro
I believe it is time to get a solution to the most plaguing issue (in my opinion) of AVPro: Audio Filters I do not think this is a "can't fix" situation. In this proposal I will go over the problem, considerations that have been discussed historically, and the solution I believe is feasible to implement with working sample code. ### Previous Cannys 1) https://feedback.vrchat.com/open-beta/p/986-avpro-player-ignores-lowpass-reverb-and-other-filters 2) https://feedback.vrchat.com/sdk-bug-reports/p/avpro-video-player-audio-filter-issue 3) https://feedback.vrchat.com/sdk-bug-reports/p/sound-effects-are-not-applied-to-audiosource-using-avpro-that-comes-with-sdk3 4) https://feedback.vrchat.com/feature-requests/p/usharpvideo-stream-audio-does-not-support-filters ### Crux of the issue As previously discussed in above canny #1, the current way of handling the AVPro speaker component (type named AudioOutput ) is that the component is implicitly created via AddComponent on the same game object. This has the critical drawback of being unable to respect any audio filters due to the DSP filter chain being _component order dependent_. The second half of this issue is that Unity has no runtime native way to change the ordering of components without fully reconstructing the references. This causes very obvious issues in regards to dependent scene references. (TCL's comment in canny #1 clarifies this as well) ### What has been considered Detecting and destroying/rebuilding known filter components after the implicit component is added. This is bad because all scene references to those components would be lost (eg: UI Events or public Udon variables). To avoid the lost components issue, a full scene search would be required in order to update the references which is costly and fragile. Placeholder components (shims) for each filter type that gets implicitly created after the implicit AudioOutput This is bad because it does not allow users to reference the actual filter components in the inspector (namely an issue for UI Events) Allow adding the AudioOutput script manually in scene and have the speaker search for it before trying to implicitly add the component. This is bad because it requires that the user import the AVProTrial package to be able to use built-in unity audio filters. This needs to be compatible with situations where the user does not wish to import that package so the dependency is decoupled from the feature itself. ### Proposed Solution A shim script that inherits from the AudioOutput class combined with a compiler flag for detecting if AVPro is present, and if not, then have a stub type of the _same namespace and type name_ which is _ONLY_ present in the sdk. Then update the VRCAVProVideoSpeaker to check for the existence of the shim component before creating an implicit AudioOutput, using it instead if found on the game object. This ensures that when the main shim script is loaded in editor, it is already a valid AudioOutput component and the component order is correctly retained so the Audio Filters will work correctly. In the SDK, the script type will check for the existence of AVPro through a version define, and if NOT present, will enable the AudioOutput stub class of the same namespace. An example of what it might be like: https://gist.github.com/techanon/41efc336604e148dde55862bff1778d9 I've tested this specific example in editor and it works there. Can't test in-client obviously.
24
·
tracked
VRC Object Sync - MAJOR Performance Issues With a Real Solution
VRC Object Sync by default is a continuously operating script that pings locations to all players even when objects are at rest or behind the player/occluded by the world. As a result, once the object pool reaches higher numbers, over 200, frame times are permanently hindered as the game waits for all these pings. I'd tested in my world the difference between VRChat's default Object Sync script and MMMaellon's Smart Object Sync on about 212 objects. Performance with default object sync raised frame times to 16.7-17ms. MMMAellon's Smart Object Sync brought framerates down to 2.4-3ms, an overall savings of around 4-5x performance improvement. And this is not on a slow PC - this is on a Ryzen 7 7800x3D with a Noctua NH-12s cooler, an RTX 4070, and 64 GB of RAM. You cannot simply add power to fix the problem. MMMaellon's script does a lot to improve performance, but the core function allows objects at rest to stop pinging unless exerted by an external force. They are also developing a newer version of the script that cuts bandwidth in half. As VRC adds more dynamic global objects through the inventory system, I fear this issue will only become more exasperated the longer global sync gets ignored. I highly recommend enabling higher performance syncing methods by default for newer worlds and enabling the older sync system only when absolutely necessary. As many maps feature QV pens, pool tables, grabbable pillows, coffee and drink prefabs, and other grabbable synced objects, this will have an immediate performance impact across the entire game, and it's something all creators need to be made aware. https://github.com/MMMaellon/SmartObjectSync
4
·
Feature Request
·
tracked
Load More
→