diff --git a/Assets/VRM/Editor/Format/VRMEditorExporter.cs b/Assets/VRM/Editor/Format/VRMEditorExporter.cs index 74bc3a710..f727df52f 100644 --- a/Assets/VRM/Editor/Format/VRMEditorExporter.cs +++ b/Assets/VRM/Editor/Format/VRMEditorExporter.cs @@ -199,12 +199,10 @@ namespace VRM } } - // 正規化 if (settings.PoseFreeze) { - // BoneNormalizer.Execute は Copy を作って正規化する。UNDO無用 - target = VRMBoneNormalizer.Execute(target, settings.ForceTPose); - destroy.Add(target); + // 正規化 + VRMBoneNormalizer.Execute(target, settings.ForceTPose); } var fp = target.GetComponent(); diff --git a/Assets/VRM/Editor/Format/VRMHumanoidNormalizerMenu.cs b/Assets/VRM/Editor/Format/VRMHumanoidNormalizerMenu.cs index 47c8665ff..777de6e79 100644 --- a/Assets/VRM/Editor/Format/VRMHumanoidNormalizerMenu.cs +++ b/Assets/VRM/Editor/Format/VRMHumanoidNormalizerMenu.cs @@ -46,8 +46,7 @@ namespace VRM { var go = Selection.activeObject as GameObject; - // BoneNormalizer.Execute はコピーを正規化する。UNDO無用 - Selection.activeGameObject = VRMBoneNormalizer.Execute(go, true); + VRMBoneNormalizer.Execute(go, true); } } } diff --git a/Assets/VRM/Runtime/SkinnedMeshUtility/VRMBoneNormalizer.cs b/Assets/VRM/Runtime/SkinnedMeshUtility/VRMBoneNormalizer.cs index 81f630c52..7f1a25d14 100644 --- a/Assets/VRM/Runtime/SkinnedMeshUtility/VRMBoneNormalizer.cs +++ b/Assets/VRM/Runtime/SkinnedMeshUtility/VRMBoneNormalizer.cs @@ -41,17 +41,26 @@ namespace VRM /// /// モデルの正規化を実行する + /// + /// v0.115 ヒエラルキーのコピーをしなくまりました(仕様変更) + /// v0.116 Animator.avatar 代入の副作用回避修正 + /// + /// v0.114以前: 非破壊 + /// - return コピーされて正規化されたヒエラルキー + /// v0.115以降: 対象のヒエラルキーが正規化されます。 + /// - Transform が変更されます。 + /// - Animator.avatar が差し替えられます。 + /// - SkinnedMeshRenderer.sharedMesh が差し替えられます。 + /// - MeshFilter.sharedMesh が差し替えられます。 + /// - return void /// /// 対象モデルのルート /// 強制的にT-Pose化するか - /// 正規化済みのモデル - public static GameObject Execute(GameObject go, bool forceTPose) + public static void Execute(GameObject go, bool forceTPose) { - // - // T-Poseにする - // if (forceTPose) { + // T-Poseにする var hips = go.GetComponent().GetBoneTransform(HumanBodyBones.Hips); var hipsPosition = hips.position; var hipsRotation = hips.rotation; @@ -66,19 +75,30 @@ namespace VRM } } - // Meshの焼きこみ - var newMesh = BoneNormalizer.NormalizeHierarchyFreezeMesh(go, true); - // 焼いたMeshで置き換える - BoneNormalizer.Replace(go, newMesh, true, true); + // Transform の回転とスケールを Mesh に適用します。 + // - 回転とスケールが反映された新しい Mesh が作成されます + // - Transform の回転とスケールはクリアされます。world position を維持します。 + var newMeshMap = BoneNormalizer.NormalizeHierarchyFreezeMesh(go, true); - // 新しいヒエラルキーからAvatarを作る - var newAnimator = go.GetComponent(); - var newAvatar = UniHumanoid.AvatarDescription.RecreateAvatar(newAnimator); - newAnimator.avatar = newAvatar; + // SkinnedMeshRenderer.sharedMesh と MeshFilter.sharedMesh を新しいMeshで置き換える + BoneNormalizer.Replace(go, newMeshMap, true, true); - // CopyVRMComponents(go, normalized, bMap); + // 回転とスケールが除去された新しいヒエラルキーからAvatarを作る + var animator = go.GetComponent(); + var newAvatar = UniHumanoid.AvatarDescription.RecreateAvatar(animator); - return go; + // Animator.avatar を代入したときに副作用でTransformが変更されるのを回避するために削除します。 + if (Application.isPlaying) + { + GameObject.Destroy(animator); + } + else + { + GameObject.DestroyImmediate(animator); + } + animator = go.AddComponent(); + + animator.avatar = newAvatar; } /// diff --git a/Assets/VRM_Samples/RuntimeExporterSample/VRMRuntimeExporter.cs b/Assets/VRM_Samples/RuntimeExporterSample/VRMRuntimeExporter.cs index 3d396b37b..7eaf769bc 100644 --- a/Assets/VRM_Samples/RuntimeExporterSample/VRMRuntimeExporter.cs +++ b/Assets/VRM_Samples/RuntimeExporterSample/VRMRuntimeExporter.cs @@ -141,17 +141,9 @@ namespace VRM.RuntimeExporterSample static byte[] ExportCustom(GameObject exportRoot, bool forceTPose = false) { // normalize - var target = VRMBoneNormalizer.Execute(exportRoot, forceTPose); + VRMBoneNormalizer.Execute(exportRoot, forceTPose); - try - { - return ExportSimple(target); - } - finally - { - // cleanup - GameObject.Destroy(target); - } + return ExportSimple(exportRoot); } void OnExported(UniGLTF.glTF vrm)