From 4ee2036b1cf78c14934cf74e5d5ca982b3a7b7b7 Mon Sep 17 00:00:00 2001 From: d4rkc0d3r <1735522+d4rkc0d3r@users.noreply.github.com> Date: Fri, 2 Aug 2024 16:00:26 +0200 Subject: [PATCH] Fix crash with missing scripts on the avatar. --- CHANGELOG.md | 1 + Editor/ExtensionMethods.cs | 26 +++++++++++++++++++++++++- Editor/d4rkAvatarOptimizer.cs | 14 +++++++------- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8374542..993426b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## v3.7.4 ### Bug Fixes * Fix viseme blendshapes and eyelid blendshapes sometimes not getting reassigned correctly if they aren't on a mesh named `Body`. +* Fix crash with missing scripts on the avatar. ## v3.7.3 ### Bug Fixes diff --git a/Editor/ExtensionMethods.cs b/Editor/ExtensionMethods.cs index e3f4fd9..9bd486a 100644 --- a/Editor/ExtensionMethods.cs +++ b/Editor/ExtensionMethods.cs @@ -83,11 +83,35 @@ public static IEnumerable GetAllDescendants(this Transform transform) } } } + + public static Component[] GetNonNullComponents(this Transform transform) + { + var components = transform.GetComponents(); + if (components.All(c => c != null)) + { + return components; + } + var path = new List(); + var current = transform; + while (current != null) + { + path.Add(current.name); + current = current.parent; + } + string pathString = string.Join("/", path.Reverse()); + var nonNullComponents = components.Where(c => c != null).ToArray(); + Debug.LogWarning($"Found {components.Length - nonNullComponents.Length} null components on {pathString}. You might be missing some scripts."); + return nonNullComponents; + } + + public static Component[] GetNonNullComponents(this GameObject gameObject) + { + return gameObject.transform.GetNonNullComponents(); + } } public static class AnimatorControllerExtensions { - public static IEnumerable EnumerateAllStates(this AnimatorController controller) { var queue = new Queue(); diff --git a/Editor/d4rkAvatarOptimizer.cs b/Editor/d4rkAvatarOptimizer.cs index 7707795..f8835c3 100644 --- a/Editor/d4rkAvatarOptimizer.cs +++ b/Editor/d4rkAvatarOptimizer.cs @@ -1111,7 +1111,7 @@ private void DeleteAllUnusedSkinnedMeshRenderers() { var obj = skinnedMeshRenderer.gameObject; DestroyImmediate(skinnedMeshRenderer); - if (!keepTransforms.Contains(obj.transform) && (obj.transform.childCount == 0 && obj.GetComponents().Length == 1)) + if (!keepTransforms.Contains(obj.transform) && (obj.transform.childCount == 0 && obj.GetNonNullComponents().Length == 1)) DestroyImmediate(obj); } } @@ -1287,7 +1287,7 @@ public bool IsAnimatableBinding(EditorCurveBinding binding) { } } animatableBindings.Add(("ComponentExists", typeof(GameObject))); - foreach (var component in targetObject.GetComponents()) { + foreach (var component in targetObject.GetNonNullComponents()) { animatableBindings.Add(("ComponentExists", component.GetType())); } if (targetObject.TryGetComponent(out VRCStation station)) { @@ -2003,7 +2003,7 @@ bool IsPossibleBinding(EditorCurveBinding binding) { // AnimationUtility.GetAnimatableBindings(transform.gameObject, gameObject) // is too slow, so we just check if the components mentioned in the bindings exist at that path - possibleTypeNames.UnionWith(transform.GetComponents().Select(c => c.GetType().FullName)); + possibleTypeNames.UnionWith(transform.GetNonNullComponents().Select(c => c.GetType().FullName)); possibleTypeNames.Add(typeof(GameObject).FullName); } possibleBindingTypes[binding.path] = possibleTypeNames; @@ -2224,7 +2224,7 @@ void AddDependency(Transform t, Object obj) { result[physBone].UnionWith(dependencies); } - result[physBone].UnionWith(current.GetComponents().Where(c => c != physBone && !(c is Transform))); + result[physBone].UnionWith(current.GetNonNullComponents().Where(c => c != physBone && !(c is Transform))); } } @@ -2774,7 +2774,7 @@ public HashSet FindAllUnusedComponents() .Where(r => !behaviourToggles.Contains(GetPathToRoot(r)))); alwaysDisabledBehaviours.UnionWith(FindAllAlwaysDisabledGameObjects() - .SelectMany(t => t.GetComponents().Where(c => c != null && !(c is Transform)))); + .SelectMany(t => t.GetNonNullComponents().Where(c => !(c is Transform)))); var exclusions = GetAllExcludedTransforms(); @@ -4643,7 +4643,7 @@ string CalculateNewBlendShapeName(string blendShapeName) { { var obj = combinableSkinnedMeshes[meshID].gameObject; DestroyImmediate(combinableSkinnedMeshes[meshID]); - if (!keepTransforms.Contains(obj.transform) && (obj.transform.childCount == 0 && obj.GetComponents().Length == 1)) + if (!keepTransforms.Contains(obj.transform) && (obj.transform.childCount == 0 && obj.GetNonNullComponents().Length == 1)) DestroyImmediate(obj); } @@ -4834,7 +4834,7 @@ private void DestroyUnusedGameObjects() foreach (var obj in transform.GetAllDescendants()) { - if (obj.GetComponents().Length > 1) + if (obj.GetNonNullComponents().Length > 1) { used.Add(obj); }