From f84a6ccb730760d52270ad6fc329c59776cec69e Mon Sep 17 00:00:00 2001 From: ousttrue Date: Fri, 1 Dec 2023 17:06:31 +0900 Subject: [PATCH] fix GltfMeshUtility.WriteAssets --- .../Editor/MeshUtility/MeshUtilityDialog.cs | 130 +++++++----------- .../Editor/MeshUtility/PrefabContext.cs | 63 +++++++++ .../Editor/MeshUtility/PrefabContext.cs.meta | 11 ++ .../UniGLTF/Editor/MeshUtility/UndoContext.cs | 27 ++++ .../Editor/MeshUtility/UndoContext.cs.meta | 11 ++ .../Runtime/MeshUtility/BoneNormalizer.cs | 10 +- .../Runtime/MeshUtility/GltfMeshUtility.cs | 54 +++++--- .../Runtime/MeshUtility/MeshAttachInfo.cs | 42 ++++-- .../MeshUtility/MeshIntegrationResult.cs | 8 ++ .../Runtime/MeshUtility/MeshIntegrator.cs | 15 +- .../VrmMeshIntegratorWizard.cs | 28 ++++ .../SkinnedMeshUtility/VrmMeshUtility.cs | 17 ++- .../Runtime/MeshUtility/Vrm10MeshUtility.cs | 14 +- 13 files changed, 300 insertions(+), 130 deletions(-) create mode 100644 Assets/UniGLTF/Editor/MeshUtility/PrefabContext.cs create mode 100644 Assets/UniGLTF/Editor/MeshUtility/PrefabContext.cs.meta create mode 100644 Assets/UniGLTF/Editor/MeshUtility/UndoContext.cs create mode 100644 Assets/UniGLTF/Editor/MeshUtility/UndoContext.cs.meta diff --git a/Assets/UniGLTF/Editor/MeshUtility/MeshUtilityDialog.cs b/Assets/UniGLTF/Editor/MeshUtility/MeshUtilityDialog.cs index 332324a10..b06889160 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/MeshUtilityDialog.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/MeshUtilityDialog.cs @@ -3,7 +3,7 @@ using UnityEditor; using UniGLTF.M17N; using System.Collections.Generic; using System.Linq; -using System.IO; +using System; namespace UniGLTF.MeshUtility @@ -179,54 +179,50 @@ namespace UniGLTF.MeshUtility { /// [prefab] /// - /// * backup するのではなく 変更した copy を作成する。元は変えない - /// * copy 先の統合前の renderer を disable で残さず destroy する - /// * 実行すると mesh, blendshape, blendShape を新規に作成する - /// * 新しいヒエラルキーを prefab に保存してから削除して終了する - - // 出力フォルダを決める - var folder = "Assets"; - var prefab = _exportTarget.GetPrefab(); - if (prefab != null) + /// * prefab から instance を作る + /// * instance に対して 焼き付け, 統合, 分離 を実行する + /// * instance のヒエラルキーが改変され、mesh 等のアセットは改変版が作成される(元は変わらない) + /// * instance を asset に保存してから prefab を削除して終了する + /// + UnityPath assetFolder = default; + try { - folder = AssetDatabase.GetAssetPath(prefab); - // Debug.Log(folder); + assetFolder = PrefabContext.GetOutFolder(_exportTarget); } - // 新規で作成されるアセットはすべてこのフォルダの中に作る。上書きチェックはしない - var assetFolder = EditorUtility.SaveFolderPanel("select asset save folder", Path.GetDirectoryName(folder), "VrmIntegrated"); - var unityPath = UniGLTF.UnityPath.FromFullpath(assetFolder); - if (!unityPath.IsUnderWritableFolder) + catch (Exception) { EditorUtility.DisplayDialog("asset folder", "Target folder must be in the Assets or writable Packages folder", "cancel"); return; } - assetFolder = unityPath.Value; - var copy = GameObject.Instantiate(_exportTarget); - if (PrefabUtility.IsOutermostPrefabInstanceRoot(copy)) + using (var context = new PrefabContext(_exportTarget, assetFolder)) { - PrefabUtility.UnpackPrefabInstance(copy, PrefabUnpackMode.Completely, InteractionMode.AutomatedAction); + try + { + var (results, created) = MeshUtility.Process(_exportTarget, context.Instance); + + WriteAssets(context.Instance, context.AssetFolder, results); + } + catch (Exception ex) + { +#if DEBUG + Debug.LogException(ex, context.Instance); + context.Keep = true; +#endif + } } - - var (results, created) = MeshUtility.Process(_exportTarget, copy); - - WriteAssets(copy, assetFolder, results); - - // destroy scene - UnityEngine.Object.DestroyImmediate(copy); } else { - Undo.RegisterFullObjectHierarchyUndo(_exportTarget, "MeshUtility"); + using (var context = new UndoContext("MeshUtility", _exportTarget)) + { + var (results, created) = MeshUtility.Process(_exportTarget, null); - if (_exportTarget.GetPrefabType() == UnityExtensions.PrefabType.PrefabInstance) - { - PrefabUtility.UnpackPrefabInstance(_exportTarget, PrefabUnpackMode.Completely, InteractionMode.AutomatedAction); - } - var (results, created) = MeshUtility.Process(_exportTarget, null); - foreach (var go in created) - { - Undo.RegisterCreatedObjectUndo(go, "MeshUtility"); + foreach (var go in created) + { + // 処理後の mesh をアタッチした Renderer.gameobject + Undo.RegisterCreatedObjectUndo(go, "MeshUtility"); + } } } @@ -235,68 +231,36 @@ namespace UniGLTF.MeshUtility } } - void WriteAssets(GameObject copy, string assetFolder, List results) + /// + /// Write Mesh & Prefab + /// + protected virtual void WriteAssets(GameObject copy, string assetFolder, List results) { - // // write mesh asset foreach (var result in results) { - var childAssetPath = $"{assetFolder}/{result.Integrated.IntegratedRenderer.gameObject.name}{ASSET_SUFFIX}"; - Debug.LogFormat("CreateAsset: {0}", childAssetPath); - AssetDatabase.CreateAsset(result.Integrated.IntegratedRenderer.sharedMesh, childAssetPath); - } - - // 統合した結果をヒエラルキーに追加する - foreach (var result in results) - { - if (result.Integrated.IntegratedRenderer != null) + if (result.Integrated != null) { - result.Integrated.IntegratedRenderer.transform.SetParent(copy.transform, false); + var childAssetPath = $"{assetFolder}/{result.Integrated.IntegratedRenderer.gameObject.name}{ASSET_SUFFIX}"; + Debug.LogFormat("CreateAsset: {0}", childAssetPath); + AssetDatabase.CreateAsset(result.Integrated.IntegratedRenderer.sharedMesh, childAssetPath); + } + if (result.IntegratedNoBlendShape != null) + { + var childAssetPath = $"{assetFolder}/{result.IntegratedNoBlendShape.IntegratedRenderer.gameObject.name}{ASSET_SUFFIX}"; + Debug.LogFormat("CreateAsset: {0}", childAssetPath); + AssetDatabase.CreateAsset(result.IntegratedNoBlendShape.IntegratedRenderer.sharedMesh, childAssetPath); } } - // 統合した結果を反映した BlendShapeClip を作成して置き換える - // var clips = VRMMeshIntegratorUtility.FollowBlendshapeRendererChange(results, copy, assetFolder); - - // 用が済んだ 統合前 の renderer を削除する - foreach (var result in results) - { - foreach (var renderer in result.SourceMeshRenderers) - { - GameObject.DestroyImmediate(renderer); - } - foreach (var renderer in result.SourceSkinnedMeshRenderers) - { - GameObject.DestroyImmediate(renderer); - } - } - - // reset firstperson - // var firstperson = copy.GetComponent(); - // if (firstperson != null) - // { - // firstperson.Reset(); - // } - // prefab - var prefabPath = $"{assetFolder}/VrmIntegrated.prefab"; + var prefabPath = $"{assetFolder}/Integrated.prefab"; Debug.Log(prefabPath); PrefabUtility.SaveAsPrefabAsset(copy, prefabPath, out bool success); if (!success) { throw new System.Exception($"PrefabUtility.SaveAsPrefabAsset: {prefabPath}"); } - - // var prefabReference = AssetDatabase.LoadAssetAtPath(prefabPath); - // foreach (var clip in clips) - // { - // var so = new SerializedObject(clip); - // so.Update(); - // // clip.Prefab = copy; - // var prop = so.FindProperty("m_prefab"); - // prop.objectReferenceValue = prefabReference; - // so.ApplyModifiedProperties(); - // } } protected bool ToggleIsModified(string label, ref bool value) diff --git a/Assets/UniGLTF/Editor/MeshUtility/PrefabContext.cs b/Assets/UniGLTF/Editor/MeshUtility/PrefabContext.cs new file mode 100644 index 000000000..df80d3f3b --- /dev/null +++ b/Assets/UniGLTF/Editor/MeshUtility/PrefabContext.cs @@ -0,0 +1,63 @@ +using System; +using System.IO; +using UnityEditor; +using UnityEngine; + +namespace UniGLTF.MeshUtility +{ + // Instantiate + class PrefabContext : IDisposable + { + public readonly GameObject Instance; + + readonly UnityPath _assetFolder; + + public bool Keep = false; + + public string AssetFolder => _assetFolder.Value; + + public PrefabContext(GameObject prefab, UnityPath assetFolder) + { + this._assetFolder = assetFolder; + this.Instance = GameObject.Instantiate(prefab); + if (PrefabUtility.IsOutermostPrefabInstanceRoot(this.Instance)) + { + // どういう条件でここに来るかはよくわからない + PrefabUtility.UnpackPrefabInstance(this.Instance, PrefabUnpackMode.Completely, InteractionMode.AutomatedAction); + } + } + + // - Instance を Asset に書き出す + // - Instance を削除する + public void Dispose() + { + if (Keep) + { + // for debug + return; + } + UnityEngine.Object.DestroyImmediate(Instance); + } + + public static UnityPath GetOutFolder(GameObject _exportTarget) + { + // 出力フォルダを決める + var folder = "Assets"; + var prefab = _exportTarget.GetPrefab(); + if (prefab != null) + { + folder = AssetDatabase.GetAssetPath(prefab); + // Debug.Log(folder); + } + + // 新規で作成されるアセットはすべてこのフォルダの中に作る。上書きチェックはしない + var assetFolder = EditorUtility.SaveFolderPanel("select asset save folder", Path.GetDirectoryName(folder), "Integrated"); + var unityPath = UniGLTF.UnityPath.FromFullpath(assetFolder); + if (!unityPath.IsUnderWritableFolder) + { + throw new Exception("not in asset folder"); + } + return unityPath; + } + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Editor/MeshUtility/PrefabContext.cs.meta b/Assets/UniGLTF/Editor/MeshUtility/PrefabContext.cs.meta new file mode 100644 index 000000000..6cc2fba37 --- /dev/null +++ b/Assets/UniGLTF/Editor/MeshUtility/PrefabContext.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 948458ced6bcc904781eed04ebe7cd01 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UniGLTF/Editor/MeshUtility/UndoContext.cs b/Assets/UniGLTF/Editor/MeshUtility/UndoContext.cs new file mode 100644 index 000000000..eaf53f0f8 --- /dev/null +++ b/Assets/UniGLTF/Editor/MeshUtility/UndoContext.cs @@ -0,0 +1,27 @@ +using System; +using UnityEditor; +using UnityEngine; + +namespace UniGLTF.MeshUtility +{ + // Instantiate + class UndoContext : IDisposable + { + public UndoContext(string undoName, GameObject go) + { + Undo.RegisterFullObjectHierarchyUndo(go, undoName); + if (go.GetPrefabType() == UnityExtensions.PrefabType.PrefabInstance) + { + PrefabUtility.UnpackPrefabInstance(go, PrefabUnpackMode.Completely, InteractionMode.AutomatedAction); + } + } + + public void Dispose() + { + // 特に何もしない + // Undo すると元に戻ってしまう + + // TODO: あれば一時オブジェクトの破棄 + } + } +} diff --git a/Assets/UniGLTF/Editor/MeshUtility/UndoContext.cs.meta b/Assets/UniGLTF/Editor/MeshUtility/UndoContext.cs.meta new file mode 100644 index 000000000..bf4202411 --- /dev/null +++ b/Assets/UniGLTF/Editor/MeshUtility/UndoContext.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5019966789c0e094a8f58fc2734c9a35 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UniGLTF/Runtime/MeshUtility/BoneNormalizer.cs b/Assets/UniGLTF/Runtime/MeshUtility/BoneNormalizer.cs index e3db9e0c9..81be0e9ac 100644 --- a/Assets/UniGLTF/Runtime/MeshUtility/BoneNormalizer.cs +++ b/Assets/UniGLTF/Runtime/MeshUtility/BoneNormalizer.cs @@ -45,17 +45,11 @@ namespace UniGLTF.MeshUtility /// - /// 回転とスケールを除去したヒエラルキーのコピーを作成する(MeshをBakeする) + /// 各レンダラー(SkinnedMeshRenderer と MeshRenderer)にアタッチされた sharedMesh に対して + /// 回転とスケールを除去し、BlendShape の現状を焼き付けた版を作成する(まだ、アタッチしない) /// - /// 対象のヒエラルキーのルート - /// BlendShapeを0クリアするか否か。false の場合 BlendShape の現状を Bake する - /// Avatarを作る関数 - /// public static Dictionary NormalizeHierarchyFreezeMesh(GameObject go) { - // - // 各メッシュから回転・スケールを取り除いてBinding行列を再計算する - // var result = new Dictionary(); foreach (var src in go.transform.Traverse()) { diff --git a/Assets/UniGLTF/Runtime/MeshUtility/GltfMeshUtility.cs b/Assets/UniGLTF/Runtime/MeshUtility/GltfMeshUtility.cs index 0e4f8ebce..270876ccf 100644 --- a/Assets/UniGLTF/Runtime/MeshUtility/GltfMeshUtility.cs +++ b/Assets/UniGLTF/Runtime/MeshUtility/GltfMeshUtility.cs @@ -174,33 +174,40 @@ namespace UniGLTF.MeshUtility } } - public virtual (List, List) Process(GameObject go, GameObject instance) + public virtual (List, List) Process(GameObject _go, GameObject _instance) { + var target = _instance ?? _go; if (FreezeBlendShape || FreezeRotation || FreezeScaling) { // MeshをBakeする - var newMesh = BoneNormalizer.NormalizeHierarchyFreezeMesh(go); + var newMesh = BoneNormalizer.NormalizeHierarchyFreezeMesh(target); // - ヒエラルキーから回転・拡縮を除去する // - BakeされたMeshで置き換える // - bindPoses を再計算する - BoneNormalizer.Replace(go, newMesh, FreezeRotation, FreezeScaling); + BoneNormalizer.Replace(target, newMesh, FreezeRotation, FreezeScaling); } - var copy = CopyInstantiate(go, instance); + // prefab が instantiate されていた場合に + // Mesh統合設定を instantiate に置き換える + var groupCopy = CopyInstantiate(_go, _instance); var newList = new List(); - var empty = GetOrCreateEmpty(instance ?? go, "mesh"); + var empty = GetOrCreateEmpty(target, "mesh"); var results = new List(); - foreach (var group in copy) + foreach (var group in groupCopy) { - var (result, newGo) = Integrate(empty, group); - results.Add(result); - newList.AddRange(newGo); + if (TryIntegrate(empty, group, out var resultAndAdded)) + { + var (result, newGo) = resultAndAdded; + results.Add(result); + newList.AddRange(newGo); + } } + // // 用が済んだ 統合前 の renderer を削除する foreach (var result in results) { foreach (var r in result.SourceMeshRenderers) @@ -212,22 +219,37 @@ namespace UniGLTF.MeshUtility RemoveComponent(r); } } + // foreach (var result in results) + // { + // foreach (var renderer in result.SourceMeshRenderers) + // { + // GameObject.DestroyImmediate(renderer); + // } + // foreach (var renderer in result.SourceSkinnedMeshRenderers) + // { + // GameObject.DestroyImmediate(renderer); + // } + // } MeshIntegrationGroups.Clear(); return (results, newList); } - protected virtual (MeshIntegrationResult, GameObject[]) Integrate(GameObject empty, - MeshIntegrationGroup group) + protected virtual bool TryIntegrate(GameObject empty, + MeshIntegrationGroup group, out (MeshIntegrationResult, GameObject[]) resultAndAdded) { - var result = MeshIntegrator.Integrate(group, SplitByBlendShape + if (MeshIntegrator.TryIntegrate(group, SplitByBlendShape ? MeshIntegrator.BlendShapeOperation.Split - : MeshIntegrator.BlendShapeOperation.Use); + : MeshIntegrator.BlendShapeOperation.Use, out var result)) + { + var newGo = result.AddIntegratedRendererTo(empty).ToArray(); + resultAndAdded = (result, newGo); + return true; + } - var newGo = result.AddIntegratedRendererTo(empty).ToArray(); - - return (result, newGo); + resultAndAdded = default; + return false; } } } diff --git a/Assets/UniGLTF/Runtime/MeshUtility/MeshAttachInfo.cs b/Assets/UniGLTF/Runtime/MeshUtility/MeshAttachInfo.cs index 6684777c4..54f36ee4f 100644 --- a/Assets/UniGLTF/Runtime/MeshUtility/MeshAttachInfo.cs +++ b/Assets/UniGLTF/Runtime/MeshUtility/MeshAttachInfo.cs @@ -1,3 +1,4 @@ +using System; using System.Linq; using UnityEngine; @@ -11,23 +12,46 @@ namespace UniGLTF.MeshUtility public Transform RootBone; public void ReplaceMesh(GameObject dst) { + if (dst == null) + { + throw new ArgumentNullException(); + } + if (Bones != null) { // recalc bindposes Mesh.bindposes = Bones.Select(x => x.worldToLocalMatrix * dst.transform.localToWorldMatrix).ToArray(); - var dstRenderer = dst.GetComponent(); - dstRenderer.sharedMesh = Mesh; - dstRenderer.sharedMaterials = Materials; - dstRenderer.bones = Bones; - dstRenderer.rootBone = RootBone; + if (dst.GetComponent() is SkinnedMeshRenderer dstRenderer) + { + dstRenderer.sharedMesh = Mesh; + dstRenderer.sharedMaterials = Materials; + dstRenderer.bones = Bones; + dstRenderer.rootBone = RootBone; + } + else + { + Debug.LogError($"SkinnedMeshRenderer not found", dst); + } } else { - var dstFilter = dst.GetComponent(); - dstFilter.sharedMesh = Mesh; - var dstRenderer = dst.gameObject.AddComponent(); - dstRenderer.sharedMaterials = Materials; + if (dst.GetComponent() is MeshFilter dstFilter) + { + dstFilter.sharedMesh = Mesh; + if (dst.gameObject.GetComponent() is MeshRenderer dstRenderer) + { + dstRenderer.sharedMaterials = Materials; + } + else + { + Debug.LogError($"MeshRenderer not found", dst); + } + } + else + { + Debug.LogError($"MeshFilter not found", dst); + } } } } diff --git a/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegrationResult.cs b/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegrationResult.cs index 493ca7071..34b42df5a 100644 --- a/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegrationResult.cs +++ b/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegrationResult.cs @@ -48,16 +48,24 @@ namespace UniGLTF.MeshUtility public IEnumerable AddIntegratedRendererTo(GameObject parent) { + int count = 0; if (Integrated != null) { Integrated.AddIntegratedRendererTo(parent, Bones); + ++count; yield return Integrated.IntegratedRenderer.gameObject; } if (IntegratedNoBlendShape != null) { IntegratedNoBlendShape.AddIntegratedRendererTo(parent, Bones); + ++count; yield return IntegratedNoBlendShape.IntegratedRenderer.gameObject; } + + if (count == 0) + { + throw new NotImplementedException(); + } } } } diff --git a/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegrator.cs b/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegrator.cs index 9dd280350..6c3b26bb0 100644 --- a/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegrator.cs +++ b/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegrator.cs @@ -275,7 +275,8 @@ namespace UniGLTF.MeshUtility return found; } - public static MeshIntegrationResult Integrate(MeshIntegrationGroup group, BlendShapeOperation op) + public static bool TryIntegrate(MeshIntegrationGroup group, BlendShapeOperation op, + out MeshIntegrationResult result) { var integrator = new MeshUtility.MeshIntegrator(); foreach (var x in group.Renderers) @@ -289,7 +290,15 @@ namespace UniGLTF.MeshUtility integrator.Push(mr); } } - return integrator.Integrate(group.Name, op); + result = integrator.Integrate(group.Name, op); + if (result.Integrated != null || result.IntegratedNoBlendShape != null) + { + return true; + } + else + { + return false; + } } delegate bool TriangleFilter(int i0, int i1, int i2); @@ -351,7 +360,7 @@ namespace UniGLTF.MeshUtility return mesh; } - public MeshIntegrationResult Integrate(string name, BlendShapeOperation op) + MeshIntegrationResult Integrate(string name, BlendShapeOperation op) { if (_Bones.Count != _BindPoses.Count) { diff --git a/Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs b/Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs index ed590ef40..776cefccd 100644 --- a/Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs +++ b/Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs @@ -3,6 +3,8 @@ using UnityEditor; using UnityEngine; using UniGLTF.M17N; using UniGLTF; +using System.Collections.Generic; +using UniGLTF.MeshUtility; namespace VRM @@ -48,6 +50,32 @@ namespace VRM return firstPerson || mod; } + protected override void WriteAssets(GameObject copy, string assetFolder, List results) + { + base.WriteAssets(copy, assetFolder, results); + + // 統合した結果を反映した BlendShapeClip を作成して置き換える + // var clips = VRMMeshIntegratorUtility.FollowBlendshapeRendererChange(results, copy, assetFolder); + + // reset firstperson + // var firstperson = copy.GetComponent(); + // if (firstperson != null) + // { + // firstperson.Reset(); + // } + + // var prefabReference = AssetDatabase.LoadAssetAtPath(prefabPath); + // foreach (var clip in clips) + // { + // var so = new SerializedObject(clip); + // so.Update(); + // // clip.Prefab = copy; + // var prop = so.FindProperty("m_prefab"); + // prop.objectReferenceValue = prefabReference; + // so.ApplyModifiedProperties(); + // } + } + protected override void DialogMessage() { EditorGUILayout.HelpBox(Message.MESH_UTILITY.Msg(), MessageType.Info); diff --git a/Assets/VRM/Runtime/SkinnedMeshUtility/VrmMeshUtility.cs b/Assets/VRM/Runtime/SkinnedMeshUtility/VrmMeshUtility.cs index afb4d3f3d..161f0fddd 100644 --- a/Assets/VRM/Runtime/SkinnedMeshUtility/VrmMeshUtility.cs +++ b/Assets/VRM/Runtime/SkinnedMeshUtility/VrmMeshUtility.cs @@ -38,13 +38,19 @@ namespace VRM return copy; } - protected override - (UniGLTF.MeshUtility.MeshIntegrationResult, GameObject[]) Integrate( + protected override bool + TryIntegrate( GameObject empty, - UniGLTF.MeshUtility.MeshIntegrationGroup group) + UniGLTF.MeshUtility.MeshIntegrationGroup group, + out (UniGLTF.MeshUtility.MeshIntegrationResult, GameObject[]) resultAndAdded) { - var (result, newList) = base.Integrate(empty, group); + if (!base.TryIntegrate(empty, group, out resultAndAdded)) + { + resultAndAdded = default; + return false; + } + var (result, newGo) = resultAndAdded; if (_generateFirstPerson && group.Name == nameof(FirstPersonFlag.Auto)) { // Mesh 統合の後処理 @@ -62,8 +68,7 @@ namespace VRM _ProcessFirstPerson(_vrmInstance.FirstPersonBone, result.IntegratedNoBlendShape.IntegratedRenderer); } } - - return (result, newList); + return true; } private void _ProcessFirstPerson(Transform firstPersonBone, SkinnedMeshRenderer smr) diff --git a/Assets/VRM10/Runtime/MeshUtility/Vrm10MeshUtility.cs b/Assets/VRM10/Runtime/MeshUtility/Vrm10MeshUtility.cs index 15728a027..e9caabcef 100644 --- a/Assets/VRM10/Runtime/MeshUtility/Vrm10MeshUtility.cs +++ b/Assets/VRM10/Runtime/MeshUtility/Vrm10MeshUtility.cs @@ -39,11 +39,16 @@ namespace UniVRM10 } protected override - (UniGLTF.MeshUtility.MeshIntegrationResult, GameObject[]) Integrate( + bool TryIntegrate( GameObject empty, - UniGLTF.MeshUtility.MeshIntegrationGroup group) + UniGLTF.MeshUtility.MeshIntegrationGroup group, + out (UniGLTF.MeshUtility.MeshIntegrationResult, GameObject[]) resultAndAdded) { - var (result, newList) = base.Integrate(empty, group); + if (!base.TryIntegrate(empty, group, out resultAndAdded)) + { + return false; + } + var (result, newList) = resultAndAdded; if (_generateFirstPerson && group.Name == nameof(UniGLTF.Extensions.VRMC_vrm.FirstPersonType.auto)) { @@ -62,8 +67,7 @@ namespace UniVRM10 _ProcessFirstPerson(_vrmInstance.Humanoid.Head, result.IntegratedNoBlendShape.IntegratedRenderer); } } - - return (result, newList); + return true; } private void _ProcessFirstPerson(Transform firstPersonBone, SkinnedMeshRenderer smr)