diff --git a/CHANGELOG.md b/CHANGELOG.md index 01a1d454..49794b06 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - [#257] Proxy renderers no longer appear in the hierarchy. +- [#260] [ChilloutVR] Fix: Build fails due to CVRAvatar preventing recreation of Animator (contributed by @hai-vr) ### Changed diff --git a/Editor/ApplyOnPlay.cs b/Editor/ApplyOnPlay.cs index 8c708a87..83a82608 100644 --- a/Editor/ApplyOnPlay.cs +++ b/Editor/ApplyOnPlay.cs @@ -27,6 +27,7 @@ #region using System; +using System.Collections.Generic; using System.Linq; using nadena.dev.ndmf.config; using nadena.dev.ndmf.runtime; @@ -135,19 +136,56 @@ private static void RecreateAnimators(Transform avatar) var tmpAnimator = tmpObject.AddComponent(); bool enabled = animator.enabled; + // Support components that need to be destroyed before the Animator is destroyed, + // such as ChilloutVR's CVRAvatar component. + var tmpComponentsRequiringAnimator = new List(); + foreach (var componentRequiringAnimator in FindSiblingComponentsRequiringAnimator(animator)) + { + var tmpComponentRequiringAnimator = tmpObject.AddComponent(componentRequiringAnimator.GetType()); + tmpComponentsRequiringAnimator.Add(tmpComponentRequiringAnimator); + EditorUtility.CopySerialized(componentRequiringAnimator, tmpComponentRequiringAnimator); + // Destroy this first before destroying the Animator below. + UnityObject.DestroyImmediate(componentRequiringAnimator); + } + EditorUtility.CopySerialized(animator, tmpAnimator); UnityObject.DestroyImmediate(animator); var newAnimator = obj.AddComponent(); newAnimator.enabled = false; EditorUtility.CopySerialized(tmpAnimator, newAnimator); newAnimator.enabled = enabled; + + foreach (var tmpComponentRequiringAnimator in tmpComponentsRequiringAnimator) + { + var newComponent = obj.AddComponent(tmpComponentRequiringAnimator.GetType()); + EditorUtility.CopySerialized(tmpComponentRequiringAnimator, newComponent); + // Even in the temporary object, destroy this first before destroying the Animator below. + UnityObject.DestroyImmediate(tmpComponentRequiringAnimator); + } UnityObject.DestroyImmediate(tmpAnimator); } UnityObject.DestroyImmediate(tmpObject); } - + + private static IEnumerable FindSiblingComponentsRequiringAnimator(Animator animator) + { + return animator.GetComponents() + // GetComponents may return null elements on unloaded MonoBehaviour scripts + .Where(component => component != null) + .Where(component => + { + var requiresAnimator = component.GetType() + .GetCustomAttributes(typeof(RequireComponent), true) + .Cast() + .Any(requireComponent => requireComponent.m_Type0 == typeof(Animator) + || requireComponent.m_Type1 == typeof(Animator) + || requireComponent.m_Type2 == typeof(Animator)); + return requiresAnimator; + }); + } + private static void OnPlayModeStateChanged(PlayModeStateChange obj) { if (obj == PlayModeStateChange.EnteredPlayMode)