Restore compatibility with legacy unitypackage VRCSDKs

If this breaks again I probably won't fix it.
This commit is contained in:
bd_ 2022-11-26 12:56:32 -08:00
parent 25729dc81b
commit 0dd571e371
8 changed files with 78 additions and 44 deletions

View File

@ -23,13 +23,13 @@
*/
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Reflection;
using UnityEditor;
using UnityEngine;
using VRC.SDK3.Avatars.Components;
using VRC.SDK3.Editor;
using VRC.SDKBase.Editor.BuildPipeline;
using VRC.SDKBase.Validation.Performance.Stats;
using Object = UnityEngine.Object;
namespace nadena.dev.modular_avatar.core.editor
@ -139,14 +139,57 @@ namespace nadena.dev.modular_avatar.core.editor
}
}
// The VRCSDK captures some debug information about animators as part of the build process, prior to invoking
// hooks. For some reason this happens in the ValidateFeatures call on the SDK builder. Reinvoke it to
// refresh this debug info.
var avatar = avatarGameObject.GetComponent<VRCAvatarDescriptor>();
var animator = avatarGameObject.GetComponent<Animator>();
var builder = new VRCSdkControlPanelAvatarBuilder3A();
builder.RegisterBuilder(ScriptableObject.CreateInstance<VRCSdkControlPanel>());
builder.ValidateFeatures(avatar, animator, new AvatarPerformanceStats(false));
FixupAnimatorDebugData(avatarGameObject);
}
[SuppressMessage("ReSharper", "PossibleNullReferenceException")]
private static void FixupAnimatorDebugData(GameObject avatarGameObject)
{
Object tempControlPanel = null;
try
{
// The VRCSDK captures some debug information about animators as part of the build process, prior to invoking
// hooks. For some reason this happens in the ValidateFeatures call on the SDK builder. Reinvoke it to
// refresh this debug info.
//
// All of these methods are public, but for compatibility with unitypackage-based SDKs, we need to use
// reflection to invoke everything here, as the asmdef structure is different between the two SDK variants.
// Bleh.
//
// Canny filed requesting that this processing move after build hooks:
// https://feedback.vrchat.com/sdk-bug-reports/p/animator-debug-information-needs-to-be-captured-after-invoking-preprocess-avatar
var ty_VRCSdkControlPanelAvatarBuilder3A = Util.FindType(
"VRC.SDK3.Editor.VRCSdkControlPanelAvatarBuilder3A"
);
var ty_AvatarPerformanceStats = Util.FindType(
"VRC.SDKBase.Validation.Performance.Stats.AvatarPerformanceStats"
);
var ty_VRCSdkControlPanel = Util.FindType("VRCSdkControlPanel");
tempControlPanel = ScriptableObject.CreateInstance(ty_VRCSdkControlPanel) as Object;
var avatar = avatarGameObject.GetComponent<VRCAvatarDescriptor>();
var animator = avatarGameObject.GetComponent<Animator>();
var builder = ty_VRCSdkControlPanelAvatarBuilder3A.GetConstructor(Type.EmptyTypes)
.Invoke(Array.Empty<object>());
var perfStats = ty_AvatarPerformanceStats.GetConstructor(new[] {typeof(bool)})
.Invoke(new object[] {false});
ty_VRCSdkControlPanelAvatarBuilder3A
.GetMethod("RegisterBuilder", BindingFlags.Public | BindingFlags.Instance)
.Invoke(builder, new object[] {tempControlPanel});
ty_VRCSdkControlPanelAvatarBuilder3A.GetMethod("ValidateFeatures").Invoke(
builder, new object[] {avatar, animator, perfStats}
);
}
catch (Exception e)
{
Debug.LogWarning(
"[ModularAvatar] Incompatible VRCSDK version; failed to regenerate animator debug data");
Debug.LogException(e);
}
finally
{
if (tempControlPanel != null) Object.DestroyImmediate(tempControlPanel);
}
}
}
}

View File

