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
[3.10.6] "Use All Tracking Keys" toggle may be unclickable, and the left half of field values may not respond to input
What happens Two related problems occur under certain conditions: 1) The "Use All Tracking Keys" checkbox works only at certain Inspector widths. 2) The left half of each field value does not respond to clicks when the Inspector is wide. See the attached image 1. Conditions This happens when the inspector of components placed below the VRCAvatarDescriptor assigns to EditorGUIUtility.labelWidth . This typically happens when a component has some multi-value fields (Vector, Rect, Quaternion and others) or fields with a custom PropertyDrawer or DecoratorDrawer since Unity internal code for them assigns that, but custom inspector code can also do it. In some cases, the issue does not occur even when these conditions are met, so there may be additional factors, such as Unity Editor internal timing or internal Inspector ordering. I have not been able to find reliable reproduction steps. It seems most likely to happen right after adding such a component to the Avatar Root, but I don't know whether this always reproduces it. Known components that meet this condition and are likely to be added to the Avatar Root: All AAO: Avatar Optimizer components (<=1.9.21) (PropertyDrawer) VQT Avatar Converter Settings (as of 3.0.3) (PropertyDrawer) MA Mesh Settings (as of 1.18.7) (multi-value field) Components that also meet this condition but are unlikely to be added to the Avatar Root: Unity Collider components (multi-value field) Workarounds a) Collapse inspector for components below VRCAvatarDescriptor. See the attached image 2. b) Move the VRCAvatarDescriptor component to the bottom of the component list. c) Click the horizontal position where checkboxes on other components are drawn, rather than the position where this checkbox is drawn. See the attached image 3. d) Component inspector developers can prevent this problem by setting EditorGUIUtility.labelWidth = 0; after drawing their component (example: [5]). Note that this does not work in PropertyDrawer s, because Unity's internal code sets EditorGUIUtility.labelWidth after your PropertyDrawer runs [4]. Cause VRCSDK 3.10.6 added AvatarDescriptorEditor3.CreateInspectorGUI , which simply wraps OnInspectorGUI in an IMGUIContainer , and this causes the problem. When Unity creates its own IMGUIContainer for an inspector, it uses a closure that does many things before and after calling OnInspectorGUI [1]. The most important of these are EditorGUIUtility.ResetGUIState(); [2] and EditorGUIUtility.hierarchyMode = true; [3]. The missing ResetGUIState() call causes the unclickable checkbox and the unresponsive left half of field values. Additional Notes VRCSDK 3.10.6 has problem that label area is narrower than that of other components. The cause of this problem is the missing hierarchyMode = true . [1] https://github.com/Unity-Technologies/UnityCsReference/blob/2022.3.22f1/Editor/Mono/UIElements/Inspector/InspectorElement.cs#L623 [2] https://github.com/Unity-Technologies/UnityCsReference/blob/2022.3.22f1/Editor/Mono/UIElements/Inspector/InspectorElement.cs#L659 [3] https://github.com/Unity-Technologies/UnityCsReference/blob/2022.3.22f1/Editor/Mono/UIElements/Inspector/InspectorElement.cs#L667 [4] https://github.com/Unity-Technologies/UnityCsReference/blob/2022.3.22f1/Editor/Mono/ScriptAttributeGUI/PropertyHandler.cs#L191 [5] https://github.com/anatawa12/AvatarOptimizer/pull/1816
1
·
Bug Report
·
tracked
[Bug] VRC Avatar Desc.'s Colliders do not copy and paste transform references correctly.
When copying and pasting a whole VRC Avatar Descriptor component to a different avatar, the colliders transform references (hands, fingers, torso, feet, head) do not update to reference the new avatar's transforms for Custom-set colliders. I had an issue where I wanted to quickly transfer all the NativeFT work I did to another one of my avatars in a different outfit. So I copied and pasted the updated VRC Avi Desc. from the finished avatar to another avatar. Uploaded that new avatar, and found out I couldn't interact with any PhysBones. Found out it was because the colliders failed to copy over the correct transform references as expected when I copied and pasted the descriptor. If a collider is set to Custom, the internal transform reference to where that collider is supposed to be, maintains the previous avatar transform's reference instead of the new avatar's respective transform. If the collider is set to Automatic, the copy and pasting works just fine. This happens to both VRC Avi Desc components being copied and pasted as a new component, or pasting values into a pre-existing component. Steps to recreate: Create an avatar that uses at least one VRC Avatar Descriptor collider set to Custom. Copy the VRC Avatar Descriptor component off that avatar. Paste that VRC Avatar Descriptor component to a new avatar. Move the new avatar to observe that the Custom collider does not follow the new avatar, only the old copied-from, avatar. See included video where, in a fresh project with no extra plug-ins (other than VRC Light Volume's), I copy and paste a VRC Avatar Descriptor component onto a fresh new avatar. But, when I select and move that new avatar, the colliders set to Custom (head, hands, feet, fingers) are stuck to the old avatar. The Torso collider was set to Automatic, and correctly follows my avatar after being copied over. It might just require updating each ColliderConfig 's transform by calling Animator.GetBoneTransform(<insert correct humanoid bone>) , on the descriptor's OnValidate() or Reset() or whatever better method there is to detect copying and pasting. (Though this might break collider stealing features of Modular Avatar or Dark's Avatar Optimizer... maybe not, idk)
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
Load More
→