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
"Assets/Create/U# Script" still fails if destination file is outside project root
https://feedback.vrchat.com/sdk-bug-reports/p/assets-create-u-script-fails-if-destination-file-is-outside-project-root was marked as fixed in sdk 3.10.5, but the fix was not comprehensive. Packages added from disk during development (click "Add package from disk" in unity's Package Manager tab) are not inside the project root, and now result in "UdonSharp scripts must be created inside the project's Assets or Packages folder" which is not correct. If validation is still needed, you can check if an absolute path is inside one of these "outside of root" package folders by using !Path.IsPathRooted(FileUtil.GetLogicalPath(scriptFilePath)) , and then using FileUtil.GetLogicalPath(scriptFilePath) as the projectRelativeScriptPath The Unity's CreateAsset() cannot create assets in Packages comment in the current code is also incorrect. Unity can definitely create assets within Packages, the current implementation just doesn't deduce the relative path properly. The entire method can be replaced by this implementation, which solves all of those issues: internal static string CreateUSharpScript(string folderPath, bool createProgramAsset) { string chosenFilePath = EditorUtility.SaveFilePanel("Save UdonSharp File", folderPath, string.Empty, "cs"); if (chosenFilePath.Length > 0) { string chosenDirectory = Path.GetDirectoryName(chosenFilePath)!; string sanitizedFileName = UdonSharpSettings.SanitizeName(Path.GetFileNameWithoutExtension(chosenFilePath)); string scriptFilePath = Path.Combine(chosenDirectory, $"{sanitizedFileName}.cs").Replace('\\', '/'); string assetFilePath = Path.Combine(chosenDirectory, $"{sanitizedFileName}.asset").Replace('\\', '/'); string projectRelativeScriptPath = Path.IsPathRooted(FileUtil.GetLogicalPath(scriptFilePath)) ? FileUtil.GetProjectRelativePath(scriptFilePath) : FileUtil.GetLogicalPath(scriptFilePath); string projectRelativeAssetPath = Path.IsPathRooted(FileUtil.GetLogicalPath(assetFilePath)) ? FileUtil.GetProjectRelativePath(assetFilePath) : FileUtil.GetLogicalPath(assetFilePath); if (projectRelativeScriptPath.Length == 0) { EditorUtility.DisplayDialog("Invalid path", "UdonSharp scripts must be created inside the project's Assets or Packages folders.", "Ok"); return null; } if (createProgramAsset) { if (AssetDatabase.LoadAssetAtPath<UdonSharpProgramAsset>(projectRelativeAssetPath) != null) { if (!EditorUtility.DisplayDialog("File already exists", $"Corresponding asset file '{projectRelativeAssetPath}' already found for new UdonSharp script. Overwrite?", "Ok", "Cancel")) { return null; } } } // Commit to creation from this point string fileContents = UdonSharpSettings.GetProgramTemplateString(sanitizedFileName); File.WriteAllText(scriptFilePath, fileContents, System.Text.Encoding.UTF8); AssetDatabase.ImportAsset(projectRelativeScriptPath, ImportAssetOptions.ForceSynchronousImport); if (createProgramAsset) { MonoScript newScript = AssetDatabase.LoadAssetAtPath<MonoScript>(projectRelativeScriptPath); UdonSharpProgramAsset newProgramAsset = CreateInstance<UdonSharpProgramAsset>(); newProgramAsset.sourceCsScript = newScript; AssetDatabase.CreateAsset(newProgramAsset, projectRelativeAssetPath); } AssetDatabase.Refresh(); return projectRelativeScriptPath; } return null; }
2
·
Bug Report
·
tracked
[3.7.5+] Parallel Import encounters null exception following migration from VRCSettings to VRCPackageSettings
With SDK version 3.7.5 several settings were migrated from the static class VRCSettings , existing within the VRCSDKBase-Editor.dll library provided alongside the SDK to VRCPackageSettings , the change also included a refactor of the class, introducing a static property Instance , used to get or create an instance of the class, an instance is attempted to be created by the PerceptualPostProcessor as DPID settings were part of the migration, however this fails because of a null exception: VRCPackageSettings.Instance.dpidMipmaps within PerceptualPostProcessor executes VRCPackageSettings.Instance_get VRCPackageSettings._instance is null so Create() is called, which calls Load() Load() and calls within it, including EnsurePathExists() expect GetPath() to not be null, causing a null exception when it is because GetPath() calls GetPathFromType(GetType()) which calls UnityEditor.PackageManager.PackageInfo.FindForAssembly(t.Assembly) and returns null when executed by a worker process, GetPathFromType then returns null (a comment assumes this would only occur when the SDK is not located within the Packages folder) but this execution path was seemingly never tested and so methods that expect valid strings such as Directory.CreateDirectory within EnsurePathExists() throw null exceptions. Simply resolving the null exceptions is not enough as the current implementation would cause Load() to not load any data when it's meant to, leading to VRCPackageSettings.Instance to contain default values when executed by worker processes ( AssetDatabase.IsAssetImportWorkerProcess() ), you cannot simply abort execution because that invalidates the use of Parallel Import and would cause textures marked as "dirty" to not actually be updated to have mipmaps re-generated, a proper solution leading to the same settings file must be implemented, the whole dependency on the assembly's package info seems extreme. This can be easily reproduced on any 3.7.5+ project with Parallel Import enabled (Project Settings -> Editor, mine is configured with 8 desired workers and 2 on standby) by enabling/disabling "Override Kaiser mipmapping" in the SDK settings.
1
·
Bug Report
·
tracked
ClientSim PlayerObject persistence writes invalid JSON for synced strings containing escaped quotes, causing DataToken.Error on the next Play Mode session
Unity: 2022.3.22f1 VRChat SDK - Worlds: 3.10.4 Title: ClientSim corrupts PlayerObject strings containing nested JSON Environment: Unity 2022.3.22f1 Worlds SDK 3.10.4 Reproduction: Add an Udon-synced string to a PlayerObject. Store JSON containing another serialized JSON string: {"outerKey":"[\"innerValue\"]"} Call RequestSerialization() and allow ClientSim to save the PlayerObject. Exit and enter Play Mode again. ClientSim fails while restoring the saved PlayerObject. ClientSim saves: "{\"outerKey\":\"[\\"innerValue\\"]\"}" It should save: "{\"outerKey\":\"[\\\"innerValue\\\"]\"}" The backslash preceding each nested quote is not escaped for the additional ClientSim JSON storage layer. The malformed value is loaded as a DataToken.Error, but ClientSim then accesses it as a DataDictionary in ClientSimNetworkIdHolder.Decode() line 180 As a result, the PlayerObject is not restored and all persistence stored in it appears lost. ClientSim may subsequently overwrite the file with empty/default data. The same nested JSON persistence seems to works correctly in the real VRChat client, so this appears to be specific to ClientSim’s local PlayerObject save/load implementation. Trace stack: InvalidOperationException: Attempted to access Error token as DataDictionary VRC.SDK3.Data .DataToken.get_DataDictionary () (at <8dae6d6858f2465fad961e5d8ef394cc>:0) VRC.SDK3.ClientSim.ClientSimNetworkIdHolder.Decode ( VRC.SDK3.Data .DataList data) (at ./Packages/com.vrchat.worlds/Integrations/ClientSim/Runtime/Networking/ClientSimNetworkIdHolder.cs:180) VRC.SDK3.ClientSim.ClientSimNetworkingView.Decode ( VRC.SDK3.Data .DataList data) (at ./Packages/com.vrchat.worlds/Integrations/ClientSim/Runtime/Networking/ClientSimNetworkingView.cs:95) VRC.SDK3.ClientSim.Persistence.ClientSimPlayerObjectStorage.Decode () (at ./Packages/com.vrchat.worlds/Integrations/ClientSim/Runtime/Player/PlayerPersistence/ClientSimPlayerObjectStorage.cs:165) VRC.SDK3.ClientSim.Persistence.ClientSimPlayerObjectStorage.OnPlayerJoined (VRC.SDK3.ClientSim.ClientSimOnPlayerJoinedEvent payload) (at ./Packages/com.vrchat.worlds/Integrations/ClientSim/Runtime/Player/PlayerPersistence/ClientSimPlayerObjectStorage.cs:102) VRC.SDK3.ClientSim.ClientSimEventDispatcher.SendEvent[T] (T clientSimEvent) (at ./Packages/com.vrchat.worlds/Integrations/ClientSim/Runtime/Events/ClientSimEventDispatcher.cs:62) VRC.SDK3.ClientSim.ClientSimPlayerManager.DispatchPlayerJoinedEvent (VRC.SDKBase.VRCPlayerApi player) (at ./Packages/com.vrchat.worlds/Integrations/ClientSim/Runtime/System/ClientSimPlayerManager.cs:137) VRC.SDK3.ClientSim.ClientSimPlayerManager.OnClientSimReady () (at ./Packages/com.vrchat.worlds/Integrations/ClientSim/Runtime/System/ClientSimPlayerManager.cs:129) VRC.SDK3.ClientSim.ClientSimMain+<InitializeClientSim>d__45.MoveNext () (at ./Packages/com.vrchat.worlds/Integrations/ClientSim/Runtime/System/ClientSimMain.cs:399) UnityEngine.SetupCoroutine.InvokeMoveNext (System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress) (at <cb81df0c49c643b1a04d9fc6ccca2433>:0)
1
·
Bug Report
·
tracked
VRCTween doesn't refresh duration in speed-based mode with ChangeEndValue()
When creating a tween with VRCTweenHandle.SetSpeedBased() , there is no way to call VRCTweenHandle.ChangeEndValue() and have the tween refresh its duration. This is due to the fact that internally dotween doesn't call Tween.DOStartupDurationBased() within Tween.DoChangeEndValue() unless a duration is specified - because VRCTween doesn't provide a duration, it calls it with -1, which means that it never calls the duration update. Additionally, because VRCTweenHandle.SetDuration() sets the duration directly via reflection, there is no chance for it to recalculate the tween, and VRCTweenHandle.SetSpeedBased() - and thus TweenSettingsExtensions.SetSpeedBased() - this only sets it so other hooks update their values, which means that the value is never propagated. This renders speed-based tween values useless for continuous motion. Sample code to prove it: class Blah : UdonSharpBehaviour { public float value; private VRCTweenHandle _handle; public void _FadeUp() { _TweenTo(1, 0.1f); } public void _FadeDown() { _TweenTo(0, 0.1f); } public void _TweenTo(float target, float speed) { if (_handle.IsActive) { _handle.ChangeEndValue(target, true) .SetDuration(speed) .SetSpeedBased(); } else { _handle = VRCTween.TweenFloat(value, target, speed, this, nameof(value), "_DummyCall", VRCTweenEase.Linear) .SetSpeedBased(); } } } If you trigger _FadeUp and _FadeDown, you will see that if the tween is not freshly created, it will result in it ignoring duration. No matter how you change the ChangeEndValue branch (aside from recalculating the values yourself) you will see it will never result in a consistent transition speed. SDK version is worlds 3.10.4, unity version 2022.3.22f1
1
·
Bug Report
·
tracked
Load More