@ -57,7 +57,7 @@ namespace nadena.dev.modular_avatar.core.editor
// side-effect) causes the list to be initially cached. This call will throw a NPE because we're passing
// a null GameObject, but that's okay.
var avatarValidation = FindType("VRC.SDK3.Validation.AvatarValidation");
var avatarValidation = Util.FindType("VRC.SDK3.Validation.AvatarValidation");
var findIllegalComponents =
avatarValidation?.GetMethod("FindIllegalComponents", BindingFlags.Public | BindingFlags.Static);
@ -86,7 +86,7 @@ namespace nadena.dev.modular_avatar.core.editor
}
// Now fetch the cached allowlist and add our components to it.
var validationUtils = FindType("VRC.SDKBase.Validation.ValidationUtils");
var validationUtils = Util.FindType("VRC.SDKBase.Validation.ValidationUtils");
var whitelistedTypes = validationUtils?.GetMethod(
"WhitelistedTypes",
BindingFlags.Public | BindingFlags.Static,
@ -124,20 +124,5 @@ namespace nadena.dev.modular_avatar.core.editor
}
}
}
private static Type FindType(string typeName)
{
Type avatarValidation = null;
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
avatarValidation = assembly.GetType(typeName);
if (avatarValidation != null)
{
break;
}
}
return avatarValidation;
}
}
}

View File

@ -22,11 +22,13 @@
* SOFTWARE.
*/
using System;
using System.Reflection;
using JetBrains.Annotations;
using UnityEditor;
using UnityEditor.Animations;
using UnityEngine;
using VRC.SDKBase.Editor.BuildPipeline;
using Object = UnityEngine.Object;
namespace nadena.dev.modular_avatar.core.editor
{
@ -121,5 +123,20 @@ namespace nadena.dev.modular_avatar.core.editor
return path != null && path.StartsWith(GetGeneratedAssetsFolder() + "/");
}
public static Type FindType(string typeName)
{
Type avatarValidation = null;
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
avatarValidation = assembly.GetType(typeName);
if (avatarValidation != null)
{
break;
}
}
return avatarValidation;
}
}
}

View File

@ -2,9 +2,7 @@
"name": "nadena.dev.modular-avatar.core.editor",
"references": [
"GUID:fc900867c0f47cd49b6e2ae4ef907300",
"GUID:5718fb738711cd34ea54e9553040911d",
"GUID:6e9c6119ac4eb334284fb7b4bc6d1f05",
"GUID:b906909fcc54f634db50f2cad0f988d9"
"GUID:5718fb738711cd34ea54e9553040911d"
],
"includePlatforms": [
"Editor"

View File

@ -12,6 +12,7 @@
"url": "",
"repo": "https://vpm.nadena.dev/vpm.json",
"dependencies": {
"com.unity.nuget.newtonsoft-json": "2.0.0"
},
"vpmDependencies": {
"com.vrchat.base": "3.1.9",

View File

@ -145,7 +145,9 @@
"version": "file:nadena.dev.modular-avatar",
"depth": 0,
"source": "embedded",
"dependencies": {}
"dependencies": {
"com.unity.nuget.newtonsoft-json": "2.0.0"
}
},
"com.unity.modules.ai": {
"version": "1.0.0",

View File

@ -19,12 +19,6 @@ be made prior to version 1.0. As such, it is not recommended to distribute prefa
:::
:::caution
Modular Avatar is currently only compatible with installations of the VRCSDK that use the VRChat Creator Companion.
:::
To install Modular Avatar, download and import the `unitypackage` file from the "Assets" section on [the latest release](https://github.com/bdunderscore/modular-avatar/releases).
Then, check out one of the tutorials below:

View File

@ -16,12 +16,6 @@ Modular Avatarは開発途中であり、まだ本格運用が非推奨です。
:::
:::caution
現在、Modular AvatarはVRChat Creator Companionを使ったVRCSDKのインストールのみに対応しています。
:::
Modular Avatarをインストールするには、[最新リリース]のAssets項目から`unitypackage`ファイルをダウンロードして、インポートしてください。
その後の手順に関しては以下のチュートリアルを見てください