From 333d4e8a95492bcabb5025e07a17ea1232896e0f Mon Sep 17 00:00:00 2001 From: bd_ Date: Thu, 3 Aug 2023 20:13:27 +0900 Subject: [PATCH] chore: fix perf issues with new asset saving logic --- .../EditModeTests/SerializationTests.meta | 3 + .../SerializationTests/Animation.anim | 53 ++ .../SerializationTests/Animation.anim.meta | 8 + .../SerializationTests/Controller.controller | 101 ++++ .../Controller.controller.meta | 8 + .../SerializationTests/SerializationTests.cs | 66 +++ .../SerializationTests.cs.meta | 3 + .../TestSerializationTraversal.prefab | 513 ++++++++++++++++++ .../TestSerializationTraversal.prefab.meta | 7 + .../Editor/BuildContext.cs | 87 +-- 10 files changed, 811 insertions(+), 38 deletions(-) create mode 100644 Assets/_ModularAvatar/EditModeTests/SerializationTests.meta create mode 100644 Assets/_ModularAvatar/EditModeTests/SerializationTests/Animation.anim create mode 100644 Assets/_ModularAvatar/EditModeTests/SerializationTests/Animation.anim.meta create mode 100644 Assets/_ModularAvatar/EditModeTests/SerializationTests/Controller.controller create mode 100644 Assets/_ModularAvatar/EditModeTests/SerializationTests/Controller.controller.meta create mode 100644 Assets/_ModularAvatar/EditModeTests/SerializationTests/SerializationTests.cs create mode 100644 Assets/_ModularAvatar/EditModeTests/SerializationTests/SerializationTests.cs.meta create mode 100644 Assets/_ModularAvatar/EditModeTests/SerializationTests/TestSerializationTraversal.prefab create mode 100644 Assets/_ModularAvatar/EditModeTests/SerializationTests/TestSerializationTraversal.prefab.meta diff --git a/Assets/_ModularAvatar/EditModeTests/SerializationTests.meta b/Assets/_ModularAvatar/EditModeTests/SerializationTests.meta new file mode 100644 index 00000000..5a831f37 --- /dev/null +++ b/Assets/_ModularAvatar/EditModeTests/SerializationTests.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: eb84ce2b801f4ebbad6a92bc870a1467 +timeCreated: 1691147043 \ No newline at end of file diff --git a/Assets/_ModularAvatar/EditModeTests/SerializationTests/Animation.anim b/Assets/_ModularAvatar/EditModeTests/SerializationTests/Animation.anim new file mode 100644 index 00000000..d02d23cd --- /dev/null +++ b/Assets/_ModularAvatar/EditModeTests/SerializationTests/Animation.anim @@ -0,0 +1,53 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!74 &7400000 +AnimationClip: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Animation + serializedVersion: 6 + m_Legacy: 0 + m_Compressed: 0 + m_UseHighQualityCurve: 1 + m_RotationCurves: [] + m_CompressedRotationCurves: [] + m_EulerCurves: [] + m_PositionCurves: [] + m_ScaleCurves: [] + m_FloatCurves: [] + m_PPtrCurves: [] + m_SampleRate: 60 + m_WrapMode: 0 + m_Bounds: + m_Center: {x: 0, y: 0, z: 0} + m_Extent: {x: 0, y: 0, z: 0} + m_ClipBindingConstant: + genericBindings: [] + pptrCurveMapping: [] + m_AnimationClipSettings: + serializedVersion: 2 + m_AdditiveReferencePoseClip: {fileID: 0} + m_AdditiveReferencePoseTime: 0 + m_StartTime: 0 + m_StopTime: 1 + m_OrientationOffsetY: 0 + m_Level: 0 + m_CycleOffset: 0 + m_HasAdditiveReferencePose: 0 + m_LoopTime: 0 + m_LoopBlend: 0 + m_LoopBlendOrientation: 0 + m_LoopBlendPositionY: 0 + m_LoopBlendPositionXZ: 0 + m_KeepOriginalOrientation: 0 + m_KeepOriginalPositionY: 1 + m_KeepOriginalPositionXZ: 0 + m_HeightFromFeet: 0 + m_Mirror: 0 + m_EditorCurves: [] + m_EulerEditorCurves: [] + m_HasGenericRootTransform: 0 + m_HasMotionFloatCurves: 0 + m_Events: [] diff --git a/Assets/_ModularAvatar/EditModeTests/SerializationTests/Animation.anim.meta b/Assets/_ModularAvatar/EditModeTests/SerializationTests/Animation.anim.meta new file mode 100644 index 00000000..0cac4f32 --- /dev/null +++ b/Assets/_ModularAvatar/EditModeTests/SerializationTests/Animation.anim.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3555aa63101ee6641b578d6eec4993d3 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 7400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/_ModularAvatar/EditModeTests/SerializationTests/Controller.controller b/Assets/_ModularAvatar/EditModeTests/SerializationTests/Controller.controller new file mode 100644 index 00000000..d1442e52 --- /dev/null +++ b/Assets/_ModularAvatar/EditModeTests/SerializationTests/Controller.controller @@ -0,0 +1,101 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!206 &-7586320810096879075 +BlendTree: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Blend Tree + m_Childs: + - serializedVersion: 2 + m_Motion: {fileID: 7400000, guid: 3555aa63101ee6641b578d6eec4993d3, type: 2} + m_Threshold: 0 + m_Position: {x: 0, y: 0} + m_TimeScale: 1 + m_CycleOffset: 0 + m_DirectBlendParameter: Blend + m_Mirror: 0 + m_BlendParameter: Blend + m_BlendParameterY: Blend + m_MinThreshold: 0 + m_MaxThreshold: 1 + m_UseAutomaticThresholds: 1 + m_NormalizedBlendValues: 0 + m_BlendType: 0 +--- !u!1102 &-4921136121750434117 +AnimatorState: + serializedVersion: 6 + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Blend Tree + m_Speed: 1 + m_CycleOffset: 0 + m_Transitions: [] + m_StateMachineBehaviours: [] + m_Position: {x: 50, y: 50, z: 0} + m_IKOnFeet: 0 + m_WriteDefaultValues: 1 + m_Mirror: 0 + m_SpeedParameterActive: 0 + m_MirrorParameterActive: 0 + m_CycleOffsetParameterActive: 0 + m_TimeParameterActive: 0 + m_Motion: {fileID: -7586320810096879075} + m_Tag: + m_SpeedParameter: + m_MirrorParameter: + m_CycleOffsetParameter: + m_TimeParameter: +--- !u!91 &9100000 +AnimatorController: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Controller + serializedVersion: 5 + m_AnimatorParameters: + - m_Name: Blend + m_Type: 1 + m_DefaultFloat: 0 + m_DefaultInt: 0 + m_DefaultBool: 0 + m_Controller: {fileID: 0} + m_AnimatorLayers: + - serializedVersion: 5 + m_Name: Base Layer + m_StateMachine: {fileID: 6228416413684685432} + m_Mask: {fileID: 0} + m_Motions: [] + m_Behaviours: [] + m_BlendingMode: 0 + m_SyncedLayerIndex: -1 + m_DefaultWeight: 0 + m_IKPass: 0 + m_SyncedLayerAffectsTiming: 0 + m_Controller: {fileID: 9100000} +--- !u!1107 &6228416413684685432 +AnimatorStateMachine: + serializedVersion: 6 + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Base Layer + m_ChildStates: + - serializedVersion: 1 + m_State: {fileID: -4921136121750434117} + m_Position: {x: 280, y: 190, z: 0} + m_ChildStateMachines: [] + m_AnyStateTransitions: [] + m_EntryTransitions: [] + m_StateMachineTransitions: {} + m_StateMachineBehaviours: [] + m_AnyStatePosition: {x: 50, y: 20, z: 0} + m_EntryPosition: {x: 50, y: 120, z: 0} + m_ExitPosition: {x: 800, y: 120, z: 0} + m_ParentStateMachinePosition: {x: 800, y: 20, z: 0} + m_DefaultState: {fileID: -4921136121750434117} diff --git a/Assets/_ModularAvatar/EditModeTests/SerializationTests/Controller.controller.meta b/Assets/_ModularAvatar/EditModeTests/SerializationTests/Controller.controller.meta new file mode 100644 index 00000000..524a0145 --- /dev/null +++ b/Assets/_ModularAvatar/EditModeTests/SerializationTests/Controller.controller.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2e7fa84316a0c33439fd03f8a47f27cd +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 9100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/_ModularAvatar/EditModeTests/SerializationTests/SerializationTests.cs b/Assets/_ModularAvatar/EditModeTests/SerializationTests/SerializationTests.cs new file mode 100644 index 00000000..1948d449 --- /dev/null +++ b/Assets/_ModularAvatar/EditModeTests/SerializationTests/SerializationTests.cs @@ -0,0 +1,66 @@ +using System.Linq; +using modular_avatar_tests; +using nadena.dev.modular_avatar.core; +using nadena.dev.modular_avatar.core.editor; +using NUnit.Framework; +using UnityEditor; +using UnityEditor.Animations; +using UnityEngine; +using VRC.SDK3.Avatars.Components; + +namespace _ModularAvatar.EditModeTests.SerializationTests +{ + public class SerializationTests : TestBase + { + [Test] + public void SerializationSavesAssetsRecursively() + { + var avatar = CreatePrefab("TestSerializationTraversal.prefab"); + + var originalAnimController = avatar.GetComponent().baseAnimationLayers + .First(l => l.animatorController != null) + .animatorController as AnimatorController; + + AvatarProcessor.ProcessAvatar(avatar); + + var avdesc = avatar.GetComponent(); + var animController = avdesc.baseAnimationLayers + .First(l => l.animatorController != null) + .animatorController as AnimatorController; + + Assert.AreNotEqual(originalAnimController, animController); + Assert.False(string.IsNullOrEmpty(AssetDatabase.GetAssetPath(animController))); + + AssertTempAsset(animController); + var stateMachine = animController.layers[0].stateMachine; + AssertTempAsset(stateMachine); + var state = stateMachine.states[0].state; + AssertTempAsset(state); + + // We might eventually optimize away rewriting clips that don't need changes, so just assert that they're + // saved + var blendTree = state.motion as BlendTree; + Assert.IsFalse(string.IsNullOrEmpty(AssetDatabase.GetAssetPath(blendTree))); + + var clip = blendTree.children[0].motion as AnimationClip; + Assert.IsFalse(string.IsNullOrEmpty(AssetDatabase.GetAssetPath(clip))); + + // Validate that the menu is saved + var menu = avdesc.expressionsMenu; + AssertTempAsset(menu); + AssertTempAsset(menu.controls[0].subMenu); + var parameters = avdesc.expressionParameters; + AssertTempAsset(parameters); + } + + + void AssertTempAsset(UnityEngine.Object obj) + { + var path = AssetDatabase.GetAssetPath(obj); + Assert.False(string.IsNullOrEmpty(path)); + + var mainAsset = AssetDatabase.LoadMainAssetAtPath(path); + Assert.IsInstanceOf(mainAsset); + } + } +} \ No newline at end of file diff --git a/Assets/_ModularAvatar/EditModeTests/SerializationTests/SerializationTests.cs.meta b/Assets/_ModularAvatar/EditModeTests/SerializationTests/SerializationTests.cs.meta new file mode 100644 index 00000000..9b3d1698 --- /dev/null +++ b/Assets/_ModularAvatar/EditModeTests/SerializationTests/SerializationTests.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: fec2299eef88489597f183983fd8961f +timeCreated: 1691147060 \ No newline at end of file diff --git a/Assets/_ModularAvatar/EditModeTests/SerializationTests/TestSerializationTraversal.prefab b/Assets/_ModularAvatar/EditModeTests/SerializationTests/TestSerializationTraversal.prefab new file mode 100644 index 00000000..2dc3e253 --- /dev/null +++ b/Assets/_ModularAvatar/EditModeTests/SerializationTests/TestSerializationTraversal.prefab @@ -0,0 +1,513 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &92866570714702294 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6186606167685701483} + - component: {fileID: 4634045538804780499} + m_Layer: 0 + m_Name: ConstraintReference + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &6186606167685701483 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 92866570714702294} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 6788302372926405977} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1773428102 &4634045538804780499 +ParentConstraint: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 92866570714702294} + m_Enabled: 1 + m_Weight: 1 + m_TranslationAtRest: {x: 0, y: 0, z: 0} + m_RotationAtRest: {x: 0, y: 0, z: 0} + m_TranslationOffsets: + - {x: 0, y: 0, z: 0} + m_RotationOffsets: + - {x: 0, y: 0, z: 0} + m_AffectTranslationX: 1 + m_AffectTranslationY: 1 + m_AffectTranslationZ: 1 + m_AffectRotationX: 1 + m_AffectRotationY: 1 + m_AffectRotationZ: 1 + m_IsContraintActive: 0 + m_IsLocked: 0 + m_Sources: + - sourceTransform: {fileID: 2212008645677311682} + weight: 1 +--- !u!1 &806545622753785384 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2212008645677311682} + - component: {fileID: 4424376654900210002} + - component: {fileID: 6373581450075928885} + m_Layer: 0 + m_Name: Menu + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2212008645677311682 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 806545622753785384} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 2684679302888174294} + m_Father: {fileID: 6788302372926405977} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &4424376654900210002 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 806545622753785384} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 7ef83cb0c23d4d7c9d41021e544a1978, type: 3} + m_Name: + m_EditorClassIdentifier: + menuToAppend: {fileID: 0} + installTargetMenu: {fileID: 0} +--- !u!114 &6373581450075928885 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 806545622753785384} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3b29d45007c5493d926d2cd45a489529, type: 3} + m_Name: + m_EditorClassIdentifier: + Control: + name: + icon: {fileID: 0} + type: 103 + parameter: + name: + value: 1 + style: 0 + subMenu: {fileID: 0} + subParameters: [] + labels: [] + MenuSource: 1 + menuSource_otherObjectChildren: {fileID: 0} + isSynced: 1 + isSaved: 1 +--- !u!1 &2272347755453238262 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6788302372926405977} + - component: {fileID: 1866562071556594017} + - component: {fileID: 8339718273392281678} + - component: {fileID: 6901588645704615622} + m_Layer: 0 + m_Name: TestSerializationTraversal + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &6788302372926405977 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2272347755453238262} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 3.7040002, y: -1.5267198, z: -7.534614} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 2212008645677311682} + - {fileID: 6186606167685701483} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1866562071556594017 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2272347755453238262} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 542108242, guid: 67cc4cb7839cd3741b63733d5adf0442, type: 3} + m_Name: + m_EditorClassIdentifier: + Name: + ViewPosition: {x: 0, y: 1.6, z: 0.2} + Animations: 0 + ScaleIPD: 1 + lipSync: 0 + lipSyncJawBone: {fileID: 0} + lipSyncJawClosed: {x: 0, y: 0, z: 0, w: 1} + lipSyncJawOpen: {x: 0, y: 0, z: 0, w: 1} + VisemeSkinnedMesh: {fileID: 0} + MouthOpenBlendShapeName: Facial_Blends.Jaw_Down + VisemeBlendShapes: [] + unityVersion: + portraitCameraPositionOffset: {x: 0, y: 0, z: 0} + portraitCameraRotationOffset: {x: 0, y: 1, z: 0, w: -0.00000004371139} + networkIDs: [] + customExpressions: 0 + expressionsMenu: {fileID: 0} + expressionParameters: {fileID: 0} + enableEyeLook: 0 + customEyeLookSettings: + eyeMovement: + confidence: 0.5 + excitement: 0.5 + leftEye: {fileID: 0} + rightEye: {fileID: 0} + eyesLookingStraight: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + eyesLookingUp: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + eyesLookingDown: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + eyesLookingLeft: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + eyesLookingRight: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + eyelidType: 0 + upperLeftEyelid: {fileID: 0} + upperRightEyelid: {fileID: 0} + lowerLeftEyelid: {fileID: 0} + lowerRightEyelid: {fileID: 0} + eyelidsDefault: + upper: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + lower: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + eyelidsClosed: + upper: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + lower: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + eyelidsLookingUp: + upper: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + lower: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + eyelidsLookingDown: + upper: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + lower: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + eyelidsSkinnedMesh: {fileID: 0} + eyelidsBlendshapes: + customizeAnimationLayers: 1 + baseAnimationLayers: + - isEnabled: 0 + type: 0 + animatorController: {fileID: 0} + mask: {fileID: 0} + isDefault: 1 + - isEnabled: 0 + type: 4 + animatorController: {fileID: 0} + mask: {fileID: 0} + isDefault: 1 + - isEnabled: 0 + type: 5 + animatorController: {fileID: 9100000, guid: 2e7fa84316a0c33439fd03f8a47f27cd, + type: 2} + mask: {fileID: 0} + isDefault: 0 + specialAnimationLayers: + - isEnabled: 0 + type: 6 + animatorController: {fileID: 0} + mask: {fileID: 0} + isDefault: 1 + - isEnabled: 0 + type: 7 + animatorController: {fileID: 0} + mask: {fileID: 0} + isDefault: 1 + - isEnabled: 0 + type: 8 + animatorController: {fileID: 0} + mask: {fileID: 0} + isDefault: 1 + AnimationPreset: {fileID: 0} + animationHashSet: [] + autoFootsteps: 1 + autoLocomotion: 1 + collider_head: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_torso: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_footR: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_footL: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_handR: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_handL: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_fingerIndexL: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_fingerMiddleL: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_fingerRingL: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_fingerLittleL: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_fingerIndexR: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_fingerMiddleR: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_fingerRingR: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_fingerLittleR: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} +--- !u!114 &8339718273392281678 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2272347755453238262} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -1427037861, guid: 4ecd63eff847044b68db9453ce219299, type: 3} + m_Name: + m_EditorClassIdentifier: + launchedFromSDKPipeline: 0 + completedSDKPipeline: 0 + blueprintId: + contentType: 0 + assetBundleUnityVersion: + fallbackStatus: 0 +--- !u!95 &6901588645704615622 +Animator: + serializedVersion: 3 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2272347755453238262} + m_Enabled: 1 + m_Avatar: {fileID: 0} + m_Controller: {fileID: 0} + m_CullingMode: 0 + m_UpdateMode: 0 + m_ApplyRootMotion: 0 + m_LinearVelocityBlending: 0 + m_WarningMessage: + m_HasTransformHierarchy: 1 + m_AllowConstantClipSamplingOptimization: 1 + m_KeepAnimatorControllerStateOnDisable: 0 +--- !u!1 &8069818621794346195 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2684679302888174294} + - component: {fileID: 1803761364175295593} + m_Layer: 0 + m_Name: test2 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2684679302888174294 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8069818621794346195} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 2212008645677311682} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1803761364175295593 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8069818621794346195} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3b29d45007c5493d926d2cd45a489529, type: 3} + m_Name: + m_EditorClassIdentifier: + Control: + name: + icon: {fileID: 0} + type: 101 + parameter: + name: + value: 1 + style: 0 + subMenu: {fileID: 0} + subParameters: [] + labels: [] + MenuSource: 0 + menuSource_otherObjectChildren: {fileID: 0} + isSynced: 1 + isSaved: 1 diff --git a/Assets/_ModularAvatar/EditModeTests/SerializationTests/TestSerializationTraversal.prefab.meta b/Assets/_ModularAvatar/EditModeTests/SerializationTests/TestSerializationTraversal.prefab.meta new file mode 100644 index 00000000..fc73269b --- /dev/null +++ b/Assets/_ModularAvatar/EditModeTests/SerializationTests/TestSerializationTraversal.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 08390c6d5634900488fda75e64ea0ddf +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/nadena.dev.modular-avatar/Editor/BuildContext.cs b/Packages/nadena.dev.modular-avatar/Editor/BuildContext.cs index 40d73d4d..47bc3db6 100644 --- a/Packages/nadena.dev.modular-avatar/Editor/BuildContext.cs +++ b/Packages/nadena.dev.modular-avatar/Editor/BuildContext.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using JetBrains.Annotations; using UnityEditor; using UnityEditor.Animations; using UnityEngine; @@ -151,57 +150,69 @@ namespace nadena.dev.modular_avatar.core.editor SaveImmediate = true; - void Walk(GameObject obj) + void Walk(GameObject root) { - sceneAssets.Add(obj); + var components = AvatarDescriptor.gameObject.GetComponentsInChildren(true); + Queue visitQueue = new Queue( + components.Where(t => (!(t is Transform))) + ); - foreach (var component in obj.GetComponents()) + while (visitQueue.Count > 0) { - sceneAssets.Add(component); - if (component is Transform t) + var current = visitQueue.Dequeue(); + if (referencedAssets.Contains(current)) continue; + referencedAssets.Add(current); + + // These assets have large internal arrays we don't want to walk through... + if (current is Mesh || current is AnimationClip || current is Texture) continue; + + var so = new SerializedObject(current); + var sp = so.GetIterator(); + bool enterChildren = true; + + while (sp.Next(enterChildren)) { - foreach (Transform child in t) + enterChildren = true; + if (sp.name == "m_GameObject") continue; + if (sp.propertyType == SerializedPropertyType.String) { - Walk(child.gameObject); + enterChildren = false; + continue; } - } - Queue visitQueue = new Queue(); - visitQueue.Enqueue(component); - - while (visitQueue.Count > 0) - { - var current = visitQueue.Dequeue(); - if (referencedAssets.Contains(current)) continue; - referencedAssets.Add(current); - - var so = new SerializedObject(current); - var sp = so.GetIterator(); - bool enterChildren = true; - - while (sp.Next(enterChildren)) + if (sp.isArray && IsPrimitiveArray(sp)) { - enterChildren = true; - if (sp.name == "m_GameObject") continue; - if (sp.propertyType == SerializedPropertyType.String) - { - enterChildren = false; - continue; - } + enterChildren = false; + } - if (sp.propertyType != SerializedPropertyType.ObjectReference) - { - continue; - } + if (sp.propertyType != SerializedPropertyType.ObjectReference) + { + continue; + } - if (sp.objectReferenceValue != null) - { - visitQueue.Enqueue(sp.objectReferenceValue); - } + var obj = sp.objectReferenceValue; + if (obj != null && !referencedAssets.Contains(obj) && !(obj is Transform) && + !(obj is GameObject)) + { + visitQueue.Enqueue(sp.objectReferenceValue); } } } } } + + private bool IsPrimitiveArray(SerializedProperty prop) + { + if (prop.arraySize == 0) return false; + var propertyType = prop.GetArrayElementAtIndex(0).propertyType; + switch (propertyType) + { + case SerializedPropertyType.Generic: + case SerializedPropertyType.ObjectReference: + return false; + default: + return true; + } + } } } \ No newline at end of file