From 176ac7edf600f684b574d83be54e0fb146f3d94e Mon Sep 17 00:00:00 2001 From: notargs Date: Thu, 26 Jun 2025 19:08:11 +0900 Subject: [PATCH 1/6] =?UTF-8?q?MaterialValueBindingMerger=E3=81=AB?= =?UTF-8?q?=E3=81=A4=E3=81=84=E3=81=A6=E3=80=81sharedMaterials=E3=81=A7?= =?UTF-8?q?=E3=81=AF=E3=81=AA=E3=81=8Fmaterials=E3=82=92=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E3=81=99=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Components/Expression/ExpressionMerger.cs | 10 ++++-- .../Expression/MaterialValueBindingMerger.cs | 36 +++++++++++++++---- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/Assets/VRM10/Runtime/Components/Expression/ExpressionMerger.cs b/Assets/VRM10/Runtime/Components/Expression/ExpressionMerger.cs index 791397b22..8fe59c146 100644 --- a/Assets/VRM10/Runtime/Components/Expression/ExpressionMerger.cs +++ b/Assets/VRM10/Runtime/Components/Expression/ExpressionMerger.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using UnityEngine; @@ -8,7 +9,7 @@ namespace UniVRM10 /// /// ブレンドシェイプを蓄えてまとめて適用するクラス /// - internal sealed class ExpressionMerger + internal sealed class ExpressionMerger : IDisposable { /// /// Key から Expression を得る @@ -74,5 +75,10 @@ namespace UniVRM10 { m_materialValueBindingMerger.RestoreMaterialInitialValues(); } + + public void Dispose() + { + m_materialValueBindingMerger.Dispose(); + } } } diff --git a/Assets/VRM10/Runtime/Components/Expression/MaterialValueBindingMerger.cs b/Assets/VRM10/Runtime/Components/Expression/MaterialValueBindingMerger.cs index 495ccfd90..ee1c75cd9 100644 --- a/Assets/VRM10/Runtime/Components/Expression/MaterialValueBindingMerger.cs +++ b/Assets/VRM10/Runtime/Components/Expression/MaterialValueBindingMerger.cs @@ -3,13 +3,14 @@ using System.Collections.Generic; using UniGLTF.Extensions.VRMC_vrm; using UnityEngine; using VRM10.MToon10; +using Object = UnityEngine.Object; namespace UniVRM10 { /// /// Base + (A.Target - Base) * A.Weight + (B.Target - Base) * B.Weight ... /// - internal sealed class MaterialValueBindingMerger + internal sealed class MaterialValueBindingMerger : IDisposable { private static readonly string COLOR_PROPERTY = MToon10Prop.BaseColorFactor.ToUnityShaderLabName(); private static readonly string EMISSION_COLOR_PROPERTY = MToon10Prop.EmissiveFactor.ToUnityShaderLabName(); @@ -18,6 +19,8 @@ namespace UniVRM10 private static readonly string SHADE_COLOR_PROPERTY = MToon10Prop.ShadeColorFactor.ToUnityShaderLabName(); private static readonly string MATCAP_COLOR_PROPERTY = MToon10Prop.MatcapColorFactor.ToUnityShaderLabName(); + private readonly HashSet _clonedMaterials = new(); + public static string GetProperty(MaterialColorType bindType) { switch (bindType) @@ -55,12 +58,24 @@ namespace UniVRM10 Dictionary materialNameMap = new Dictionary(); foreach (var renderer in root.GetComponentsInChildren()) { - foreach (var material in renderer.sharedMaterials) + // VFXRendererなど、Materialが設定できないRendererが存在する + if (renderer is not SkinnedMeshRenderer && renderer is not MeshRenderer) continue; + + var sharedMaterials = renderer.sharedMaterials; + var materials = renderer.materials; + for (var i = 0; i < materials.Length; i++) { - if (material != null && !materialNameMap.ContainsKey(material.name)) - { - materialNameMap.Add(material.name, material); - } + var sharedMaterial = sharedMaterials[i]; + var material = materials[i]; + + if (!sharedMaterial || !material) continue; + + // 複製されたマテリアルはこのクラス内で破棄 + if (sharedMaterial != material) _clonedMaterials.Add(material); + + // 複製前の名前を記録しておく + // なお、Vrm10Runtimeのインスタンスが作られるより先にユーザーによってMaterialが複製されるパターンは想定しない + materialNameMap.TryAdd(sharedMaterial.name, material); } } @@ -288,5 +303,14 @@ namespace UniVRM10 { InitializeMaterialMap(clipMap, root); } + + public void Dispose() + { + foreach (var clonedMaterial in _clonedMaterials) + { + Object.Destroy(clonedMaterial); + } + _clonedMaterials.Clear(); + } } } From 3dd21ea35440a4d68b2c9d6b5d615e521107b117 Mon Sep 17 00:00:00 2001 From: notargs Date: Thu, 26 Jun 2025 19:15:17 +0900 Subject: [PATCH 2/6] =?UTF-8?q?Dispose=E3=82=92=E8=BF=BD=E8=A8=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Runtime/Components/Vrm10Runtime/Vrm10RuntimeExpression.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeExpression.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeExpression.cs index 1a4f747ce..62603029d 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeExpression.cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeExpression.cs @@ -56,6 +56,9 @@ namespace UniVRM10 _eyeDirectionApplicable?.Restore(); _eyeDirectionApplicable = null; + + _merger?.Dispose(); + _merger = null; } internal void Process(LookAtEyeDirection inputEyeDirection) From 70c0c40fb80099891fc1aabdcd3db28bb0b3067b Mon Sep 17 00:00:00 2001 From: notargs Date: Thu, 26 Jun 2025 21:05:07 +0900 Subject: [PATCH 3/6] =?UTF-8?q?TODO=E3=82=92=E8=BF=BD=E8=A8=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/UniGLTF/Runtime/UniGLTF/RuntimeGltfInstance.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Assets/UniGLTF/Runtime/UniGLTF/RuntimeGltfInstance.cs b/Assets/UniGLTF/Runtime/UniGLTF/RuntimeGltfInstance.cs index 79f7d94c1..b2a28cc5a 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/RuntimeGltfInstance.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/RuntimeGltfInstance.cs @@ -9,6 +9,10 @@ namespace UniGLTF /// ImporterContext の Load 結果の GltfModel /// /// Runtime でモデルを Destory したときに関連リソース(Texture, Material...などの UnityEngine.Object)を自動的に Destroy する。 + /// + /// TODO: Editor Importの場合でも一瞬だけこのクラスのインスタンスが生じるが、すぐDestroyImmediateされる + /// Editorでも利用されている以上、名前・責務が良くないので見直したい。 + /// /// public class RuntimeGltfInstance : MonoBehaviour, IResponsibilityForDestroyObjects { From 21155c332fb66da67c342e2fdd270be054d18ddb Mon Sep 17 00:00:00 2001 From: notargs Date: Thu, 26 Jun 2025 21:23:16 +0900 Subject: [PATCH 4/6] =?UTF-8?q?RuntimeImport=E3=81=AE=E9=9A=9B=E3=81=AFmat?= =?UTF-8?q?erial=E3=82=92=E8=A4=87=E8=A3=BD=E3=81=97=E3=81=AA=E3=81=84?= =?UTF-8?q?=E3=82=88=E3=81=86=E3=81=AB=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../GltfScriptedImporterBase.cs | 2 +- .../Components/Expression/ExpressionMerger.cs | 4 +- .../Expression/MaterialValueBindingMerger.cs | 45 ++++++++++++------- .../Components/Vrm10Instance/Vrm10Instance.cs | 5 ++- .../Components/Vrm10Runtime/Vrm10Runtime.cs | 4 +- .../Vrm10Runtime/Vrm10RuntimeExpression.cs | 4 +- 6 files changed, 41 insertions(+), 23 deletions(-) diff --git a/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/GltfScriptedImporterBase.cs b/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/GltfScriptedImporterBase.cs index d7588cbcf..83dd81993 100644 --- a/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/GltfScriptedImporterBase.cs +++ b/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/GltfScriptedImporterBase.cs @@ -61,7 +61,7 @@ namespace UniGLTF context.AddObjectToAsset(k.Name, o); }); var root = loaded.Root; - GameObject.DestroyImmediate(loaded); + DestroyImmediate(loaded); context.AddObjectToAsset(root.name, root); context.SetMainObject(root); diff --git a/Assets/VRM10/Runtime/Components/Expression/ExpressionMerger.cs b/Assets/VRM10/Runtime/Components/Expression/ExpressionMerger.cs index 8fe59c146..e178df0c5 100644 --- a/Assets/VRM10/Runtime/Components/Expression/ExpressionMerger.cs +++ b/Assets/VRM10/Runtime/Components/Expression/ExpressionMerger.cs @@ -25,7 +25,7 @@ namespace UniVRM10 MaterialValueBindingMerger m_materialValueBindingMerger; - public ExpressionMerger(VRM10ObjectExpression expressions, Transform root) + public ExpressionMerger(VRM10ObjectExpression expressions, Transform root, bool isPrefabInstance) { m_clipMap = expressions.Clips.ToDictionary( x => expressions.CreateKey(x.Clip), @@ -34,7 +34,7 @@ namespace UniVRM10 ); m_valueMap = new Dictionary(ExpressionKey.Comparer); m_morphTargetBindingMerger = new MorphTargetBindingMerger(m_clipMap, root); - m_materialValueBindingMerger = new MaterialValueBindingMerger(m_clipMap, root); + m_materialValueBindingMerger = new MaterialValueBindingMerger(m_clipMap, root, isPrefabInstance); } /// diff --git a/Assets/VRM10/Runtime/Components/Expression/MaterialValueBindingMerger.cs b/Assets/VRM10/Runtime/Components/Expression/MaterialValueBindingMerger.cs index ee1c75cd9..d754cffe0 100644 --- a/Assets/VRM10/Runtime/Components/Expression/MaterialValueBindingMerger.cs +++ b/Assets/VRM10/Runtime/Components/Expression/MaterialValueBindingMerger.cs @@ -53,29 +53,44 @@ namespace UniVRM10 /// Dictionary m_materialMap = new Dictionary(); - void InitializeMaterialMap(Dictionary clipMap, Transform root) + void InitializeMaterialMap(Dictionary clipMap, Transform root, bool isPrefabInstance) { - Dictionary materialNameMap = new Dictionary(); + var materialNameMap = new Dictionary(); foreach (var renderer in root.GetComponentsInChildren()) { // VFXRendererなど、Materialが設定できないRendererが存在する if (renderer is not SkinnedMeshRenderer && renderer is not MeshRenderer) continue; - var sharedMaterials = renderer.sharedMaterials; - var materials = renderer.materials; - for (var i = 0; i < materials.Length; i++) + if (isPrefabInstance) { - var sharedMaterial = sharedMaterials[i]; - var material = materials[i]; + // EditorImportされたPrefabのInstanceとして生成されている場合、Materialを複製する + var sharedMaterials = renderer.sharedMaterials; + var materials = renderer.materials; + for (var i = 0; i < materials.Length; i++) + { + var sharedMaterial = sharedMaterials[i]; + var material = materials[i]; - if (!sharedMaterial || !material) continue; + if (!sharedMaterial || !material) continue; - // 複製されたマテリアルはこのクラス内で破棄 - if (sharedMaterial != material) _clonedMaterials.Add(material); + // 複製されたマテリアルはこのクラス内で破棄 + if (sharedMaterial != material) _clonedMaterials.Add(material); - // 複製前の名前を記録しておく - // なお、Vrm10Runtimeのインスタンスが作られるより先にユーザーによってMaterialが複製されるパターンは想定しない - materialNameMap.TryAdd(sharedMaterial.name, material); + // 複製前の名前を記録しておく + // なお、Vrm10Runtimeのインスタンスが作られるより先にユーザーによってMaterialが複製されるパターンは想定しない + materialNameMap.TryAdd(sharedMaterial.name, material); + } + } + else + { + // PrefabのInstanceでない(RuntimeImportされている)ならMaterialは複製しない + foreach (var material in renderer.sharedMaterials) + { + if (material) + { + materialNameMap.TryAdd(material.name, material); + } + } } } @@ -299,9 +314,9 @@ namespace UniVRM10 } #endregion - public MaterialValueBindingMerger(Dictionary clipMap, Transform root) + public MaterialValueBindingMerger(Dictionary clipMap, Transform root, bool isPrefabInstance) { - InitializeMaterialMap(clipMap, root); + InitializeMaterialMap(clipMap, root, isPrefabInstance); } public void Dispose() diff --git a/Assets/VRM10/Runtime/Components/Vrm10Instance/Vrm10Instance.cs b/Assets/VRM10/Runtime/Components/Vrm10Instance/Vrm10Instance.cs index f27be9aea..5b4d46531 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Instance/Vrm10Instance.cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Instance/Vrm10Instance.cs @@ -141,8 +141,11 @@ namespace UniVRM10 } var initPose = RuntimeGltfInstance.SafeGetInitialPose(transform); + + // NOTE: RuntimeGltfInstanceがないかどうかでPrefabのインスタンスであるか(EditorImportされているか)が判別できる + var isPrefabInstance = !GetComponent(); - return new Vrm10Runtime(this, useControlRig, m_springBoneRuntime, initPose); + return new Vrm10Runtime(this, useControlRig, m_springBoneRuntime, initPose, isPrefabInstance); } public Vrm10Runtime Runtime diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs index c6e8661e2..5a800d2e1 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs @@ -52,7 +52,7 @@ namespace UniVRM10 IReadOnlyDictionary _initPose; public Vrm10Runtime(Vrm10Instance instance, bool useControlRig, IVrm10SpringBoneRuntime springBoneRuntime, - IReadOnlyDictionary initPose) + IReadOnlyDictionary initPose, bool isPrefabInstance) { if (!Application.isPlaying) { @@ -77,7 +77,7 @@ namespace UniVRM10 } Constraints = instance.GetComponentsInChildren(); LookAt = new Vrm10RuntimeLookAt(instance, instance.Humanoid, ControlRig); - Expression = new Vrm10RuntimeExpression(instance, LookAt.EyeDirectionApplicable); + Expression = new Vrm10RuntimeExpression(instance, LookAt.EyeDirectionApplicable, isPrefabInstance); SpringBone = springBoneRuntime; } diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeExpression.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeExpression.cs index 62603029d..902654f35 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeExpression.cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeExpression.cs @@ -23,9 +23,9 @@ namespace UniVRM10 public float LookAtOverrideRate { get; private set; } public float MouthOverrideRate { get; private set; } - internal Vrm10RuntimeExpression(Vrm10Instance target, ILookAtEyeDirectionApplicable eyeDirectionApplicable) + internal Vrm10RuntimeExpression(Vrm10Instance target, ILookAtEyeDirectionApplicable eyeDirectionApplicable, bool isPrefabInstance) { - _merger = new ExpressionMerger(target.Vrm.Expression, target.transform); + _merger = new ExpressionMerger(target.Vrm.Expression, target.transform, isPrefabInstance); _keys = target.Vrm.Expression.Clips .Select(x => target.Vrm.Expression.CreateKey(x.Clip)) .ToList(); From 498fb59e1cb5833d08b505da4cfe7c0845b1e180 Mon Sep 17 00:00:00 2001 From: notargs Date: Thu, 26 Jun 2025 21:26:14 +0900 Subject: [PATCH 5/6] =?UTF-8?q?=E3=82=B3=E3=83=A1=E3=83=B3=E3=83=88?= =?UTF-8?q?=E3=82=92=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/UniGLTF/Runtime/UniGLTF/RuntimeGltfInstance.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Assets/UniGLTF/Runtime/UniGLTF/RuntimeGltfInstance.cs b/Assets/UniGLTF/Runtime/UniGLTF/RuntimeGltfInstance.cs index b2a28cc5a..6f4374687 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/RuntimeGltfInstance.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/RuntimeGltfInstance.cs @@ -10,7 +10,7 @@ namespace UniGLTF /// /// Runtime でモデルを Destory したときに関連リソース(Texture, Material...などの UnityEngine.Object)を自動的に Destroy する。 /// - /// TODO: Editor Importの場合でも一瞬だけこのクラスのインスタンスが生じるが、すぐDestroyImmediateされる + /// TODO: Editor Importの場合でも一瞬だけこのクラスのインスタンスが生じるが、すぐDestroyImmediateされるため、それらを区別する用途に使うことができる /// Editorでも利用されている以上、名前・責務が良くないので見直したい。 /// /// From a5042629d7ea871dbe6ecd4b8c9c6467e453e3d3 Mon Sep 17 00:00:00 2001 From: notargs Date: Thu, 26 Jun 2025 21:42:45 +0900 Subject: [PATCH 6/6] =?UTF-8?q?=E5=90=8D=E5=89=8D=E3=82=92=E6=8F=83?= =?UTF-8?q?=E3=81=88=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Components/Expression/MaterialValueBindingMerger.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Assets/VRM10/Runtime/Components/Expression/MaterialValueBindingMerger.cs b/Assets/VRM10/Runtime/Components/Expression/MaterialValueBindingMerger.cs index d754cffe0..665b2b611 100644 --- a/Assets/VRM10/Runtime/Components/Expression/MaterialValueBindingMerger.cs +++ b/Assets/VRM10/Runtime/Components/Expression/MaterialValueBindingMerger.cs @@ -76,8 +76,9 @@ namespace UniVRM10 // 複製されたマテリアルはこのクラス内で破棄 if (sharedMaterial != material) _clonedMaterials.Add(material); - // 複製前の名前を記録しておく + // 複製前の名前に揃え、それを記録しておく // なお、Vrm10Runtimeのインスタンスが作られるより先にユーザーによってMaterialが複製されるパターンは想定しない + material.name = sharedMaterial.name; materialNameMap.TryAdd(sharedMaterial.name, material); } }